nest-server-updating

Installation
SKILL.md

@lenne.tech/nest-server Update Knowledge Base

This skill provides knowledge and resources for updating @lenne.tech/nest-server. For automated execution, use the lt-dev:nest-server-updater agent via /lt-dev:backend:update-nest-server.

Important: After updating nest-server, also check if @lenne.tech/nuxt-extensions in projects/app/ needs a compatible update, as nuxt-extensions is aligned with nest-server.

Gotchas

  • Crossing the jest→vitest boundary — At some point on the upstream nest-server-starter timeline the test runner migrated from jest+ts-jest to vitest+unplugin-swc (check the starter's package.json for the current truth — if vitest-e2e.config.ts exists, the boundary is behind you). Updating an existing project across that boundary needs more than a pnpm install: every @Prop whose property is a TypeScript union ('a' | 'b', null | string, an alias for either) must add type: String (or type: Object for record-likes), every import * as supertest must become a default import, every jest.* call must become vi.*, and jest-e2e.json + babel.config.js must be removed. Without these, vitest fails with "Cannot determine a type for the X field" from Mongoose, or "is not a function" from supertest. The full recipe lives in the modernizing-toolchain skill — apply Phases 2 and 3 before running pnpm test. A project still on jest when it reaches 12.x must migrate first: the NestJS 12 packages are ESM-only, and jest loads them only on Node 24.9+ (ERR_REQUIRE_ASYNC_MODULE below that).
  • The 12.0 step (NestJS 12, TypeScript 6) breaks builds without a single source change — 11.43.x-to-12.0.x.md is the guide; four things in it catch most projects. (1) Raise every NestJS-family pin and typescript together with nest-server (pnpm run update raises the pins the project already declares): one @nestjs/* package left on 11 installs a second NestJS copy, and the build fails with Class 'X' incorrectly extends base class 'CoreX'. (2) TypeScript 6 turns strict on, resolves rootDir to the tsconfig's directory and defaults types to [], so tsconfig.json needs "strict": false, "types": ["node", "vitest/globals"] and a rootDir the start:prod path expects; an explicit "moduleResolution": "node" is error TS5107. (3) @nestjs/{jwt,mongoose,passport,schedule,swagger,terminus} resolve only from their package root, so a deep …/dist/… import fails with TS2307 or ERR_PACKAGE_PATH_NOT_EXPORTED. (4) A subclass that redeclares its constructor no longer inherits the parent's @Optional() flags; the symptom is Nest can't resolve dependencies of the XService (…, ?). nest-server itself is an ES module from 12.0 on, like every @nestjs/* package, and CommonJS projects stay CommonJS: Node loads them all through require(esm), which is why the Node floor matters (22.12+, nest-server's engines.node names the exact one). A vendor-mode project has one more required step: its dev start moves from ts-node to the framework's loader (node -r ./src/core/modules/migrate/helpers/ts-compiler.js src/main.ts, guide §14), because the 12.x core imports ./x.js and ts-node cannot load it; without it pnpm start fails with Cannot find module './core.module.js' while build, migrate:* and tests pass (details in nest-server-core-vendoring).
  • ESM projects are optional, never part of the update — Converting a project to "type": "module" (guide §17 "Converting a project to ESM") is worth it only for a package that loads from an ES module alone (top-level await, ERR_REQUIRE_ASYNC_MODULE under require(esm)) or to match nest new. Do it as its own step after the update is green, with lt server convert-esm --noConfirm in the API project or a workspace root with projects/api (--dry-run previews; it refuses nest-server below 12 and, unless --force, a dirty git tree, so the conversion is one diff). What has no exact rewrite (a named import from a CommonJS package, a decorated field on an import cycle, a leftover require) comes with file:line and exit 1: fix it by hand (generating-nest-servers → ESM rules) and run the same command again, which on an ESM project re-checks without a clean tree. It ends with build, start of the BUILT server, migrate:list and dev start, because vitest passes code that Node's ESM loader refuses; with --skip-verify, or by the guide's steps on a CLI without the command, start the built server yourself.
  • useDefineForClassFields mismatch — When migrating to vitest, both the tsconfig.json compilerOptions.useDefineForClassFields and the swc plugin in vitest-e2e.config.ts must be set to true. Mixing them (e.g. swc=false, ts=true) silently breaks NestJS DI: securityCheck gets the wrong currentUser, so user signUp returns createdBy: null even though the override service set it. There is no error, only test failures that look like business logic regressions.
  • Minor version bumps are treated as MAJOR — @lenne.tech/nest-server follows a "stepwise update" policy even on minor versions. Jumping from 7.5.x directly to 7.9.x in one step is likely to miss breaking changes that were introduced sub-minor. Always run the update step-by-step via pnpm run update, even if the version gap looks small.
  • pnpm run update requires the target version in package.json FIRST — The update script reads the current/target from package.json. Running it before bumping the version does nothing or produces confusing errors. Order: (1) bump package.json → (2) pnpm install → (3) pnpm run update.
  • nuxt-extensions alignment breaks silently — @lenne.tech/nuxt-extensions is version-aligned with @lenne.tech/nest-server. Updating nest-server to 7.19.0 without also updating nuxt-extensions to 7.19.x leaves the frontend consuming an outdated API contract. Types generated via generate-types may still pass locally but break at runtime on production.
  • Migration guides are cumulative — read ALL between old and new version — If you jump from 7.12 to 7.19, migration guides for 7.13, 7.14, 7.15, 7.16, 7.17, 7.18, 7.19 ALL apply. Don't skip reading them — each introduces non-trivial behavior changes.
  • Starter project is the ground truth for constellations — When a migration is ambiguous (e.g., which package.json override to add, which config value to change), check nest-server-starter's current package.json via GitHub raw. It reflects the canonical working constellation for the target version.

Scope: npm mode vs vendored mode

Installs
1
First Seen
Oct 27, 2026