Commit Graph

23 Commits

Author SHA1 Message Date
adisbladis
5666445319 importNpmLock: correctly handle more dist tags than just "latest"
Discovered while trying to package https://github.com/membermatters/membermatters (out of tree)
where its dependency on @intlify/message-compiler failed.
2026-08-02 11:37:12 +02:00
Sigmanificient
0bbc8dffae treewide: set meta.license on hooks 2026-05-25 13:48:20 +02:00
nixpkgs-ci[bot]
2af179604c Merge master into staging-next 2026-04-08 18:27:42 +00:00
K900
b68eb306fc import-npm-lock: fix build with structuredAttrs 2026-04-08 13:04:26 +03:00
Stefan Frijters
d997cac9c2 build-support/node/import-npm-lock: use printf instead of echo
This is a shell builtin and is safer when dealing with large inputs:
it avoids possible 'argument list too long' errors.
2026-03-22 13:04:17 +01:00
Philip Taron
6e613243b1 build-support/node/import-npm-lock: use structuredAttrs instead of passAsFile (#498929) 2026-03-22 06:20:58 +00:00
Winter M
d370f2f878 importNpmLock: handle commit in resolved git url
npm's locking process resolves Git dependencies to a given commit, separated
by a `#`. Before this change, any encounter of these URLs would cause `fetchGit`
to fail, as they're not valid repo URLs.
2026-03-18 13:14:16 -04:00
Linus Heckemann
a15d4a443d linkNodeModulesHook: replace symlinks atomically
Up to now, existing symlinks were replaced by removing the existing link
and then creating a new one. This left a window where the link did not
exist, which would break cases where the hook was running concurrently
with other things using node_modules.

In my case, I would run multiple webpack builds at once like:

  nix develop -c webpack build --mode production
  nix develop -c webpack build --mode development

If one of the shells was ready faster than the other, webpack would
start running, then the second would run the linkNodeModules hook, and
the earlier webpack build would run into missing files as the second
linkNodeModules hook removed symlinks to replace them.


This change mitigates this race condition in two ways:

- Not replacing the symlink if it already points to the right target
  (this also avoids superfluous filesystem writes)

- Replacing the symlink atomically, using a rename,
  otherwise. The symlink was replaced atomically prior to
  db7050bb88 as well, but the name of the
  temporary symlink was always the same, which led to a similar race
  condition. This change reintroduces the atomic replacement, but adds
  the PID to the temporary filename in order to avoid conflicting with
  other instances of the hook running concurrently.
2026-03-17 16:09:18 +01:00
Stefan Frijters
e00cfe671f build-support/node/import-npm-lock: use structuredAttrs instead of passAsFile 2026-03-12 18:30:19 +01:00
Linus Heckemann
345c0e2851 linkNodeModulesHook: respect NODE_PATH 2026-02-23 19:04:59 +01:00
NAHO
c8d4dabc43 pkgs: remove optional builtins prefixes from prelude functions
Remove optional builtins prefixes from prelude functions by running:

    builtins=(
      abort
      baseNameOf
      break
      derivation
      derivationStrict
      dirOf
      false
      fetchGit
      fetchMercurial
      fetchTarball
      fetchTree
      fromTOML
      import
      isNull
      map
      null
      placeholder
      removeAttrs
      scopedImport
      throw
      toString
      true
    )

    fd \
      --type file \
      . \
      pkgs \
      --exec-batch sed --in-place --regexp-extended "
        s/\<builtins\.($(
          printf '%s\n' "${builtins[@]}" |
            paste --delimiter '|' --serial -
        ))\>/\1/g
      "

    nix fmt
2025-10-04 19:02:37 +02:00
Wolfgang Walther
5a0711127c treewide: run nixfmt 1.0.0 2025-07-24 13:55:40 +02:00
Philip Taron
c98749388a importNpmLock: fix native dependencies for Darwin (#423199) 2025-07-23 08:01:57 -07:00
adisbladis
db7050bb88 importNpmLock: Don't create intermediate symlink files
It's currently possible to run into a race condition when entering the same development environment concurrently:
```
❯ git fetch; jj rebase -b 'all:mutable() & mine()' -d main@origin --skip-emptied
Rebased 4 commits onto destination
Abandoned 1 newly emptied commits
Working copy  (@) now at: tnyknvqt 93e36def (empty) (no description set)
Parent commit (@-)      : wnqxqyyl e0983a05 main@origin | Increase limit of max number of words
Added 0 files, modified 8 files, removed 0 files
direnv: loading ~/dev/REDACTED/.envrc
direnv: loading https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.4/direnvrc (sha256-DzlYZ33mWF/Gs8DDeyjr8mnVmQGx7ASYqA5WlxwvBG4=)
Executing linkNodeModulesHook
node:internal/fs/promises:782
  return await PromisePrototypeThen(
         ^

Error: ENOENT: no such file or directory, rename 'node_modules/.bin-nix-hook-temp' -> 'node_modules/.bin'
    at async Object.rename (node:internal/fs/promises:782:10)
    at async /nix/store/ps9ivjjxzi0fks67j6vd4gbw5dcnhp0w-link-node-modules.js:84:7
    at async Promise.all (index 0)
    at async main (/nix/store/ps9ivjjxzi0fks67j6vd4gbw5dcnhp0w-link-node-modules.js:58:3) {
  errno: -2,
  code: 'ENOENT',
  syscall: 'rename',
  path: 'node_modules/.bin-nix-hook-temp',
  dest: 'node_modules/.bin'
}

Node.js v20.17.0
Finished executing linkNodeModulesShellHook
```

This change removes the intermediate file creation and simply tries to create a symlink directly.
If the target `node_modules/foo` already exists we unlink it and try to create the symlink again.
2025-07-14 18:43:05 +12:00
Moritz Heidkamp
da4672b591 importNpmLock: fix native dependencies for Darwin
Essentially the same fix as 79459354cb for `buildNpmPackage`.
2025-07-07 15:33:28 +02:00
uonr
339d1d1cb1 importNpmLock: handle "resolved" is null 2025-04-30 18:52:11 +09:00
Peder Bergebakken Sundt
5aba99242e treewide: fix typos in comments
Made with

```shell
git restore .
fd '\.nix$' pkgs/ --type f -j1 -x bash -xc "$(cat <<"EOF"
    typos --no-check-filenames --write-changes "$1"
    git diff --exit-code "$1" && exit
    #( git diff "$1" | grep -qE "^\+ +[^# ]") && git restore "$1"
    count1="$( bat --language nix --diff --style changes "$1" --theme "Monokai Extended" --color always | aha --no-header | grep -E '^<span style="color:olive;">~</span> ' | wc -l )"
    count2="$( bat --language nix --diff --style changes "$1" --theme "Monokai Extended" --color always | aha --no-header | grep -E '^<span style="color:olive;">~</span> (<span style="color:#f8f8f2;"> *</span>)?<span style="color:#75715e;">.*</span>$' | wc -l )"
    [[ $count1 -ne $count2 ]] && git restore "$1"
EOF
)" -- {}
```

and filtered with `GIT_DIFF_OPTS='--unified=15' git -c interactive.singleKey=true add --patch`

I initially tried using the tree-sitter cli, python bindings and even ast-grep through various means, but this is what I ended up with.
2025-02-24 10:44:41 +01:00
phaer
e2013a5096 importNpmLock: fix check for .bin in linkNodeModulesHook
node_modules/.bin/ is expected to be (symlink to) a directory rather
than a regular file, so we check for that.

This seems to work for pre-existing directories as well as those
we link to the store (managed & unmanaged in the hooks terminology).

I am not entirely sure whether the original check was simply a typo
or intentional for some use-cases.
2025-01-10 12:37:32 +01:00
Silvan Mosberger
4f0dadbf38 treewide: format all inactive Nix files
After final improvements to the official formatter implementation,
this commit now performs the first treewide reformat of Nix files using it.
This is part of the implementation of RFC 166.

Only "inactive" files are reformatted, meaning only files that
aren't being touched by any PR with activity in the past 2 months.
This is to avoid conflicts for PRs that might soon be merged.
Later we can do a full treewide reformat to get the rest,
which should not cause as many conflicts.

A CI check has already been running for some time to ensure that new and
already-formatted files are formatted, so the files being reformatted here
should also stay formatted.

This commit was automatically created and can be verified using

    nix-build a08b3a4d19.tar.gz \
      --argstr baseRev b32a094368
    result/bin/apply-formatting $NIXPKGS_PATH
2024-12-10 20:26:33 +01:00
Johannes Kirschbauer
34b7d209bb nodejs/importNpmLock: init source overrides option 2024-10-17 12:00:45 +02:00
adisbladis
9c7ff7277c importNpmLock.buildNodeModules: init
`importNpmLock.buildNodeModules` returns a derivation with a pre-built `node_modules` directory, as imported by `importNpmLock`.
This is to be used together with `importNpmLock.hooks.linkNodeModulesHook` to facilitate `nix-shell`/`nix develop` based development workflows:

```nix
pkgs.mkShell {
  packages = [
    importNpmLock.hooks.linkNodeModulesHook
    nodejs
  ];

  npmDeps = importNpmLock.buildNodeModules {
    npmRoot = ./.;
    inherit nodejs;
  };
}
```
will create a development shell where a `node_modules` directory is created & packages symlinked to the Nix store when activated.

This code is adapted from https://github.com/adisbladis/buildNodeModules
2024-08-29 06:12:07 -07:00
Johannes Kirschbauer
3ed5055f0f importNpmLock: init fetcherOps per package 2024-08-13 09:38:37 +02:00
adisbladis
b6e4b86809 importNpmLock: init
This is an alternative to `fetchNpmDeps` that is notably different in that it uses metadata from `package.json` & `package-lock.json` instead of specifying a fixed-output hash.

Notable features:
- IFD free.
- Only fetches a node dependency once. No massive FODs.
- Support for URL, Git and path dependencies.
- Uses most of the existing `npmHooks`

`importNpmLock` can be used _only_ in the cases where we need to check in a `package-lock.json` in the tree.
Currently this means that we have 13 packages that would be candidates to use this function, though I expect most usage to be in private repositories.

This is upstreaming the builder portion of https://github.com/adisbladis/buildNodeModules into nixpkgs (different naming but the code is the same).
I will archive this repository and consider nixpkgs the new upstream once it's been merged.

For more explanations and rationale see https://discourse.nixos.org/t/buildnodemodules-the-dumbest-node-to-nix-packaging-tool-yet/35733

Example usage:
``` nix
stdenv.mkDerivation {
  pname = "my-nodejs-app";
  version = "0.1.0";

  src = ./.;

  nativeBuildInputs = [
    importNpmLock.hooks.npmConfigHook
    nodejs
    nodejs.passthru.python # for node-gyp
    npmHooks.npmBuildHook
    npmHooks.npmInstallHook
  ];

  npmDeps = buildNodeModules.fetchNodeModules {
    npmRoot = ./.;
  };
}
```
2024-03-05 12:23:28 +13:00