feat: add node module and buildPnpmTask helper #37
No reviewers
Labels
No labels
needs/docs
needs/research
needs/upstream
type/bug
type/external
type/feature
type/refactor
urgency
high
urgency
immediate
urgency
low
urgency
medium
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
ScottyLabs/kennel!37
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/node-pnpm"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Why
Kennel only supports JavaScript projects through Deno. Projects that can't move to Deno yet (maps, for example, is on Bun) had no supported way onto devenv and kennel. In the Discord thread, Anish said a pnpm/Node helper was fine as an alternative, so this adds one. Deno stays the recommended default, and the docs say so.
What this adds
scottylabs.node.enable = trueand the shell gets Node.js 24 and pnpm, installs dependencies on entry, and runs lint, type-check and tests on every commit, the same way the Deno setup does.buildPnpmTask. It builds a pnpm project into something kennel can deploy: either a static site or a backend service.Nothing changes for existing Deno projects.
How a project uses it
Things to know
hashfor its dependencies. Set it to"", build once, and copy the hash from the error. Update it wheneverpnpm-lock.yamlchanges, or kennel's build fails. A different pnpm version also changes the hash, so recheck it after a nixpkgs update.prisma generate, have to go in the build script.package.jsonhas apackageManagerfield for a different pnpm major, the shell and the build end up on different pnpm versions. Remove the field or pick the matching pnpm (see the docs).This PR doesn't touch maps; Sushrut's PR is handling that onboarding.
Technical details
Changes
nix/modules/node.nix(new):scottylabs.node.enable,package(Node.js, defaultpkgs.nodejs_24),pnpm(defaultpkgs.pnpm),dirs(default[ "." ], mirrorsdeno.dirs),react.enable,checkScript(defaulttypecheck),testScript(defaulttest).pnpm installruns in each ofdirson shell entry.pnpm-checkandpnpm-testrunpnpm run --if-present <script>in each ofdirs, failing on the first error. In a workspace, the root script fans out (pnpm -r ...or turbo)..devenv/state/pnpmvia bothnpm_config_store_dirandpnpm_config_store_dir. pnpm 10 only reads the first and pnpm 12 only the second.nix/modules/oxc.nix(new): the oxlint hook, oxfmt andOXLINT_TSGOLINT_PATHmove here fromdeno.nix, so both toolchains share one definition instead of defining the hook twice. React plugins are on when either toolchain'sreact.enableis set.nix/lib/build-pnpm-task.nix(new):buildPnpmTask, exposed inmkLib.src,cwd,pname,version,hash,script(defaultbuild,nullskips it),output(defaultdist),main,nodejs,pnpm.fetchPnpmDeps(fetcherVersion 4) andpnpmConfigHook.buildEnvis exported into the build only, as with the other helpers.node_modules, then runs autoPatchelf over the native addons, likebuildDenoTask.main, it copies<cwd>/<output>to$out.main, it copies the built tree (includingnode_modules, whose links point into the workspace root) to$out/lib, and writes$out/bin/<pname>. That wrapper runsnode $out/lib/<cwd>/<main>, keeps the caller's working directory sosecretspec.tomlis found, and defaultsNODE_ENVtoproduction.nix/modules/default.niximports the two new modules.flake.nixaddsbuildPnpmTasktomkLib..forgejo/actions/prepare/action.ymlcaches.devenv/state/pnpmand addspnpm-lock.yamlto the cache key.nix/modules/security.nix: the osv-scanner description listspnpm-lock.yaml.guides/deploying.md: the JS section is split into Deno and Node.js with pnpm, and gains the hash workflow, the build-vs-shell differences, and the Bun migration steps.reference/build-helpers.mddocumentsbuildPnpmTask.guides/ci.mdmentions the pnpm cache,guides/features.mdaddsnodeto the Sentry platform examples, andnix/README.mdlists Node.js.Design notes
languages.javascript, to matchdeno.nix, which also sets up its toolchain directly.pnpm deploy --prodcould trim it in a follow-up.pnpm importcan't readbun.lock, so moving off Bun means resolving dependencies fresh. The migration steps say this.maindirectly only if it uses erasable syntax (noenum,namespaceor parameter properties). Otherwise the build script compiles it.Testing
pnpm_10:buildEnvvariable baked in.mainset: it answered/api/healthwhen started from an unrelated directory. Rebuilding it withscript = nullalso worked, and a dangling symlink owned by the project survived the build.dirs = [ "a" "b" ]and ran it. It ran in both directories, failed when one script exited nonzero, and passed once that script was removed.main.packageManager: pnpm@10field in the shell.pnpm importrejects maps'bun.lock..tsfile and rejectsenum.nix build .#docssucceeds, and the cross-page link todeploying.html#nodejs-with-pnpmresolves.deadnix --fail, statix, mdformat and block-ai-slop pass.nix build --rebuild) produced the same hash, so it's reproducible. pnpm 10 and pnpm 12 produce different hashes for the same lockfile, which is why the docs say to recheck the hash after a pnpm or nixpkgs update.SSL_CERT_FILEat the proxy's CA inside the fetch. That doesn't affect the output hash.Kennel Deployments
Last updated for commit
afbe923.View command line instructions
Manual merge helper
Use this merge commit message when completing the merge manually.
Checkout
From your project repository, check out a new branch and test the changes.