@depup/nestjs__cli 12.0.0-depup.0 → 12.0.1-depup.0

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.
package/README.md CHANGED
@@ -13,18 +13,16 @@ npm install @depup/nestjs__cli
13
13
 
14
14
  | Field | Value |
15
15
  |-------|-------|
16
- | Original | [@nestjs/cli](https://www.npmjs.com/package/@nestjs/cli) @ 12.0.0 |
17
- | Processed | 2026-08-27 |
16
+ | Original | [@nestjs/cli](https://www.npmjs.com/package/@nestjs/cli) @ 12.0.1 |
17
+ | Processed | 2026-09-14 |
18
18
  | Smoke test | failed |
19
- | Deps updated | 4 |
19
+ | Deps updated | 2 |
20
20
 
21
21
  ## Dependency Changes
22
22
 
23
23
  | Dependency | From | To |
24
24
  |------------|------|-----|
25
- | @angular-devkit/core | 22.1.5 | ^22.1.6 |
26
- | @angular-devkit/schematics | 22.1.5 | ^22.1.6 |
27
- | @angular-devkit/schematics-cli | 22.1.5 | ^22.1.6 |
25
+ | @nestjs/schematics | ^12.0.0 | ^12.0.2 |
28
26
  | typescript | ~6.0.2 | ^7.0.2 |
29
27
 
30
28
  ---
@@ -1,6 +1,4 @@
1
- import { createRequire } from 'module';
2
1
  import { red } from 'ansis';
3
- import { join } from 'path';
4
2
  import { AssetsManager } from '../lib/compiler/assets-manager.js';
5
3
  import { deleteOutDirIfEnabled } from '../lib/compiler/helpers/delete-out-dir.js';
6
4
  import { getBuilder } from '../lib/compiler/helpers/get-builder.js';
@@ -16,9 +14,8 @@ import { NestConfigurationLoader, } from '../lib/configuration/index.js';
16
14
  import { defaultOutDir, defaultRspackConfigFilename, defaultWebpackConfigFilename, } from '../lib/configuration/defaults.js';
17
15
  import { FileSystemReader } from '../lib/readers/index.js';
18
16
  import { ERROR_PREFIX, INFO_PREFIX } from '../lib/ui/index.js';
19
- import { isModuleAvailable } from '../lib/utils/is-module-available.js';
17
+ import { loadBuilderConfig } from '../lib/utils/load-builder-config.js';
20
18
  import { AbstractAction } from './abstract.action.js';
21
- const require = createRequire(import.meta.url);
22
19
  export class BuildAction extends AbstractAction {
23
20
  pluginsLoader = new PluginsLoader();
24
21
  tsLoader = new TypeScriptBinaryLoader();
@@ -155,7 +152,7 @@ export class BuildAction extends AbstractAction {
155
152
  const webpackCompiler = new WebpackCompiler(this.pluginsLoader);
156
153
  const webpackPath = getWebpackConfigPath(configuration, options, appName) ??
157
154
  defaultWebpackConfigFilename;
158
- const webpackConfigFactoryOrConfig = this.getWebpackConfigFactoryByPath(webpackPath, defaultWebpackConfigFilename);
155
+ const webpackConfigFactoryOrConfig = await this.getWebpackConfigFactoryByPath(webpackPath, defaultWebpackConfigFilename);
159
156
  return webpackCompiler.run(configuration, pathToTsconfig, appName, {
160
157
  options,
161
158
  webpackConfigFactoryOrConfig,
@@ -168,8 +165,10 @@ export class BuildAction extends AbstractAction {
168
165
  if (watchMode) {
169
166
  const { WatchCompiler } = await import('../lib/compiler/watch-compiler.js');
170
167
  const watchCompiler = new WatchCompiler(this.pluginsLoader, this.tsConfigProvider, this.tsLoader);
171
- const isPreserveWatchOutputEnabled = !!options.preserveWatchOutput;
172
- watchCompiler.run(configuration, pathToTsconfig, appName, { preserveWatchOutput: isPreserveWatchOutputEnabled }, onSuccess);
168
+ watchCompiler.run(configuration, pathToTsconfig, appName,
169
+ // Left undefined when the flag is absent so `WatchCompiler` can
170
+ // fall through to the tsconfig 'preserveWatchOutput' option.
171
+ { preserveWatchOutput: options.preserveWatchOutput }, onSuccess);
173
172
  }
174
173
  else {
175
174
  const { Compiler } = await import('../lib/compiler/compiler.js');
@@ -178,20 +177,15 @@ export class BuildAction extends AbstractAction {
178
177
  await assetsManager.closeWatchers();
179
178
  }
180
179
  }
181
- getWebpackConfigFactoryByPath(webpackPath, defaultPath) {
182
- const pathToWebpackFile = join(process.cwd(), webpackPath);
183
- const isWebpackFileAvailable = isModuleAvailable(pathToWebpackFile);
184
- if (!isWebpackFileAvailable && webpackPath === defaultPath) {
185
- return (_config) => ({});
186
- }
187
- return require(pathToWebpackFile);
180
+ async getWebpackConfigFactoryByPath(webpackPath, defaultPath) {
181
+ return loadBuilderConfig(webpackPath, defaultPath);
188
182
  }
189
183
  async runRspack(configuration, appName, options, pathToTsconfig, tsOptions, debug, watchMode, onSuccess, assetsManager) {
190
184
  const { RspackCompiler } = await import('../lib/compiler/rspack-compiler.js');
191
185
  const rspackCompiler = new RspackCompiler(this.pluginsLoader);
192
186
  const rspackPath = getRspackConfigPath(configuration, options, appName) ??
193
187
  defaultRspackConfigFilename;
194
- const rspackConfigFactoryOrConfig = this.getRspackConfigFactoryByPath(rspackPath, defaultRspackConfigFilename);
188
+ const rspackConfigFactoryOrConfig = await this.getRspackConfigFactoryByPath(rspackPath, defaultRspackConfigFilename);
195
189
  return rspackCompiler.run(configuration, pathToTsconfig, appName, {
196
190
  options,
197
191
  rspackConfigFactoryOrConfig,
@@ -201,13 +195,8 @@ export class BuildAction extends AbstractAction {
201
195
  assetsManager,
202
196
  }, onSuccess);
203
197
  }
204
- getRspackConfigFactoryByPath(rspackPath, defaultPath) {
205
- const pathToRspackFile = join(process.cwd(), rspackPath);
206
- const isRspackFileAvailable = isModuleAvailable(pathToRspackFile);
207
- if (!isRspackFileAvailable && rspackPath === defaultPath) {
208
- return (_config) => ({});
209
- }
210
- return require(pathToRspackFile);
198
+ async getRspackConfigFactoryByPath(rspackPath, defaultPath) {
199
+ return loadBuilderConfig(rspackPath, defaultPath);
211
200
  }
212
201
  warnOnIgnoredLibraryAssets(configuration, appNames) {
213
202
  if (!configuration.projects) {
package/changes.json CHANGED
@@ -1,22 +1,14 @@
1
1
  {
2
2
  "bumped": {
3
- "@angular-devkit/core": {
4
- "from": "22.1.5",
5
- "to": "^22.1.6"
6
- },
7
- "@angular-devkit/schematics": {
8
- "from": "22.1.5",
9
- "to": "^22.1.6"
10
- },
11
- "@angular-devkit/schematics-cli": {
12
- "from": "22.1.5",
13
- "to": "^22.1.6"
3
+ "@nestjs/schematics": {
4
+ "from": "^12.0.0",
5
+ "to": "^12.0.2"
14
6
  },
15
7
  "typescript": {
16
8
  "from": "~6.0.2",
17
9
  "to": "^7.0.2"
18
10
  }
19
11
  },
20
- "timestamp": "2026-08-27T11:23:37.886Z",
21
- "totalUpdated": 4
12
+ "timestamp": "2026-09-14T16:08:56.059Z",
13
+ "totalUpdated": 2
22
14
  }
@@ -58,9 +58,11 @@ export class BuildCommand extends AbstractCommand {
58
58
  // still fall through to `compilerOptions.emitDeclarations`.
59
59
  emitDeclarations: options.emitDeclarations,
60
60
  silent: !!options.silent,
61
- preserveWatchOutput: !!options.preserveWatchOutput &&
62
- !!options.watch &&
63
- !isWebpackEnabled,
61
+ // Left undefined when the flag is absent so `WatchCompiler` can
62
+ // fall through to the tsconfig 'preserveWatchOutput' option.
63
+ preserveWatchOutput: !!options.watch && !isWebpackEnabled
64
+ ? options.preserveWatchOutput
65
+ : false,
64
66
  all: !!options.all,
65
67
  parallel,
66
68
  };
@@ -11,7 +11,7 @@ export interface BuildCommandContext {
11
11
  typeCheck?: boolean;
12
12
  emitDeclarations?: boolean;
13
13
  silent?: boolean;
14
- preserveWatchOutput: boolean;
14
+ preserveWatchOutput?: boolean;
15
15
  all: boolean;
16
16
  parallel?: number | boolean;
17
17
  }
@@ -11,7 +11,7 @@ export interface StartCommandContext {
11
11
  typeCheck?: boolean;
12
12
  emitDeclarations?: boolean;
13
13
  silent?: boolean;
14
- preserveWatchOutput: boolean;
14
+ preserveWatchOutput?: boolean;
15
15
  debug?: boolean | string;
16
16
  exec?: string;
17
17
  sourceRoot?: string;
@@ -57,8 +57,19 @@ export class GenerateCommand extends AbstractCommand {
57
57
  }
58
58
  buildSchematicsListAsTable(schematics) {
59
59
  const leftMargin = ' ';
60
+ if ((process.stdout.columns ?? 80) < 80) {
61
+ return schematics
62
+ .map((schematic) => {
63
+ const header = `${leftMargin}${green(schematic.name)} ${cyan(schematic.alias)}`;
64
+ return schematic.description
65
+ ? `${header}\n${leftMargin} ${schematic.description}`
66
+ : header;
67
+ })
68
+ .join('\n');
69
+ }
60
70
  const tableConfig = {
61
71
  head: ['name', 'alias', 'description'],
72
+ wordWrap: true,
62
73
  chars: {
63
74
  'left': leftMargin.concat('│'),
64
75
  'top-left': leftMargin.concat('┌'),
@@ -57,9 +57,11 @@ export class StartCommand extends AbstractCommand {
57
57
  // still fall through to `compilerOptions.emitDeclarations`.
58
58
  emitDeclarations: options.emitDeclarations,
59
59
  silent: !!options.silent,
60
- preserveWatchOutput: !!options.preserveWatchOutput &&
61
- !!options.watch &&
62
- !isWebpackEnabled,
60
+ // Left undefined when the flag is absent so `WatchCompiler` can
61
+ // fall through to the tsconfig 'preserveWatchOutput' option.
62
+ preserveWatchOutput: !!options.watch && !isWebpackEnabled
63
+ ? options.preserveWatchOutput
64
+ : false,
63
65
  debug: options.debug,
64
66
  exec: options.exec,
65
67
  sourceRoot: options.sourceRoot,
@@ -1,6 +1,6 @@
1
1
  import * as chokidar from 'chokidar';
2
2
  import { copyFileSync, mkdirSync, rmSync, statSync } from 'fs';
3
- import { dirname, join, sep } from 'path';
3
+ import { dirname, join, resolve as resolvePath, sep } from 'path';
4
4
  import { ERROR_PREFIX } from '../ui/index.js';
5
5
  import { copyPathResolve } from './helpers/copy-path-resolve.js';
6
6
  import { globSync } from './helpers/glob.js';
@@ -171,6 +171,7 @@ export class AssetsManager {
171
171
  if (statSync(matched).isDirectory()) {
172
172
  return globSync(`${matched}/**/*`, {
173
173
  ignore: item.exclude,
174
+ dot: true,
174
175
  }).filter((file) => statSync(file).isFile());
175
176
  }
176
177
  return matched;
@@ -244,6 +245,17 @@ export class AssetsManager {
244
245
  // Set path value to true for watching the first time
245
246
  this.watchAssetsKeyValue[assetCheckKey] = true;
246
247
  let dest = copyPathResolve(path, item.outDir, sourceRoot.split(sep).length);
248
+ // When an "include" path resolves outside the strip root, stripping that
249
+ // root's segment count from the file's path can consume the filename
250
+ // itself, collapsing the destination to "outDir" — silently overwriting
251
+ // the output directory with the asset's contents before the compiler even
252
+ // runs. Fail loudly instead.
253
+ if (resolvePath(dest) === resolvePath(item.outDir)) {
254
+ throw new Error(`Refusing to copy "${path}" to "${item.outDir}": the "include" path resolves outside ` +
255
+ `"${sourceRoot}", so no path segment survives stripping and the file would overwrite ` +
256
+ `the "${item.outDir}" directory itself. Move the file inside "${sourceRoot}", or set ` +
257
+ `"rootDir" in your tsconfig to a directory that contains both it and your sources.`);
258
+ }
247
259
  // The destination is re-checked per file: the configured "outDir" is
248
260
  // validated up front, but a symlinked directory *inside* it would still
249
261
  // redirect an individual write out of the project.
@@ -0,0 +1,10 @@
1
+ import * as ts from 'typescript';
2
+ /**
3
+ * Returns `true` when the consuming project uses an ESM-style module
4
+ * resolution strategy (`node16` / `nodenext`). Under those resolution
5
+ * modes, dynamic `import()` specifiers MUST include the file extension
6
+ * (typically `.js`) for the runtime resolver to find the module. Without
7
+ * the extension, executing the generated metadata file fails with
8
+ * `ERR_MODULE_NOT_FOUND`, and TypeScript reports a diagnostic.
9
+ */
10
+ export declare function requiresExplicitImportExtensions(options: ts.CompilerOptions, tsBinary: typeof ts): boolean;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Returns `true` when the consuming project uses an ESM-style module
3
+ * resolution strategy (`node16` / `nodenext`). Under those resolution
4
+ * modes, dynamic `import()` specifiers MUST include the file extension
5
+ * (typically `.js`) for the runtime resolver to find the module. Without
6
+ * the extension, executing the generated metadata file fails with
7
+ * `ERR_MODULE_NOT_FOUND`, and TypeScript reports a diagnostic.
8
+ */
9
+ export function requiresExplicitImportExtensions(options, tsBinary) {
10
+ const moduleResolution = options.moduleResolution;
11
+ return (moduleResolution === tsBinary.ModuleResolutionKind.Node16 ||
12
+ moduleResolution === tsBinary.ModuleResolutionKind.NodeNext);
13
+ }
@@ -1,12 +1,18 @@
1
+ import { existsSync } from 'fs';
1
2
  import { createRequire } from 'module';
2
3
  import { dirname, posix } from 'path';
3
4
  import * as tsPaths from 'tsconfig-paths';
5
+ import { requiresExplicitImportExtensions } from '../helpers/requires-explicit-import-extensions.js';
4
6
  import { TypeScriptBinaryLoader } from '../typescript-loader.js';
5
7
  const require = createRequire(import.meta.url);
6
8
  export function tsconfigPathsBeforeHookFactory(compilerOptions) {
7
9
  const tsBinary = new TypeScriptBinaryLoader().load();
8
10
  const { paths = {}, baseUrl = './' } = compilerOptions;
9
11
  const matcher = tsPaths.createMatchPath(baseUrl, paths, ['main']);
12
+ const esm = requiresExplicitImportExtensions(compilerOptions, tsBinary);
13
+ const extensions = sourceToOutputExtension(compilerOptions, tsBinary);
14
+ // Resolution is immutable within a build, and the hook runs per import.
15
+ const emittedPaths = new Map();
10
16
  return (ctx) => {
11
17
  return (sf) => {
12
18
  const visitNode = (node) => {
@@ -17,7 +23,7 @@ export function tsconfigPathsBeforeHookFactory(compilerOptions) {
17
23
  if (!text) {
18
24
  return node;
19
25
  }
20
- const result = getNotAliasedPath(sf, matcher, text);
26
+ const result = getNotAliasedPath(sf, matcher, text, esm, extensions, emittedPaths);
21
27
  if (!result) {
22
28
  return node;
23
29
  }
@@ -57,13 +63,71 @@ function getModuleSpecifierText(moduleSpecifier, sourceFile) {
57
63
  }
58
64
  return importPathWithQuotes.substring(1, importPathWithQuotes.length - 1);
59
65
  }
60
- function getNotAliasedPath(sf, matcher, text) {
61
- let result = matcher(text, undefined, undefined, [
62
- '.ts',
63
- '.tsx',
64
- '.js',
65
- '.jsx',
66
- ]);
66
+ // The matcher strips the extension off the file it found, so the path it
67
+ // returns cannot be used to tell which source file that was.
68
+ function sourceToOutputExtension(compilerOptions, tsBinary) {
69
+ // `jsx: preserve` leaves the syntax in place and emits `.jsx`; every other
70
+ // mode compiles it away.
71
+ const jsxOutput = compilerOptions.jsx === tsBinary.JsxEmit.Preserve ? '.jsx' : '.js';
72
+ return {
73
+ '.mts': '.mjs',
74
+ '.cts': '.cjs',
75
+ '.ts': '.js',
76
+ '.tsx': jsxOutput,
77
+ '.js': '.js',
78
+ '.jsx': jsxOutput,
79
+ };
80
+ }
81
+ const MATCHER_EXTENSIONS = ['.mts', '.cts', '.ts', '.tsx', '.js', '.jsx'];
82
+ /**
83
+ * Resolves an alias that ESM writes with the extension the file will have
84
+ * *after* emit. The matcher looks for `./foo.js` on disk, finds only
85
+ * `./foo.ts`, and gives up, so the alias is emitted untouched and fails at
86
+ * runtime. Retrying without that extension resolves it to the source file.
87
+ */
88
+ function matchPath(matcher, text, esm) {
89
+ const result = matcher(text, undefined, undefined, MATCHER_EXTENSIONS);
90
+ if (result || !esm) {
91
+ return result;
92
+ }
93
+ const withoutOutputExtension = text.replace(/\.(m|c)?js$/, '');
94
+ return withoutOutputExtension === text
95
+ ? undefined
96
+ : matcher(withoutOutputExtension, undefined, undefined, MATCHER_EXTENSIONS);
97
+ }
98
+ /**
99
+ * Probes the disk to learn which source file the matcher resolved, and returns
100
+ * it with the extension it will carry after emit. ESM has no directory or
101
+ * extensionless resolution, so the specifier must name the emitted file, and
102
+ * the extension cannot be read off a path the matcher already stripped.
103
+ */
104
+ function toEmittedPath(resolvedPath, extensions, cache) {
105
+ const cached = cache.get(resolvedPath);
106
+ if (cached !== undefined) {
107
+ return cached;
108
+ }
109
+ const entries = Object.entries(extensions);
110
+ // An alias that names the file keeps its extension through the matcher.
111
+ for (const [source, output] of entries) {
112
+ if (resolvedPath.endsWith(source)) {
113
+ return remember(cache, resolvedPath, resolvedPath.slice(0, -source.length) + output);
114
+ }
115
+ }
116
+ for (const candidate of [resolvedPath, posix.join(resolvedPath, 'index')]) {
117
+ for (const [source, output] of entries) {
118
+ if (existsSync(`${candidate}${source}`)) {
119
+ return remember(cache, resolvedPath, `${candidate}${output}`);
120
+ }
121
+ }
122
+ }
123
+ return remember(cache, resolvedPath, resolvedPath);
124
+ }
125
+ function remember(cache, key, value) {
126
+ cache.set(key, value);
127
+ return value;
128
+ }
129
+ function getNotAliasedPath(sf, matcher, text, esm = false, extensions = {}, emittedPaths = new Map()) {
130
+ let result = matchPath(matcher, text, esm);
67
131
  if (!result) {
68
132
  return;
69
133
  }
@@ -83,6 +147,9 @@ function getNotAliasedPath(sf, matcher, text) {
83
147
  catch {
84
148
  // package resolution failed, fall through to relative path
85
149
  }
150
+ if (esm) {
151
+ result = toEmittedPath(result, extensions, emittedPaths);
152
+ }
86
153
  const resolvedPath = posix.relative(dirname(sf.fileName), result) || './';
87
154
  return resolvedPath[0] === '.' ? resolvedPath : './' + resolvedPath;
88
155
  }
@@ -1,14 +1,5 @@
1
1
  import * as ts from 'typescript';
2
2
  import { DeepPluginMeta, ReadonlyVisitor } from '../interfaces/readonly-visitor.interface.js';
3
- /**
4
- * Returns `true` when the consuming project uses an ESM-style module
5
- * resolution strategy (`node16` / `nodenext`). Under those resolution
6
- * modes, dynamic `import()` specifiers MUST include the file extension
7
- * (typically `.js`) for the runtime resolver to find the module. Without
8
- * the extension, executing the generated metadata file fails with
9
- * `ERR_MODULE_NOT_FOUND`, and TypeScript reports a diagnostic.
10
- */
11
- export declare function requiresExplicitImportExtensions(options: ts.CompilerOptions, tsBinary: typeof ts): boolean;
12
3
  /**
13
4
  * Returns the same import path with `.js` appended when (and only when)
14
5
  * the path is relative and does not already end in a recognized
@@ -1,20 +1,8 @@
1
+ import { requiresExplicitImportExtensions } from '../helpers/requires-explicit-import-extensions.js';
1
2
  import { FOUND_NO_ISSUES_GENERATING_METADATA } from '../swc/constants.js';
2
3
  import { TypeCheckerHost } from '../swc/type-checker-host.js';
3
4
  import { TypeScriptBinaryLoader } from '../typescript-loader.js';
4
5
  import { PluginMetadataPrinter } from './plugin-metadata-printer.js';
5
- /**
6
- * Returns `true` when the consuming project uses an ESM-style module
7
- * resolution strategy (`node16` / `nodenext`). Under those resolution
8
- * modes, dynamic `import()` specifiers MUST include the file extension
9
- * (typically `.js`) for the runtime resolver to find the module. Without
10
- * the extension, executing the generated metadata file fails with
11
- * `ERR_MODULE_NOT_FOUND`, and TypeScript reports a diagnostic.
12
- */
13
- export function requiresExplicitImportExtensions(options, tsBinary) {
14
- const moduleResolution = options.moduleResolution;
15
- return (moduleResolution === tsBinary.ModuleResolutionKind.Node16 ||
16
- moduleResolution === tsBinary.ModuleResolutionKind.NodeNext);
17
- }
18
6
  const RELATIVE_PATH_RE = /^\.\.?\//;
19
7
  // Any common JS/TS-style extension that the user could have authored or
20
8
  // that our rewrite would have already produced. Prevents double-appending.
@@ -26,5 +26,6 @@ export declare class PluginsLoader {
26
26
  pathToSource?: string;
27
27
  }): MultiNestCompilerPlugins;
28
28
  private resolvePluginReferences;
29
+ private resolvePluginPath;
29
30
  }
30
31
  export {};
@@ -49,22 +49,33 @@ export class PluginsLoader {
49
49
  ...(require.resolve.paths('typescript') ?? []),
50
50
  ];
51
51
  return pluginNames.map((item) => {
52
+ const binaryPath = this.resolvePluginPath(item, nodeModulePaths);
52
53
  try {
53
- try {
54
- const binaryPath = require.resolve(`${item}/${PLUGIN_ENTRY_FILENAME}`, {
55
- paths: nodeModulePaths,
56
- });
57
- return require(binaryPath);
58
- }
59
- catch {
60
- // entry-point resolution failed, try bare module resolve
61
- }
62
- const binaryPath = require.resolve(item, { paths: nodeModulePaths });
63
54
  return require(binaryPath);
64
55
  }
65
56
  catch (e) {
66
- throw new Error(`"${item}" plugin is not installed.`, { cause: e });
57
+ // Resolution succeeded, so the plugin IS installed — it crashed while
58
+ // being evaluated (e.g. its own imports are incompatible with the
59
+ // TypeScript version it ended up resolving). Surface the real reason
60
+ // instead of falling through to a misleading "not compatible" error.
61
+ throw new Error(`"${item}" plugin failed to load: ${e?.message ?? e}`, { cause: e });
67
62
  }
68
63
  });
69
64
  }
65
+ resolvePluginPath(item, nodeModulePaths) {
66
+ try {
67
+ return require.resolve(`${item}/${PLUGIN_ENTRY_FILENAME}`, {
68
+ paths: nodeModulePaths,
69
+ });
70
+ }
71
+ catch {
72
+ // entry-point resolution failed, try bare module resolve
73
+ }
74
+ try {
75
+ return require.resolve(item, { paths: nodeModulePaths });
76
+ }
77
+ catch (e) {
78
+ throw new Error(`"${item}" plugin is not installed.`, { cause: e });
79
+ }
80
+ }
70
81
  }
@@ -3,9 +3,9 @@ import { Configuration } from '../configuration/index.js';
3
3
  import { AssetsManager } from './assets-manager.js';
4
4
  import { BaseCompiler } from './base-compiler.js';
5
5
  import { PluginsLoader } from './plugins/plugins-loader.js';
6
- type RspackConfigFactory = (config: Record<string, any>, rspackRef: any) => Record<string, any>;
7
- type RspackConfigFactoryOrConfig = RspackConfigFactory | Record<string, any>;
8
- type RspackCompilerExtras = {
6
+ export type RspackConfigFactory = (config: Record<string, any>, rspackRef: any) => Record<string, any>;
7
+ export type RspackConfigFactoryOrConfig = RspackConfigFactory | Record<string, any>;
8
+ export type RspackCompilerExtras = {
9
9
  options: Record<string, any>;
10
10
  assetsManager: AssetsManager;
11
11
  rspackConfigFactoryOrConfig: RspackConfigFactoryOrConfig | RspackConfigFactoryOrConfig[];
@@ -18,4 +18,3 @@ export declare class RspackCompiler extends BaseCompiler<RspackCompilerExtras> {
18
18
  run(configuration: Required<Configuration>, tsConfigPath: string, appName: string | undefined, extras: RspackCompilerExtras, onSuccess?: () => void): void;
19
19
  private createAfterCallback;
20
20
  }
21
- export {};
@@ -1,6 +1,6 @@
1
1
  import { existsSync } from 'fs';
2
2
  import { createRequire } from 'module';
3
- import { join } from 'path';
3
+ import { resolve } from 'path';
4
4
  import { ERROR_PREFIX, INFO_PREFIX } from '../ui/index.js';
5
5
  import { isEsmProject } from '../utils/is-esm-project.js';
6
6
  import { BaseCompiler } from './base-compiler.js';
@@ -13,7 +13,7 @@ export class RspackCompiler extends BaseCompiler {
13
13
  }
14
14
  run(configuration, tsConfigPath, appName, extras, onSuccess) {
15
15
  const cwd = process.cwd();
16
- const configPath = join(cwd, tsConfigPath);
16
+ const configPath = resolve(cwd, tsConfigPath);
17
17
  if (!existsSync(configPath)) {
18
18
  throw new Error(`Could not find TypeScript configuration file "${tsConfigPath}".`);
19
19
  }
@@ -21,7 +21,7 @@ export class RspackCompiler extends BaseCompiler {
21
21
  const pathToSource = this.getPathToSource(configuration, tsConfigPath, appName);
22
22
  const entryFile = getValueOrDefault(configuration, 'entryFile', appName, 'entryFile', extras.options);
23
23
  const entryFileRoot = getValueOrDefault(configuration, 'root', appName) || '';
24
- const defaultOptions = rspackDefaultsFactory(pathToSource, entryFileRoot, entryFile, extras.debug ?? false, tsConfigPath, plugins, isEsmProject(), extras.tsOptions);
24
+ const defaultOptions = rspackDefaultsFactory(pathToSource, entryFileRoot, entryFile, extras.debug ?? false, configPath, plugins, isEsmProject(), extras.tsOptions);
25
25
  let rspack;
26
26
  try {
27
27
  rspack = require('@rspack/core');
@@ -3,9 +3,9 @@ import { AssetsManager } from './assets-manager.js';
3
3
  import { BaseCompiler } from './base-compiler.js';
4
4
  import { PluginsLoader } from './plugins/plugins-loader.js';
5
5
  import type webpack from 'webpack';
6
- type WebpackConfigFactory = (config: webpack.Configuration, webpackRef: typeof webpack) => webpack.Configuration;
7
- type WebpackConfigFactoryOrConfig = WebpackConfigFactory | webpack.Configuration;
8
- type WebpackCompilerExtras = {
6
+ export type WebpackConfigFactory = (config: webpack.Configuration, webpackRef: typeof webpack) => webpack.Configuration;
7
+ export type WebpackConfigFactoryOrConfig = WebpackConfigFactory | webpack.Configuration;
8
+ export type WebpackCompilerExtras = {
9
9
  options: Record<string, any>;
10
10
  assetsManager: AssetsManager;
11
11
  webpackConfigFactoryOrConfig: WebpackConfigFactoryOrConfig | WebpackConfigFactoryOrConfig[];
@@ -17,4 +17,3 @@ export declare class WebpackCompiler extends BaseCompiler<WebpackCompilerExtras>
17
17
  run(configuration: Required<Configuration>, tsConfigPath: string, appName: string | undefined, extras: WebpackCompilerExtras, onSuccess?: () => void): void;
18
18
  private createAfterCallback;
19
19
  }
20
- export {};
@@ -4,4 +4,4 @@ export declare const defaultTsconfigFilename: string;
4
4
  export declare const defaultWebpackConfigFilename = "webpack.config.js";
5
5
  export declare const defaultRspackConfigFilename = "rspack.config.js";
6
6
  export declare const defaultOutDir = "dist";
7
- export declare const defaultGitIgnore = "# compiled output\n/dist\n/node_modules\n/build\n\n# Logs\nlogs\n*.log\nnpm-debug.log*\npnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\nlerna-debug.log*\n\n# OS\n.DS_Store\n\n# Tests\n/coverage\n/.nyc_output\n\n# IDEs and editors\n/.idea\n.project\n.classpath\n.c9/\n*.launch\n.settings/\n*.sublime-workspace\n\n# IDE - VSCode\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json\n\n# dotenv environment variable files\n.env\n.env.development.local\n.env.test.local\n.env.production.local\n.env.local\n\n# temp directory\n.temp\n.tmp\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Diagnostic reports (https://nodejs.org/api/report.html)\nreport.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json\n";
7
+ export declare const defaultGitIgnore = "# compiled output\n/dist\n/node_modules\n/build\n\n# TypeScript build cache\n*.tsbuildinfo\n\n# Logs\nlogs\n*.log\nnpm-debug.log*\npnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\nlerna-debug.log*\n\n# OS\n.DS_Store\n\n# Tests\n/coverage\n/.nyc_output\n\n# IDEs and editors\n/.idea\n.project\n.classpath\n.c9/\n*.launch\n.settings/\n*.sublime-workspace\n\n# IDE - VSCode\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json\n\n# dotenv environment variable files\n.env\n.env.development.local\n.env.test.local\n.env.production.local\n.env.local\n\n# temp directory\n.temp\n.tmp\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Diagnostic reports (https://nodejs.org/api/report.html)\nreport.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json\n";
@@ -30,6 +30,9 @@ export const defaultGitIgnore = `# compiled output
30
30
  /node_modules
31
31
  /build
32
32
 
33
+ # TypeScript build cache
34
+ *.tsbuildinfo
35
+
33
36
  # Logs
34
37
  logs
35
38
  *.log
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Loads a builder (webpack/rspack) configuration file, which may be CommonJS,
3
+ * native ESM, or JSON. When `configPath` is the builder's default filename and
4
+ * no such file exists, the project simply has no overrides, so an identity
5
+ * factory is returned; an explicitly configured path that cannot be found is
6
+ * an error.
7
+ */
8
+ export declare function loadBuilderConfig<T = any>(configPath: string, defaultPath: string, cwd?: string): Promise<T>;
@@ -0,0 +1,40 @@
1
+ import { existsSync } from 'fs';
2
+ import { createRequire } from 'module';
3
+ import { extname, join } from 'path';
4
+ import { pathToFileURL } from 'url';
5
+ import { resolveModulePath } from './resolve-module-path.js';
6
+ const require = createRequire(import.meta.url);
7
+ /**
8
+ * Loads a builder (webpack/rspack) configuration file, which may be CommonJS,
9
+ * native ESM, or JSON. When `configPath` is the builder's default filename and
10
+ * no such file exists, the project simply has no overrides, so an identity
11
+ * factory is returned; an explicitly configured path that cannot be found is
12
+ * an error.
13
+ */
14
+ export async function loadBuilderConfig(configPath, defaultPath, cwd = process.cwd()) {
15
+ const pathToConfigFile = join(cwd, configPath);
16
+ // `require.resolve` handles extensionless and directory-index paths, but
17
+ // does not know about ESM-only extensions, hence the `existsSync` fallback.
18
+ const resolvedPath = resolveModulePath(pathToConfigFile) ??
19
+ (existsSync(pathToConfigFile) ? pathToConfigFile : undefined);
20
+ if (!resolvedPath) {
21
+ if (configPath === defaultPath) {
22
+ return ((_config) => ({}));
23
+ }
24
+ throw new Error(`Could not find the builder configuration file "${configPath}".`);
25
+ }
26
+ if (extname(resolvedPath) === '.json') {
27
+ return require(resolvedPath);
28
+ }
29
+ const imported = await import(pathToFileURL(resolvedPath).href);
30
+ const result = imported.default ?? imported;
31
+ // A CommonJS file compiled from TypeScript exposes its real export under a
32
+ // second `default`, behind the `__esModule` marker Node preserves as-is.
33
+ return (isTranspiledEsModule(result) ? result.default : result);
34
+ }
35
+ function isTranspiledEsModule(value) {
36
+ return (!!value &&
37
+ typeof value === 'object' &&
38
+ value.__esModule === true &&
39
+ 'default' in value);
40
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Resolves `path` through Node's module resolution, returning the resolved
3
+ * filename or `undefined` when it cannot be found. Callers need the resolved
4
+ * path itself (to decide how to load the file), not merely whether it exists.
5
+ */
6
+ export declare function resolveModulePath(path: string): string | undefined;
@@ -0,0 +1,15 @@
1
+ import { createRequire } from 'module';
2
+ const require = createRequire(import.meta.url);
3
+ /**
4
+ * Resolves `path` through Node's module resolution, returning the resolved
5
+ * filename or `undefined` when it cannot be found. Callers need the resolved
6
+ * path itself (to decide how to load the file), not merely whether it exists.
7
+ */
8
+ export function resolveModulePath(path) {
9
+ try {
10
+ return require.resolve(path);
11
+ }
12
+ catch {
13
+ return undefined;
14
+ }
15
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@depup/nestjs__cli",
3
- "version": "12.0.0-depup.0",
3
+ "version": "12.0.1-depup.0",
4
4
  "type": "module",
5
5
  "description": "Nest - modern, fast, powerful node.js web framework (@cli) (with updated dependencies)",
6
6
  "engines": {
@@ -35,12 +35,12 @@
35
35
  },
36
36
  "homepage": "https://github.com/nestjs/nest-cli#readme",
37
37
  "dependencies": {
38
- "@angular-devkit/core": "^22.1.6",
39
- "@angular-devkit/schematics": "^22.1.6",
40
- "@angular-devkit/schematics-cli": "^22.1.6",
41
- "@inquirer/prompts": "8.7.0",
42
- "@nestjs/schematics": "^12.0.0",
43
- "ansis": "4.3.1",
38
+ "@angular-devkit/core": "22.1.8",
39
+ "@angular-devkit/schematics": "22.1.8",
40
+ "@angular-devkit/schematics-cli": "22.1.8",
41
+ "@inquirer/prompts": "8.7.2",
42
+ "@nestjs/schematics": "^12.0.2",
43
+ "ansis": "4.4.0",
44
44
  "chokidar": "5.0.0",
45
45
  "cli-table3": "0.6.5",
46
46
  "commander": "15.0.0",
@@ -55,22 +55,23 @@
55
55
  "@commitlint/config-angular": "21.2.2",
56
56
  "@rspack/core": "^2.0.0",
57
57
  "@swc/cli": "0.8.1",
58
- "@swc/core": "1.16.1",
59
- "@types/node": "25.9.5",
58
+ "@swc/core": "1.16.2",
59
+ "@types/node": "25.9.6",
60
60
  "@types/webpack-node-externals": "3.0.4",
61
61
  "delete-empty": "3.0.0",
62
62
  "fork-ts-checker-webpack-plugin": "9.1.0",
63
63
  "gulp": "5.0.1",
64
64
  "gulp-clean": "0.4.0",
65
65
  "husky": "9.1.7",
66
- "lint-staged": "17.3.0",
67
- "oxlint": "1.80.0",
66
+ "lint-staged": "17.5.1",
67
+ "oxlint": "1.82.0",
68
68
  "prettier": "3.9.6",
69
- "release-it": "21.0.2",
69
+ "release-it": "21.0.3",
70
70
  "ts-loader": "9.6.2",
71
71
  "tsconfig-paths-webpack-plugin": "4.2.0",
72
- "vitest": "4.1.11",
73
- "webpack": "5.109.2",
72
+ "vite": "8.3.0",
73
+ "vitest": "5.0.0",
74
+ "webpack": "5.111.0",
74
75
  "webpack-node-externals": "3.0.0"
75
76
  },
76
77
  "lint-staged": {
@@ -122,27 +123,19 @@
122
123
  ],
123
124
  "depup": {
124
125
  "changes": {
125
- "@angular-devkit/core": {
126
- "from": "22.1.5",
127
- "to": "^22.1.6"
128
- },
129
- "@angular-devkit/schematics": {
130
- "from": "22.1.5",
131
- "to": "^22.1.6"
132
- },
133
- "@angular-devkit/schematics-cli": {
134
- "from": "22.1.5",
135
- "to": "^22.1.6"
126
+ "@nestjs/schematics": {
127
+ "from": "^12.0.0",
128
+ "to": "^12.0.2"
136
129
  },
137
130
  "typescript": {
138
131
  "from": "~6.0.2",
139
132
  "to": "^7.0.2"
140
133
  }
141
134
  },
142
- "depsUpdated": 4,
135
+ "depsUpdated": 2,
143
136
  "originalPackage": "@nestjs/cli",
144
- "originalVersion": "12.0.0",
145
- "processedAt": "2026-08-27T11:23:55.035Z",
137
+ "originalVersion": "12.0.1",
138
+ "processedAt": "2026-09-14T16:09:17.970Z",
146
139
  "smokeTest": "failed"
147
140
  }
148
141
  }
@@ -1 +0,0 @@
1
- export declare function isModuleAvailable(path: string): boolean;
@@ -1,11 +0,0 @@
1
- import { createRequire } from 'module';
2
- const require = createRequire(import.meta.url);
3
- export function isModuleAvailable(path) {
4
- try {
5
- require.resolve(path);
6
- return true;
7
- }
8
- catch {
9
- return false;
10
- }
11
- }