@nestjs/cli 12.0.0-alpha.0 → 12.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
1
  import { MultiNestCompilerPlugins } from '../plugins/plugins-loader.js';
2
- export declare const rspackDefaultsFactory: (sourceRoot: string, relativeSourceRoot: string, entryFilename: string, isDebugEnabled: boolean | undefined, tsConfigFile: string | undefined, plugins: MultiNestCompilerPlugins) => Record<string, any>;
2
+ export declare const rspackDefaultsFactory: (sourceRoot: string, relativeSourceRoot: string, entryFilename: string, isDebugEnabled: boolean | undefined, tsConfigFile: string | undefined, plugins: MultiNestCompilerPlugins, isEsm?: boolean) => Record<string, any>;
@@ -1,11 +1,22 @@
1
- import { createRequire } from 'module';
1
+ import { builtinModules, createRequire } from 'module';
2
2
  import { join } from 'path';
3
- import { TsconfigPathsPlugin } from 'tsconfig-paths-webpack-plugin';
4
3
  import { defaultTsconfigFilename } from '../../configuration/defaults.js';
5
4
  import { appendTsExtension } from '../helpers/append-extension.js';
6
- import nodeExternals from 'webpack-node-externals';
7
5
  const require = createRequire(import.meta.url);
8
- export const rspackDefaultsFactory = (sourceRoot, relativeSourceRoot, entryFilename, isDebugEnabled = false, tsConfigFile = defaultTsconfigFilename, plugins) => {
6
+ function loadRspackDeps() {
7
+ try {
8
+ const externals = require('webpack-node-externals');
9
+ const { TsconfigPathsPlugin } = require('tsconfig-paths-webpack-plugin');
10
+ return { nodeExternals: externals, TsconfigPathsPlugin };
11
+ }
12
+ catch (e) {
13
+ const pkg = e?.message?.match?.(/Cannot find.*'([^']+)'/)?.[1] ?? 'webpack-node-externals';
14
+ throw new Error(`The "${pkg}" package is required when using the rspack compiler but could not be found. ` +
15
+ `Please install it:\n\n npm install --save-dev @rspack/core webpack-node-externals tsconfig-paths-webpack-plugin\n`);
16
+ }
17
+ }
18
+ export const rspackDefaultsFactory = (sourceRoot, relativeSourceRoot, entryFilename, isDebugEnabled = false, tsConfigFile = defaultTsconfigFilename, plugins, isEsm = false) => {
19
+ const { nodeExternals: externals, TsconfigPathsPlugin } = loadRspackDeps();
9
20
  const isPluginRegistered = isAnyPluginRegistered(plugins);
10
21
  const rspackConfiguration = {
11
22
  entry: appendTsExtension(join(sourceRoot, entryFilename)),
@@ -13,10 +24,36 @@ export const rspackDefaultsFactory = (sourceRoot, relativeSourceRoot, entryFilen
13
24
  target: 'node',
14
25
  output: {
15
26
  filename: join(relativeSourceRoot, `${entryFilename}.js`),
27
+ ...(isEsm && {
28
+ module: true,
29
+ library: { type: 'module' },
30
+ chunkFormat: 'module',
31
+ chunkLoading: 'import',
32
+ }),
16
33
  },
34
+ ...(isEsm && {
35
+ experiments: { outputModule: true, topLevelAwait: true },
36
+ }),
17
37
  ignoreWarnings: [/^(?!CriticalDependenciesWarning$)/],
18
- externals: [nodeExternals()],
19
- externalsPresets: { node: true },
38
+ externals: [
39
+ externals(isEsm ? { importType: 'module' } : {}),
40
+ ...(isEsm
41
+ ? [
42
+ ({ request }, callback) => {
43
+ if (!request)
44
+ return callback();
45
+ const bare = request.startsWith('node:')
46
+ ? request.slice(5)
47
+ : request;
48
+ if (builtinModules.includes(bare)) {
49
+ return callback(null, `module ${request}`);
50
+ }
51
+ callback();
52
+ },
53
+ ]
54
+ : []),
55
+ ],
56
+ externalsPresets: { node: !isEsm },
20
57
  module: {
21
58
  rules: [
22
59
  {
@@ -41,11 +78,18 @@ export const rspackDefaultsFactory = (sourceRoot, relativeSourceRoot, entryFilen
41
78
  },
42
79
  ],
43
80
  exclude: /node_modules/,
81
+ ...(isEsm && { type: 'javascript/esm' }),
44
82
  },
45
83
  ],
46
84
  },
47
85
  resolve: {
48
86
  extensions: ['.tsx', '.ts', '.js'],
87
+ ...(isEsm && {
88
+ extensionAlias: {
89
+ '.js': ['.ts', '.js'],
90
+ '.mjs': ['.mts', '.mjs'],
91
+ },
92
+ }),
49
93
  tsConfig: tsConfigFile,
50
94
  plugins: [
51
95
  new TsconfigPathsPlugin({
@@ -1,3 +1,3 @@
1
+ import type webpack from 'webpack';
1
2
  import { MultiNestCompilerPlugins } from '../plugins/plugins-loader.js';
2
- import webpack from 'webpack';
3
3
  export declare const webpackDefaultsFactory: (sourceRoot: string, relativeSourceRoot: string, entryFilename: string, isDebugEnabled: boolean | undefined, tsConfigFile: string | undefined, plugins: MultiNestCompilerPlugins) => webpack.Configuration;
@@ -1,12 +1,23 @@
1
1
  import { createRequire } from 'module';
2
2
  import { join } from 'path';
3
- import { TsconfigPathsPlugin } from 'tsconfig-paths-webpack-plugin';
4
3
  import { defaultTsconfigFilename } from '../../configuration/defaults.js';
5
4
  import { appendTsExtension } from '../helpers/append-extension.js';
6
- import webpack from 'webpack';
7
- import nodeExternals from 'webpack-node-externals';
8
5
  const require = createRequire(import.meta.url);
6
+ function loadWebpackDeps() {
7
+ try {
8
+ const wp = require('webpack');
9
+ const externals = require('webpack-node-externals');
10
+ const { TsconfigPathsPlugin } = require('tsconfig-paths-webpack-plugin');
11
+ return { webpack: wp, nodeExternals: externals, TsconfigPathsPlugin };
12
+ }
13
+ catch (e) {
14
+ const pkg = e?.message?.match?.(/Cannot find.*'([^']+)'/)?.[1] ?? 'webpack';
15
+ throw new Error(`The "${pkg}" package is required when using the webpack compiler but could not be found. ` +
16
+ `Please install it:\n\n npm install --save-dev webpack webpack-node-externals tsconfig-paths-webpack-plugin ts-loader fork-ts-checker-webpack-plugin\n`);
17
+ }
18
+ }
9
19
  export const webpackDefaultsFactory = (sourceRoot, relativeSourceRoot, entryFilename, isDebugEnabled = false, tsConfigFile = defaultTsconfigFilename, plugins) => {
20
+ const { webpack: wp, nodeExternals: externals, TsconfigPathsPlugin, } = loadWebpackDeps();
10
21
  const isPluginRegistered = isAnyPluginRegistered(plugins);
11
22
  const webpackConfiguration = {
12
23
  entry: appendTsExtension(join(sourceRoot, entryFilename)),
@@ -16,7 +27,7 @@ export const webpackDefaultsFactory = (sourceRoot, relativeSourceRoot, entryFile
16
27
  filename: join(relativeSourceRoot, `${entryFilename}.js`),
17
28
  },
18
29
  ignoreWarnings: [/^(?!CriticalDependenciesWarning$)/],
19
- externals: [nodeExternals()],
30
+ externals: [externals()],
20
31
  externalsPresets: { node: true },
21
32
  module: {
22
33
  rules: [
@@ -57,7 +68,7 @@ export const webpackDefaultsFactory = (sourceRoot, relativeSourceRoot, entryFile
57
68
  __dirname: false,
58
69
  },
59
70
  plugins: [
60
- new webpack.IgnorePlugin({
71
+ new wp.IgnorePlugin({
61
72
  checkResource(resource) {
62
73
  const lazyImports = [
63
74
  '@nestjs/microservices',
@@ -2,6 +2,7 @@ import { existsSync } from 'fs';
2
2
  import { createRequire } from 'module';
3
3
  import { join } from 'path';
4
4
  import { INFO_PREFIX } from '../ui/index.js';
5
+ import { isEsmProject } from '../utils/is-esm-project.js';
5
6
  import { BaseCompiler } from './base-compiler.js';
6
7
  import { rspackDefaultsFactory } from './defaults/rspack-defaults.js';
7
8
  import { getValueOrDefault } from './helpers/get-value-or-default.js';
@@ -20,8 +21,15 @@ export class RspackCompiler extends BaseCompiler {
20
21
  const pathToSource = this.getPathToSource(configuration, tsConfigPath, appName);
21
22
  const entryFile = getValueOrDefault(configuration, 'entryFile', appName, 'entryFile', extras.options);
22
23
  const entryFileRoot = getValueOrDefault(configuration, 'root', appName) || '';
23
- const defaultOptions = rspackDefaultsFactory(pathToSource, entryFileRoot, entryFile, extras.debug ?? false, tsConfigPath, plugins);
24
- const rspack = require('@rspack/core');
24
+ const defaultOptions = rspackDefaultsFactory(pathToSource, entryFileRoot, entryFile, extras.debug ?? false, tsConfigPath, plugins, isEsmProject());
25
+ let rspack;
26
+ try {
27
+ rspack = require('@rspack/core');
28
+ }
29
+ catch {
30
+ throw new Error('@rspack/core is not installed. To use the rspack compiler, install the required packages:\n\n' +
31
+ ' npm install --save-dev @rspack/core webpack-node-externals tsconfig-paths-webpack-plugin\n');
32
+ }
25
33
  let compiler;
26
34
  let watchOptions;
27
35
  let watch;
@@ -2,7 +2,7 @@ import { Configuration } from '../configuration/index.js';
2
2
  import { AssetsManager } from './assets-manager.js';
3
3
  import { BaseCompiler } from './base-compiler.js';
4
4
  import { PluginsLoader } from './plugins/plugins-loader.js';
5
- import webpack from 'webpack';
5
+ import type webpack from 'webpack';
6
6
  type WebpackConfigFactory = (config: webpack.Configuration, webpackRef: typeof webpack) => webpack.Configuration;
7
7
  type WebpackConfigFactoryOrConfig = WebpackConfigFactory | webpack.Configuration;
8
8
  type WebpackCompilerExtras = {
@@ -1,10 +1,24 @@
1
1
  import { existsSync } from 'fs';
2
+ import { createRequire } from 'module';
2
3
  import { join } from 'path';
3
4
  import { INFO_PREFIX } from '../ui/index.js';
5
+ import { isEsmProject } from '../utils/is-esm-project.js';
4
6
  import { BaseCompiler } from './base-compiler.js';
5
7
  import { webpackDefaultsFactory } from './defaults/webpack-defaults.js';
6
8
  import { getValueOrDefault } from './helpers/get-value-or-default.js';
7
- import webpack from 'webpack';
9
+ const WEBPACK_DEPRECATION_MSG = 'The webpack compiler is deprecated and will be removed in a future major version. ' +
10
+ 'Please migrate to rspack (--builder rspack). ' +
11
+ 'See https://docs.nestjs.com/cli/usages#build for details.';
12
+ const require = createRequire(import.meta.url);
13
+ function loadWebpack() {
14
+ try {
15
+ return require('webpack');
16
+ }
17
+ catch {
18
+ throw new Error('webpack is not installed. To use the webpack compiler, install the required packages:\n\n' +
19
+ ' npm install --save-dev webpack webpack-node-externals tsconfig-paths-webpack-plugin ts-loader\n');
20
+ }
21
+ }
8
22
  export class WebpackCompiler extends BaseCompiler {
9
23
  constructor(pluginsLoader) {
10
24
  super(pluginsLoader);
@@ -19,7 +33,14 @@ export class WebpackCompiler extends BaseCompiler {
19
33
  const pathToSource = this.getPathToSource(configuration, tsConfigPath, appName);
20
34
  const entryFile = getValueOrDefault(configuration, 'entryFile', appName, 'entryFile', extras.options);
21
35
  const entryFileRoot = getValueOrDefault(configuration, 'root', appName) || '';
36
+ if (isEsmProject()) {
37
+ throw new Error('The webpack compiler does not support ESM projects ("type": "module" in package.json). ' +
38
+ 'Please use rspack instead by setting "builder": "rspack" in your nest-cli.json compilerOptions, ' +
39
+ 'or use --builder rspack on the command line.');
40
+ }
41
+ console.warn(`\n${INFO_PREFIX} ${WEBPACK_DEPRECATION_MSG}\n`);
22
42
  const defaultOptions = webpackDefaultsFactory(pathToSource, entryFileRoot, entryFile, extras.debug ?? false, tsConfigPath, plugins);
43
+ const wp = loadWebpack();
23
44
  let compiler;
24
45
  let watchOptions;
25
46
  let watch;
@@ -27,27 +48,27 @@ export class WebpackCompiler extends BaseCompiler {
27
48
  const webpackConfigurations = extras.webpackConfigFactoryOrConfig.map((configOrFactory) => {
28
49
  const unwrappedConfig = typeof configOrFactory !== 'function'
29
50
  ? configOrFactory
30
- : configOrFactory(defaultOptions, webpack);
51
+ : configOrFactory(defaultOptions, wp);
31
52
  return {
32
53
  ...defaultOptions,
33
54
  mode: extras.watchMode ? 'development' : defaultOptions.mode,
34
55
  ...unwrappedConfig,
35
56
  };
36
57
  });
37
- compiler = webpack(webpackConfigurations);
58
+ compiler = wp(webpackConfigurations);
38
59
  watchOptions = webpackConfigurations.map((config) => config.watchOptions || {});
39
60
  watch = webpackConfigurations.some((config) => config.watch);
40
61
  }
41
62
  else {
42
63
  const projectWebpackOptions = typeof extras.webpackConfigFactoryOrConfig !== 'function'
43
64
  ? extras.webpackConfigFactoryOrConfig
44
- : extras.webpackConfigFactoryOrConfig(defaultOptions, webpack);
65
+ : extras.webpackConfigFactoryOrConfig(defaultOptions, wp);
45
66
  const webpackConfiguration = {
46
67
  ...defaultOptions,
47
68
  mode: extras.watchMode ? 'development' : defaultOptions.mode,
48
69
  ...projectWebpackOptions,
49
70
  };
50
- compiler = webpack(webpackConfiguration);
71
+ compiler = wp(webpackConfiguration);
51
72
  watchOptions = webpackConfiguration.watchOptions;
52
73
  watch = webpackConfiguration.watch;
53
74
  }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Detect whether the target project uses ESM output.
3
+ * Checks the project's package.json for `"type": "module"`.
4
+ */
5
+ export declare function isEsmProject(cwd?: string): boolean;
@@ -0,0 +1,16 @@
1
+ import { readFileSync } from 'fs';
2
+ import { join } from 'path';
3
+ /**
4
+ * Detect whether the target project uses ESM output.
5
+ * Checks the project's package.json for `"type": "module"`.
6
+ */
7
+ export function isEsmProject(cwd = process.cwd()) {
8
+ try {
9
+ const raw = readFileSync(join(cwd, 'package.json'), 'utf-8');
10
+ const pkg = JSON.parse(raw);
11
+ return pkg.type === 'module';
12
+ }
13
+ catch {
14
+ return false;
15
+ }
16
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nestjs/cli",
3
- "version": "12.0.0-alpha.0",
3
+ "version": "12.0.0-alpha.2",
4
4
  "type": "module",
5
5
  "description": "Nest - modern, fast, powerful node.js web framework (@cli)",
6
6
  "publishConfig": {
@@ -28,8 +28,7 @@
28
28
  "test:dev": "npm run clean && vitest --watch",
29
29
  "prerelease": "npm run build",
30
30
  "release": "release-it",
31
- "prepare": "husky",
32
- "postinstall": "node tools/postinstall.cjs"
31
+ "prepare": "husky && node tools/postinstall.cjs"
33
32
  },
34
33
  "repository": {
35
34
  "type": "git",
@@ -50,28 +49,25 @@
50
49
  "chokidar": "4.0.3",
51
50
  "cli-table3": "0.6.5",
52
51
  "commander": "14.0.3",
53
- "fork-ts-checker-webpack-plugin": "9.1.0",
54
52
  "glob": "13.0.6",
55
53
  "node-emoji": "2.2.0",
56
54
  "ora": "9.3.0",
57
55
  "tsconfig-paths": "4.2.0",
58
- "tsconfig-paths-webpack-plugin": "4.2.0",
59
- "typescript": "5.9.3",
60
- "webpack": "5.105.4",
61
- "webpack-node-externals": "3.0.0"
56
+ "typescript": "5.9.3"
62
57
  },
63
58
  "devDependencies": {
64
59
  "@commitlint/cli": "20.4.3",
65
60
  "@commitlint/config-angular": "20.4.3",
61
+ "@eslint/js": "10.0.1",
62
+ "@rspack/core": "^1.7.7",
66
63
  "@swc/cli": "0.8.0",
67
64
  "@swc/core": "1.15.18",
68
65
  "@types/node": "24.10.13",
69
66
  "@types/webpack-node-externals": "3.0.4",
70
- "@eslint/js": "10.0.1",
71
67
  "delete-empty": "3.0.0",
72
68
  "eslint": "10.0.2",
73
69
  "eslint-config-prettier": "10.1.8",
74
- "typescript-eslint": "8.56.1",
70
+ "fork-ts-checker-webpack-plugin": "9.1.0",
75
71
  "gulp": "5.0.1",
76
72
  "gulp-clean": "0.4.0",
77
73
  "husky": "9.1.7",
@@ -79,21 +75,49 @@
79
75
  "prettier": "3.8.1",
80
76
  "release-it": "19.2.4",
81
77
  "ts-loader": "9.5.4",
82
- "vitest": "3.2.4"
78
+ "tsconfig-paths-webpack-plugin": "4.2.0",
79
+ "typescript-eslint": "8.56.1",
80
+ "vitest": "3.2.4",
81
+ "webpack": "5.105.4",
82
+ "webpack-node-externals": "3.0.0"
83
83
  },
84
84
  "lint-staged": {
85
85
  "**/*.{ts,json}": []
86
86
  },
87
87
  "peerDependencies": {
88
+ "@rspack/core": "^1.0.0",
88
89
  "@swc/cli": "^0.1.62 || ^0.3.0 || ^0.4.0 || ^0.5.0 || ^0.6.0 || ^0.7.0 || ^0.8.0",
89
- "@swc/core": "^1.3.62"
90
+ "@swc/core": "^1.3.62",
91
+ "fork-ts-checker-webpack-plugin": "^9.0.0",
92
+ "ts-loader": "^9.0.0",
93
+ "tsconfig-paths-webpack-plugin": "^4.0.0",
94
+ "webpack": "^5.0.0",
95
+ "webpack-node-externals": "^3.0.0"
90
96
  },
91
97
  "peerDependenciesMeta": {
98
+ "@rspack/core": {
99
+ "optional": true
100
+ },
92
101
  "@swc/cli": {
93
102
  "optional": true
94
103
  },
95
104
  "@swc/core": {
96
105
  "optional": true
106
+ },
107
+ "fork-ts-checker-webpack-plugin": {
108
+ "optional": true
109
+ },
110
+ "ts-loader": {
111
+ "optional": true
112
+ },
113
+ "tsconfig-paths-webpack-plugin": {
114
+ "optional": true
115
+ },
116
+ "webpack": {
117
+ "optional": true
118
+ },
119
+ "webpack-node-externals": {
120
+ "optional": true
97
121
  }
98
122
  }
99
123
  }