error after running node2nix:
node:fs:562
return binding.open(
^
Error: ENOENT: no such file or directory, open 'package.json'
at Object.openSync (node:fs:562:18)
at Object.readFileSync (node:fs:446:35)
at Object.npmToNix (/nix/store/w2s44ll9wl5k8ncdqyrbgvmyd1dj6p6w-node2nix-1.11.0/lib/node_modules/node2nix/lib/node2nix.js:46:29)
at Object.<anonymous> (/nix/store/w2s44ll9wl5k8ncdqyrbgvmyd1dj6p6w-node2nix-1.11.0/lib/node_modules/node2nix/bin/node2nix.js:296:10)
at Module._compile (node:internal/modules/cjs/loader:1554:14)
at Object..js (node:internal/modules/cjs/loader:1706:10)
at Module.load (node:internal/modules/cjs/loader:1289:32)
at Function._load (node:internal/modules/cjs/loader:1108:12)
at TracingChannel.traceSync (node:diagnostics_channel:322:14)
at wrapModuleLoad (node:internal/modules/cjs/loader:220:24) {
errno: -2,
code: 'ENOENT',
syscall: 'open',
path: 'package.json'
}
The error is correct, assets/package.json doesn’t exist
Are there any commands I (or nix) should be running?
> tree assets
assets
├── css
│ └── app.css
├── js
│ └── app.js
├── tailwind.config.js
└── vendor
└── topbar.js
These commands I’ve used
echo "use flake" > .envrc
echo ".direnv/" >> .gitignore
mix archive.install hex phx_new
mix phx.new . --module Proj --app proj
# Modify dev.exs by adding the db's port below the hostname:
sed -i '/hostname: "/a \ \ port: 5433,' config/dev.exs
# START POSTGREQL
pg-start
#
mix deps.get
# Then configure your database in config/dev.exs and run:
mix ecto.create
# You can also run your app inside IEx (Interactive Elixir) as:
iex -S mix phx.server
cd assets
node2nix --development
flake.nix
{
description = "General Elixir Project Flake 20250516";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
flake-utils.url = "github:numtide/flake-utils";
};
outputs =
{
self,
nixpkgs,
flake-utils,
}:
flake-utils.lib.eachDefaultSystem (
system:
let
pname = "proj";
version = "0.0.1";
pkgs = nixpkgs.legacyPackages.${system};
## Define Erlang with ODBC support
erlang = pkgs.beam.interpreters.erlang_27.override {
odbcSupport = true;
};
## Create a custom beam package set using our ODBC-enabled Erlang
erlangPackages = pkgs.beam.packagesWith erlang;
## Now we can create Elixir using our custom beam packages
elixir = erlangPackages.elixir_1_18;
nodejs = pkgs.nodejs_24;
postgresql = pkgs.postgresql_17;
# LANG = "C.UTF-8";
LANG = "en_US.UTF-8";
root = ./.;
in
{
formatter = pkgs.nixpkgs-fmt;
## mix2nix is a cli tool available in nixpkgs. it will generate a nix expression from a mix.lock file. It is quite standard in the 2nix tool series.
# nix run nixpkgs#mix2nix -- > mix_deps.nix
# cd assets
# nix run nixpkgs#node2nix -- --development
packages =
let
src = ./.;
mixNixDeps = with pkgs; import ./mix_deps.nix { inherit lib beamPackages; };
nodeDependencies = (pkgs.callPackage ./assets/default.nix { }).shell.nodeDependencies;
in
{
default = erlangPackages.mixRelease {
inherit
src
pname
version
mixNixDeps
;
postBuild = ''
ln -sf ${nodeDependencies}/lib/node_modules assets/node_modules
npm run deploy --prefix ./assets
# for external task you need a workaround for the no deps check flag
# https://github.com/phoenixframework/phoenix/issues/2690
mix do deps.loadpaths --no-deps-check, phx.digest
mix phx.digest --no-deps-check
'';
};
};
devShells.default = pkgs.mkShell {
inherit LANG;
PGPORT = "5433"; # default 5432
# enable IEx shell history
ERL_AFLAGS = "-kernel shell_history enabled";
# # In IEX: `open Enum.map`
# ELIXIR_EDITOR = "code --goto __FILE__:__LINE__";
## phoenix related env vars
POOL_SIZE = 15;
# DB_URL = "postgresql://postgres:postgres@localhost:5432/db";
PORT = 4000;
MIX_ENV = "dev";
## add your project env vars here, word readable in the nix store.
# ENV_VAR = "your_env_var";
##########################################################
# Without this, almost everything fails with locale issues when
# using `nix-shell --pure` (at least on NixOS).
# See
# + https://github.com/NixOS/nix/issues/318#issuecomment-52986702
# + http://lists.linuxfromscratch.org/pipermail/lfs-support/2004-June/023900.html
##########################################################
LOCALE_ARCHIVE =
if pkgs.stdenv.isLinux then "${pkgs.glibcLocales}/lib/locale/locale-archive" else "";
buildInputs =
[
pkgs.unixODBC
pkgs.psqlodbc
elixir
nodejs
postgresql
pkgs.git
pkgs.pgcli
pkgs.glibcLocales
pkgs.gnumake
pkgs.gcc
## Testing
pkgs.chromedriver
## Deploy tools
pkgs.flyctl # fly.io
# pkgs.gigalixir
pkgs.mix2nix
# Used for frontend dependencies, you are free to use yarn2nix as well
pkgs.nodePackages.node2nix
# Formatting .js file
pkgs.nodePackages.prettier
pkgs.elixir_ls # Elixir
pkgs.nixpkgs-fmt
# codespell --skip="./deps/*,./.git/*,./assets/*,./erl_crash.dump" -w
pkgs.codespell
# dot -Tpng ecto_erd.dot -o erd.png
pkgs.graphviz
(pkgs.writeShellScriptBin "pg-stop" ''
pg_ctl -D $PGDATA -U postgres stop
'')
(pkgs.writeShellScriptBin "pg-reset" ''
rm -rf $PGDATA
'')
(pkgs.writeShellScriptBin "pg-setup" ''
####################################################################
# If database is not initialized (i.e., $PGDATA directory does not
# exist), then set it up. Seems superfluous given the cleanup step
# above, but handy when one gets to force reboot the iron.
####################################################################
if ! test -d $PGDATA; then
######################################################
# Init PostgreSQL
######################################################
pg_ctl initdb -D $PGDATA
#### initdb --locale=C --encoding=UTF8 --auth-local=peer --auth-host=scram-sha-256 > /dev/null || exit
# initdb --encoding=UTF8 --no-locale --no-instructions -U postgres
######################################################
# PORT ALREADY IN USE
######################################################
# If another `nix-shell` is running with a PostgreSQL
# instance, the logs will show complaints that the
# default port 5432 is already in use. Edit the line
# below with a different port number, uncomment it,
# and try again.
######################################################
if [[ "$PGPORT" ]]; then
sed -i "s|^#port.*$|port = $PGPORT|" $PGDATA/postgresql.conf
fi
echo "listen_addresses = ${"'"}${"'"}" >> $PGDATA/postgresql.conf
echo "unix_socket_directories = '$PGDATA'" >> $PGDATA/postgresql.conf
echo "CREATE USER postgres WITH PASSWORD 'postgres' CREATEDB SUPERUSER;" | postgres --single -E postgres
fi
'')
(pkgs.writeShellScriptBin "pg-start" ''
## # Postgres Fallback using docker
## docker run -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -p 5432:5432 postgres:14
[ ! -d $PGDATA ] && pg-setup
####################################################################
# Start PostgreSQL
# ==================================================================
# Setting all necessary configuration options via `pg_ctl` (which
# is basically a wrapper around `postgres`) instead of editing
# `postgresql.conf` directly with `sed`. See docs:
#
# + https://www.postgresql.org/docs/current/app-pg-ctl.html
# + https://www.postgresql.org/docs/current/app-postgres.html
#
# See more on the caveats at
# https://discourse.nixos.org/t/how-to-configure-postgresql-declaratively-nixos-and-non-nixos/4063/1
# but recapping out of paranoia:
#
# > use `SHOW` commands to check the options because `postgres -C`
# > "_returns values from postgresql.conf_" (which is not changed by
# > supplying the configuration options on the command line) and
# > "_it does not reflect parameters supplied when the cluster was
# > started._"
#
# OPTION SUMMARY
# --------------------------------------------------------------------
#
# + `unix_socket_directories`
#
# > PostgreSQL will attempt to create a pidfile in
# > `/run/postgresql` by default, but it will fail as it
# > doesn't exist. By changing the configuration option
# > below, it will get created in $PGDATA.
#
# + `listen_addresses`
#
# > In tandem with edits in `pg_hba.conf` (see
# > `HOST_COMMON` below), it configures PostgreSQL to
# > allow remote connections (otherwise only `localhost`
# > will get authenticated and the rest of the traffic
# > discarded).
# >
# > NOTE: the edit to `pga_hba.conf` needs to come
# > **before** `pg_ctl start` (or the service
# > needs to be restarted otherwise), because then
# > the changes are not being reloaded.
# >
# > More info on setting up and troubleshooting remote
# > PosgreSQL connections (these are all mirrors of the
# > same text; again, paranoia):
# >
# > + https://stackoverflow.com/questions/24504680/connect-to-postgres-server-on-google-compute-engine
# > + https://stackoverflow.com/questions/47794979/connecting-to-postgres-server-on-google-compute-engine
# > + https://medium.com/scientific-breakthrough-of-the-afternoon/configure-postgresql-to-allow-remote-connections-af5a1a392a38
# > + https://gist.github.com/toraritte/f8c7fe001365c50294adfe8509080201#file-configure-postgres-to-allow-remote-connection-md
HOST_COMMON="host\s\+all\s\+all"
sed -i "s|^$HOST_COMMON.*127.*$|host all all 0.0.0.0/0 trust|" $PGDATA/pg_hba.conf
sed -i "s|^$HOST_COMMON.*::1.*$|host all all ::/0 trust|" $PGDATA/pg_hba.conf
# + `log*`
#
# > Setting up basic logging, to see remote connections
# > for example.
# >
# > See the docs for more:
# > https://www.postgresql.org/docs/current/runtime-config-logging.html
pg_ctl \
-D $PGDATA \
-l $PGDATA/postgres.log \
-o "-c unix_socket_directories='$PGDATA'" \
-o "-c listen_addresses='*'" \
-o "-c log_destination='stderr'" \
-o "-c logging_collector=on" \
-o "-c log_directory='log'" \
-o "-c log_filename='postgresql-%Y-%m-%d_%H%M%S.log'" \
-o "-c log_min_messages=info" \
-o "-c log_min_error_statement=info" \
-o "-c log_connections=on" \
start
'')
(pkgs.writeShellScriptBin "pg-console" ''
psql --host $PGDATA -U postgres
'')
(pkgs.writeShellScriptBin "pg-mix-setup" ''
# ####/################################################################
# # Install Node.js dependencies if not done yet.
# ####################################################################
# if test -d "$PWD/assets/" && ! test -d "$PWD/assets/node_modules/"; then
# (cd assets && npm install)
# fi
####################################################################
# If $MIX_HOME doesn't exist, set it up.
####################################################################
if ! test -d $MIX_HOME; then
######################################################
# ... but first, test whether there is a `_backup`
# directory. Had issues with installing Hex on NixOS,
# and Hex and Phoenix can be copied from there, just
# in case.
######################################################
if test -d "$PWD/_backup"; then
cp -r _backup/.mix .nix-shell/
else
######################################################
# Install Hex and Phoenix via the network
######################################################
yes | ${elixir}/bin/mix local.hex
# Install Phoenix
# yes | ${elixir}/bin/mix archive.install hex phx_new
#TODO:Go to stable whenever it's released
yes | ${elixir}/bin/mix archive.install hex phx_new 1.7.0-rc.0
fi
fi
if test -f "mix.exs"; then
# These are not in the `if` section above, because of
# the `hex` install glitch, it could be that there is
# already a `$MIX_HOME` folder. See 2019-08-05_0553
${elixir}/bin/mix deps.get
######################################################
# `ecto.setup` is defined in `mix.exs` by default when
# Phoenix project is generated via `mix phx.new`.
# It does `ecto.create`, `ecto.migrate`, and run
# `priv/seeds`.
######################################################
${elixir}/bin/mix ecto.setup
fi
'')
(pkgs.writeShellScriptBin "update" ''
nix flake update --commit-lock-file && ${elixir}/bin/mix deps.update --all && ${elixir}/bin/mix deps.get && ${elixir}/bin/mix compile
'')
(pkgs.writeShellScriptBin "check-formatted" ''
cd ${root}
echo " > CHECKING nix formatting"
${pkgs.nixpkgs-fmt}/bin/nixpkgs-fmt *.nix --check
echo " > CHECKING mix formatting"
${elixir}/bin/mix format --check-formatted
'')
]
++ pkgs.lib.optional pkgs.stdenv.isLinux pkgs.libnotify # For ExUnit Notifier on Linux.
++ pkgs.lib.optional pkgs.stdenv.isLinux pkgs.inotify-tools # For file_system on Linux.
++ pkgs.lib.optional pkgs.stdenv.isDarwin pkgs.terminal-notifier # For ExUnit Notifier on macOS.
++ pkgs.lib.optionals pkgs.stdenv.isDarwin (
with pkgs.darwin.apple_sdk.frameworks;
[
# For file_system on macOS.
CoreFoundation
CoreServices
]
);
shellHook = ''
if ! test -d .nix-shell; then
mkdir .nix-shell
fi
export NIX_SHELL_DIR=$PWD/.nix-shell
# Put the PostgreSQL databases in the project directory.
export PGDATA=$NIX_SHELL_DIR/db
# Put any Mix-related data in the project directory.
export MIX_HOME=$NIX_SHELL_DIR/.mix
export MIX_ARCHIVES=$MIX_HOME/archives
export HEX_HOME=$NIX_SHELL_DIR/.hex
export PATH=$MIX_HOME/bin:$PATH
export PATH=$HEX_HOME/bin:$PATH
export PATH=$MIX_HOME/escripts:$PATH
export LIVEBOOK_HOME=$PWD
export ERL_LIBS="${erlang}/lib/erlang/lib"
${elixir}/bin/mix --version
${elixir}/bin/iex --version
'';
};
}
);
}
mix.exs
defmodule Proj.MixProject do
use Mix.Project
def project do
[
app: :proj,
version: "0.1.0",
elixir: "~> 1.14",
elixirc_paths: elixirc_paths(Mix.env()),
start_permanent: Mix.env() == :prod,
aliases: aliases(),
deps: deps()
]
end
# Configuration for the OTP application.
#
# Type `mix help compile.app` for more information.
def application do
[
mod: {Proj.Application, []},
extra_applications: [:logger, :runtime_tools]
]
end
# Specifies which paths to compile per environment.
defp elixirc_paths(:test), do: ["lib", "test/support"]
defp elixirc_paths(_), do: ["lib"]
# Specifies your project dependencies.
#
# Type `mix help deps` for examples and options.
defp deps do
[
{:phoenix, "~> 1.7.21"},
{:phoenix_ecto, "~> 4.5"},
{:ecto_sql, "~> 3.10"},
{:postgrex, ">= 0.0.0"},
{:phoenix_html, "~> 4.1"},
{:phoenix_live_reload, "~> 1.2", only: :dev},
{:phoenix_live_view, "~> 1.0"},
{:floki, ">= 0.30.0", only: :test},
{:phoenix_live_dashboard, "~> 0.8.3"},
{:esbuild, "~> 0.8", runtime: Mix.env() == :dev},
{:tailwind, "~> 0.2.0", runtime: Mix.env() == :dev},
{:heroicons,
github: "tailwindlabs/heroicons",
tag: "v2.1.1",
sparse: "optimized",
app: false,
compile: false,
depth: 1},
{:swoosh, "~> 1.5"},
{:finch, "~> 0.13"},
{:telemetry_metrics, "~> 1.0"},
{:telemetry_poller, "~> 1.0"},
{:gettext, "~> 0.26"},
{:jason, "~> 1.2"},
{:dns_cluster, "~> 0.1.1"},
{:bandit, "~> 1.5"}
]
end
# Aliases are shortcuts or tasks specific to the current project.
# For example, to install project dependencies and perform other setup tasks, run:
#
# $ mix setup
#
# See the documentation for `Mix` for more info on aliases.
defp aliases do
[
setup: ["deps.get", "ecto.setup", "assets.setup", "assets.build"],
"ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
"ecto.reset": ["ecto.drop", "ecto.setup"],
test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"],
"assets.setup": ["tailwind.install --if-missing", "esbuild.install --if-missing"],
"assets.build": ["tailwind proj", "esbuild proj"],
"assets.deploy": [
"tailwind proj --minify",
"esbuild proj --minify",
"phx.digest"
]
]
end
end