What's Changed
@nestjs/schematics is now a native ES module, and the major version is aligned with the Nest 12 release line. Beyond the package itself going ESM, the bigger change is what it generates: nest new now scaffolds ESM applications by default, and a brand-new nest upgrade schematic migrates existing v11 projects to v12.
ESM migration
The package is published as pure ESM ("type": "module", compiled with NodeNext). All internal imports carry explicit .js extensions and the build output is ESM-only.
The package now requires Node.js >= 22.12.0 and declares a typescript >= 6.0.0 peer dependency. prettier ^3 remains an optional peer, used only when --format is passed.
require(esm) — CommonJS still works
You do not need to convert your tooling to ESM. Thanks to Node's require(esm) support, CommonJS consumers can still require('@nestjs/schematics') on the supported Node versions, so custom collections and CJS scripts that drive the schematics programmatically keep working unchanged.
nest new generates ESM by default
The application schematic gained a type option (esm | cjs) that defaults to esm:
Which module system would you like to use?
> ESM (ES Modules) [ with vitest ]
CJS (CommonJS) [ with jest ]
- ESM projects get
"type": "module", Vitest as the test runner (vitest.config.ts/vitest.config.e2e.ts), and"types": ["vitest/globals", "node"]. - CJS projects keep Jest, but the Jest configuration has moved out of
package.jsoninto a dedicatedjest.config.ts.
Pass --type cjs (or answer the prompt) to keep the classic CommonJS layout.
Generated project defaults
- TypeScript 6, with
module/moduleResolutionset tonodenext,resolvePackageJsonExports: true,isolatedModules: true, andtarget: ES2023. - oxlint replaces ESLint. New projects ship an
oxlint.jsonand a"lint": "oxlint src/ test/"script instead of the ESLint config and its plugin chain. - Rspack replaces webpack as the default builder in
nest-cli.json. - Nest dependencies are pinned to the v12 line (
@nestjs/common,@nestjs/core,@nestjs/platform-express,@nestjs/testing).
ESM-aware generators
Every element generator (module, controller, service, resource, middleware, pipe, …) now detects whether the target project is ESM and appends .js to generated relative imports accordingly — including the imports it injects into an existing @Module() when wiring up a newly generated element. CJS projects are unaffected.
New: nest upgrade
A new schematic (aliased nest update) migrates a Nest v11 project to v12. It refuses to run on anything that isn't v11, then applies the migration in steps and prints a report of every change, every follow-up action, and every warning.
Dependencies — bumps all known @nestjs/* packages to ^12.0.0 (GraphQL packages to ^14.0.0), raises typescript to ^6.0.0 and engines.node to >=20.19.0, and reports any @nestjs/* package whose v12-compatible release it doesn't know about.
tsconfig — flags module: commonjs with legacy module resolution and any moduleResolution that TypeScript 6 dropped, and points out a missing rootDir in tsconfig.build.json (TS6 error TS5011).
@nestjs/config — moves library-specific validationOptions (Joi's allowUnknown, abortEarly, …) under validationOptions.libraryOptions, and raises joi to ^18 for its Standard Schema support.
GraphQL — renames the removed playground option to graphiql, and switches subscriptions-transport-ws over to graphql-ws, updating package.json to match.
NATS — rewrites nats imports to the v3 @nats-io packages and warns about the dropped StringCodec/JSONCodec helpers and the new packet serialization (custom deserializers now receive the full NATS message; read it with msg.json()).
Testing — raises jest, @types/jest, and ts-jest to Jest 30, and warns that because the Nest 12 packages are ESM-only, Jest can only require() them on Node.js 24.9+ (older versions fail with ERR_REQUIRE_ASYNC_MODULE).
CLI config — migrates nest-cli.json builders from webpack to Rspack, drops the deprecated webpack: false option, updates affected package.json scripts, and asks you to port any custom webpack config file by hand.
Diagnostics — scans the project and warns about the refined PipeTransform#transform signature and generic ArgumentMetadata, the new ConsoleLogger structured-params behaviour (opt out with structuredParams: false), and the change to lifecycle hook ordering by component hierarchy level.
Options: --observe, --skip-install, --tag <dist-tag>, --format.
@nestjs/observe integration
Both nest new --observe and nest upgrade --observe can preconfigure the application with @nestjs/observe — distributed tracing, auto-correlated logs, metrics, and alarms. The schematic adds the dependency and wires createObserveModule() into the root module, then reminds you to set OBSERVE_APP_KEY and OBSERVE_APP_SECRET. It is opt-in and skipped when the package is already installed.
See the migration guide for the full picture.