@nx/angular 21.2.0-canary.20250529-c8a6ffb → 21.2.0-canary.20250603-88c5196

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/angular",
3
- "version": "21.2.0-canary.20250529-c8a6ffb",
3
+ "version": "21.2.0-canary.20250603-88c5196",
4
4
  "private": false,
5
5
  "description": "The Nx Plugin for Angular contains executors, generators, and utilities for managing Angular applications and libraries within an Nx workspace. It provides: \n\n- Integration with libraries such as Storybook, Jest, ESLint, Tailwind CSS, Playwright and Cypress. \n\n- Generators to help scaffold code quickly (like: Micro Frontends, Libraries, both internal to your codebase and publishable to npm) \n\n- Single Component Application Modules (SCAMs) \n\n- NgRx helpers. \n\n- Utilities for automatic workspace refactoring.",
6
6
  "repository": {
@@ -58,14 +58,14 @@
58
58
  "migrations": "./migrations.json"
59
59
  },
60
60
  "dependencies": {
61
- "@nx/devkit": "21.2.0-canary.20250529-c8a6ffb",
62
- "@nx/eslint": "21.2.0-canary.20250529-c8a6ffb",
63
- "@nx/js": "21.2.0-canary.20250529-c8a6ffb",
64
- "@nx/module-federation": "21.2.0-canary.20250529-c8a6ffb",
65
- "@nx/rspack": "21.2.0-canary.20250529-c8a6ffb",
66
- "@nx/web": "21.2.0-canary.20250529-c8a6ffb",
67
- "@nx/webpack": "21.2.0-canary.20250529-c8a6ffb",
68
- "@nx/workspace": "21.2.0-canary.20250529-c8a6ffb",
61
+ "@nx/devkit": "21.2.0-canary.20250603-88c5196",
62
+ "@nx/eslint": "21.2.0-canary.20250603-88c5196",
63
+ "@nx/js": "21.2.0-canary.20250603-88c5196",
64
+ "@nx/module-federation": "21.2.0-canary.20250603-88c5196",
65
+ "@nx/rspack": "21.2.0-canary.20250603-88c5196",
66
+ "@nx/web": "21.2.0-canary.20250603-88c5196",
67
+ "@nx/webpack": "21.2.0-canary.20250603-88c5196",
68
+ "@nx/workspace": "21.2.0-canary.20250603-88c5196",
69
69
  "@phenomnomnominal/tsquery": "~5.0.1",
70
70
  "@typescript-eslint/type-utils": "^8.0.0",
71
71
  "enquirer": "~2.3.6",
@@ -6,10 +6,10 @@
6
6
  },
7
7
  "files": [],
8
8
  "include": [],
9
- "references": [
9
+ "references": [<% if (angularMajorVersion < 20) { %>
10
10
  {
11
11
  "path": "./tsconfig.editor.json"
12
- },
12
+ },<% } %>
13
13
  {
14
14
  "path": "./tsconfig.app.json"
15
15
  }
@@ -4,8 +4,8 @@ exports.updateTsconfigFiles = updateTsconfigFiles;
4
4
  const devkit_1 = require("@nx/devkit");
5
5
  const js_1 = require("@nx/js");
6
6
  const configuration_1 = require("@nx/js/src/utils/typescript/configuration");
7
- const semver_1 = require("semver");
8
7
  const ensure_typescript_1 = require("@nx/js/src/utils/typescript/ensure-typescript");
8
+ const semver_1 = require("semver");
9
9
  const update_app_editor_tsconfig_excluded_files_1 = require("../../utils/update-app-editor-tsconfig-excluded-files");
10
10
  const version_utils_1 = require("../../utils/version-utils");
11
11
  const enable_strict_type_checking_1 = require("./enable-strict-type-checking");
@@ -43,7 +43,8 @@ function updateTsconfigFiles(tree, options) {
43
43
  compilerOptions.esModuleInterop = true;
44
44
  }
45
45
  }
46
- (0, devkit_1.updateJson)(tree, `${options.appProjectRoot}/tsconfig.json`, (json) => {
46
+ const tsconfigPath = (0, devkit_1.joinPathFragments)(options.appProjectRoot, 'tsconfig.json');
47
+ (0, devkit_1.updateJson)(tree, tsconfigPath, (json) => {
47
48
  json.compilerOptions = {
48
49
  ...json.compilerOptions,
49
50
  ...compilerOptions,
@@ -51,8 +52,24 @@ function updateTsconfigFiles(tree, options) {
51
52
  json.compilerOptions = (0, configuration_1.getNeededCompilerOptionOverrides)(tree, json.compilerOptions, rootTsConfigPath);
52
53
  return json;
53
54
  });
55
+ if (options.unitTestRunner === 'jest') {
56
+ const tsconfigSpecPath = (0, devkit_1.joinPathFragments)(options.appProjectRoot, 'tsconfig.spec.json');
57
+ (0, devkit_1.updateJson)(tree, tsconfigSpecPath, (json) => {
58
+ json.compilerOptions = {
59
+ ...json.compilerOptions,
60
+ module: 'commonjs',
61
+ moduleResolution: 'node10',
62
+ };
63
+ json.compilerOptions = (0, configuration_1.getNeededCompilerOptionOverrides)(tree, json.compilerOptions, tsconfigPath);
64
+ return json;
65
+ });
66
+ }
54
67
  }
55
68
  function updateEditorTsConfig(tree, options) {
69
+ const tsconfigEditorPath = (0, devkit_1.joinPathFragments)(options.appProjectRoot, 'tsconfig.editor.json');
70
+ if (!tree.exists(tsconfigEditorPath)) {
71
+ return;
72
+ }
56
73
  const appTsConfig = (0, devkit_1.readJson)(tree, (0, devkit_1.joinPathFragments)(options.appProjectRoot, 'tsconfig.app.json'));
57
74
  const types = appTsConfig?.compilerOptions?.types ?? [];
58
75
  if (types?.length) {
@@ -1,4 +1,4 @@
1
- import { type Tree, GeneratorCallback } from '@nx/devkit';
1
+ import { type GeneratorCallback, type Tree } from '@nx/devkit';
2
2
  import type { ConvertToRspackSchema } from './schema';
3
3
  export declare function convertToRspack(tree: Tree, schema: ConvertToRspackSchema): Promise<GeneratorCallback>;
4
4
  export default convertToRspack;
@@ -2,15 +2,16 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.convertToRspack = convertToRspack;
4
4
  const devkit_1 = require("@nx/devkit");
5
+ const executor_options_utils_1 = require("@nx/devkit/src/generators/executor-options-utils");
6
+ const get_named_inputs_1 = require("@nx/devkit/src/utils/get-named-inputs");
7
+ const enquirer_1 = require("enquirer");
8
+ const path_1 = require("path");
9
+ const posix_1 = require("path/posix");
5
10
  const versions_1 = require("../../utils/versions");
6
11
  const create_config_1 = require("./lib/create-config");
7
12
  const get_custom_webpack_config_1 = require("./lib/get-custom-webpack-config");
8
13
  const update_tsconfig_1 = require("./lib/update-tsconfig");
9
14
  const validate_supported_executor_1 = require("./lib/validate-supported-executor");
10
- const posix_1 = require("path/posix");
11
- const path_1 = require("path");
12
- const executor_options_utils_1 = require("@nx/devkit/src/generators/executor-options-utils");
13
- const enquirer_1 = require("enquirer");
14
15
  const SUPPORTED_EXECUTORS = [
15
16
  '@angular-devkit/build-angular:browser',
16
17
  '@angular-devkit/build-angular:dev-server',
@@ -164,10 +165,6 @@ function handleBuildTargetOptions(tree, options, newConfigurationOptions, root)
164
165
  customWebpackConfigPath = options.customWebpackConfig.path;
165
166
  delete options.customWebpackConfig;
166
167
  }
167
- if (options.outputs) {
168
- // handled by the Rspack inference plugin
169
- delete options.outputs;
170
- }
171
168
  for (const [key, value] of Object.entries(options)) {
172
169
  let optionName = key;
173
170
  let optionValue = key in PATH_NORMALIZER ? PATH_NORMALIZER[key](tree, value, root) : value;
@@ -247,8 +244,9 @@ async function convertToRspack(tree, schema) {
247
244
  root: project.root,
248
245
  };
249
246
  const configurationOptions = {};
250
- const buildTargetNames = [];
251
- const serveTargetNames = [];
247
+ let buildTarget;
248
+ let serveTarget;
249
+ const targetsToRemove = [];
252
250
  let customWebpackConfigPath;
253
251
  (0, validate_supported_executor_1.validateSupportedBuildExecutor)(Object.values(project.targets));
254
252
  let projectServePort = DEFAULT_PORT;
@@ -262,14 +260,15 @@ async function convertToRspack(tree, schema) {
262
260
  handleBuildTargetOptions(tree, configuration, configurationOptions[configurationName], project.root);
263
261
  }
264
262
  }
265
- buildTargetNames.push(targetName);
263
+ buildTarget = { name: targetName, config: target };
264
+ targetsToRemove.push(targetName);
266
265
  }
267
266
  else if (target.executor === '@angular-devkit/build-angular:server' ||
268
267
  target.executor === '@nx/angular:webpack-server') {
269
268
  createConfigOptions.ssr ??= {};
270
269
  createConfigOptions.ssr.entry ??= normalizeFromProjectRoot(tree, target.options.main, project.root);
271
270
  createConfigOptions.server = './src/main.server.ts';
272
- buildTargetNames.push(targetName);
271
+ targetsToRemove.push(targetName);
273
272
  }
274
273
  else if (target.executor === '@angular-devkit/build-angular:dev-server' ||
275
274
  target.executor === '@nx/angular:dev-server' ||
@@ -277,7 +276,7 @@ async function convertToRspack(tree, schema) {
277
276
  createConfigOptions.devServer = {};
278
277
  if (target.options) {
279
278
  handleDevServerTargetOptions(tree, target.options, createConfigOptions.devServer, project.root);
280
- if (target.options.port !== DEFAULT_PORT) {
279
+ if (target.options.port && target.options.port !== DEFAULT_PORT) {
281
280
  projectServePort = target.options.port;
282
281
  }
283
282
  }
@@ -288,7 +287,8 @@ async function convertToRspack(tree, schema) {
288
287
  handleDevServerTargetOptions(tree, configuration, configurationOptions[configurationName].devServer, project.root);
289
288
  }
290
289
  }
291
- serveTargetNames.push(targetName);
290
+ serveTarget = { name: targetName, config: target };
291
+ targetsToRemove.push(targetName);
292
292
  }
293
293
  else if (target.executor === '@angular-devkit/build-angular:prerender') {
294
294
  if (target.options) {
@@ -309,11 +309,11 @@ async function convertToRspack(tree, schema) {
309
309
  }
310
310
  }
311
311
  }
312
- buildTargetNames.push(targetName);
312
+ targetsToRemove.push(targetName);
313
313
  }
314
314
  else if (target.executor === '@angular-devkit/build-angular:app-shell') {
315
315
  createConfigOptions.appShell = true;
316
- buildTargetNames.push(targetName);
316
+ targetsToRemove.push(targetName);
317
317
  }
318
318
  }
319
319
  const customWebpackConfigInfo = customWebpackConfigPath
@@ -321,20 +321,169 @@ async function convertToRspack(tree, schema) {
321
321
  : undefined;
322
322
  (0, create_config_1.createConfig)(tree, createConfigOptions, configurationOptions, customWebpackConfigInfo?.normalizedPathToCustomWebpackConfig, customWebpackConfigInfo?.isWebpackConfigFunction);
323
323
  (0, update_tsconfig_1.updateTsconfig)(tree, project.root);
324
- for (const targetName of [...buildTargetNames, ...serveTargetNames]) {
324
+ for (const targetName of targetsToRemove) {
325
325
  delete project.targets[targetName];
326
326
  }
327
- if (projectServePort !== DEFAULT_PORT) {
328
- project.targets.serve ??= {};
329
- project.targets.serve.options ??= {};
330
- project.targets.serve.options.port = projectServePort;
331
- }
332
327
  (0, devkit_1.updateProjectConfiguration)(tree, projectName, project);
328
+ // ensure plugin is registered
333
329
  const { rspackInitGenerator } = (0, devkit_1.ensurePackage)('@nx/rspack', versions_1.nxVersion);
334
330
  await rspackInitGenerator(tree, {
335
331
  addPlugin: true,
336
332
  framework: 'angular',
337
333
  });
334
+ // find the inferred target names
335
+ const nxJson = (0, devkit_1.readNxJson)(tree);
336
+ let inferredBuildTargetName = 'build';
337
+ let inferredServeTargetName = 'serve';
338
+ const pluginRegistration = nxJson.plugins.find((p) => typeof p === 'string' ? false : p.plugin === '@nx/rspack/plugin');
339
+ if (pluginRegistration) {
340
+ inferredBuildTargetName =
341
+ pluginRegistration.options.buildTargetName ?? inferredBuildTargetName;
342
+ inferredServeTargetName =
343
+ pluginRegistration.options.serveTargetName ?? inferredServeTargetName;
344
+ }
345
+ if (buildTarget) {
346
+ // these are all replaced by the inferred task
347
+ delete buildTarget.config.options;
348
+ delete buildTarget.config.configurations;
349
+ delete buildTarget.config.defaultConfiguration;
350
+ delete buildTarget.config.executor;
351
+ const shouldOverrideInputs = (inputs) => {
352
+ if (!inputs?.length) {
353
+ return false;
354
+ }
355
+ if (inputs.length === 2) {
356
+ // check whether the existing inputs would match the inferred task
357
+ // inputs with the exception of the @rspack/cli external dependency
358
+ // which webpack tasks wouldn't have
359
+ const namedInputs = (0, get_named_inputs_1.getNamedInputs)(project.root, {
360
+ nxJsonConfiguration: nxJson,
361
+ configFiles: [],
362
+ workspaceRoot: devkit_1.workspaceRoot,
363
+ });
364
+ if ('production' in namedInputs) {
365
+ return !['production', '^production'].every((input) => inputs.includes(input));
366
+ }
367
+ return !['default', '^default'].every((input) => inputs.includes(input));
368
+ }
369
+ return true;
370
+ };
371
+ if (shouldOverrideInputs(buildTarget.config.inputs)) {
372
+ // keep existing inputs and add the @rspack/cli external dependency
373
+ buildTarget.config.inputs = [
374
+ ...buildTarget.config.inputs,
375
+ { externalDependencies: ['@rspack/cli'] },
376
+ ];
377
+ }
378
+ else {
379
+ delete buildTarget.config.inputs;
380
+ }
381
+ if (buildTarget.config.cache) {
382
+ delete buildTarget.config.cache;
383
+ }
384
+ if (buildTarget.config.dependsOn?.length === 1 &&
385
+ buildTarget.config.dependsOn[0] === `^${buildTarget.name}`) {
386
+ delete buildTarget.config.dependsOn;
387
+ }
388
+ else if (buildTarget.config.dependsOn) {
389
+ buildTarget.config.dependsOn = buildTarget.config.dependsOn.map((dep) => dep === `^${buildTarget.name}` ? `^${inferredBuildTargetName}` : dep);
390
+ }
391
+ const newOutputPath = (0, devkit_1.joinPathFragments)(project.root, createConfigOptions.outputPath.base);
392
+ const shouldOverrideOutputs = (outputs) => {
393
+ if (!outputs?.length) {
394
+ // this means the target was wrongly configured, so, we don't override
395
+ // anything and let the inferred outputs be used
396
+ return false;
397
+ }
398
+ if (outputs.length === 1) {
399
+ if (outputs[0] === '{options.outputPath}') {
400
+ // the inferred task output is created after the createConfig
401
+ // outputPath option, so we don't need to keep this
402
+ return false;
403
+ }
404
+ const normalizedOutputPath = outputs[0]
405
+ .replace('{workspaceRoot}/', '')
406
+ .replace('{projectRoot}', project.root)
407
+ .replace('{projectName}', '');
408
+ if (normalizedOutputPath === newOutputPath ||
409
+ normalizedOutputPath.replace(/\/browser\/?$/, '') === newOutputPath) {
410
+ return false;
411
+ }
412
+ }
413
+ return true;
414
+ };
415
+ const normalizeOutput = (path, workspaceRoot, projectRoot) => {
416
+ const fullProjectRoot = (0, path_1.resolve)(workspaceRoot, projectRoot);
417
+ const fullPath = (0, path_1.resolve)(workspaceRoot, path);
418
+ const pathRelativeToProjectRoot = (0, devkit_1.normalizePath)((0, path_1.relative)(fullProjectRoot, fullPath));
419
+ if (pathRelativeToProjectRoot.startsWith('..')) {
420
+ return (0, devkit_1.joinPathFragments)('{workspaceRoot}', (0, path_1.relative)(workspaceRoot, fullPath));
421
+ }
422
+ return (0, devkit_1.joinPathFragments)('{projectRoot}', pathRelativeToProjectRoot);
423
+ };
424
+ if (shouldOverrideOutputs(buildTarget.config.outputs)) {
425
+ buildTarget.config.outputs = buildTarget.config.outputs.map((output) => {
426
+ if (output === '{options.outputPath}') {
427
+ // the target won't have an outputPath option, so we replace it with the new output path
428
+ return normalizeOutput(newOutputPath, devkit_1.workspaceRoot, project.root);
429
+ }
430
+ const normalizedOutputPath = output
431
+ .replace('{workspaceRoot}/', '')
432
+ .replace('{projectRoot}', project.root)
433
+ .replace('{projectName}', '');
434
+ if (/\/browser\/?$/.test(normalizedOutputPath) &&
435
+ normalizedOutputPath.replace(/\/browser\/?$/, '') === newOutputPath) {
436
+ return normalizeOutput(newOutputPath, devkit_1.workspaceRoot, project.root);
437
+ }
438
+ return output;
439
+ });
440
+ }
441
+ else {
442
+ delete buildTarget.config.outputs;
443
+ }
444
+ if (buildTarget.config.syncGenerators?.length === 1 &&
445
+ buildTarget.config.syncGenerators[0] === '@nx/js:typescript-sync') {
446
+ delete buildTarget.config.syncGenerators;
447
+ }
448
+ else if (buildTarget.config.syncGenerators?.length) {
449
+ buildTarget.config.syncGenerators = Array.from(new Set([
450
+ ...buildTarget.config.syncGenerators,
451
+ '@nx/js:typescript-sync',
452
+ ]));
453
+ }
454
+ if (Object.keys(buildTarget.config).length) {
455
+ // there's extra target metadata left that wouldn't be inferred, we keep it
456
+ project.targets[inferredBuildTargetName] = buildTarget.config;
457
+ }
458
+ }
459
+ if (serveTarget) {
460
+ delete serveTarget.config.options;
461
+ delete serveTarget.config.configurations;
462
+ delete serveTarget.config.defaultConfiguration;
463
+ delete serveTarget.config.executor;
464
+ if (serveTarget.config.continuous) {
465
+ delete serveTarget.config.continuous;
466
+ }
467
+ if (serveTarget.config.syncGenerators?.length === 1 &&
468
+ serveTarget.config.syncGenerators[0] === '@nx/js:typescript-sync') {
469
+ delete serveTarget.config.syncGenerators;
470
+ }
471
+ else if (serveTarget.config.syncGenerators?.length) {
472
+ serveTarget.config.syncGenerators = Array.from(new Set([
473
+ ...serveTarget.config.syncGenerators,
474
+ '@nx/js:typescript-sync',
475
+ ]));
476
+ }
477
+ if (projectServePort !== DEFAULT_PORT) {
478
+ serveTarget.config.options = {};
479
+ serveTarget.config.options.port = projectServePort;
480
+ }
481
+ if (Object.keys(serveTarget.config).length) {
482
+ // there's extra target metadata left that wouldn't be inferred, we keep it
483
+ project.targets[inferredServeTargetName] = serveTarget.config;
484
+ }
485
+ }
486
+ (0, devkit_1.updateProjectConfiguration)(tree, projectName, project);
338
487
  // This is needed to prevent a circular execution of the build target
339
488
  const rootPkgJson = (0, devkit_1.readJson)(tree, 'package.json');
340
489
  if (rootPkgJson.scripts?.build === 'nx build') {
@@ -19,6 +19,7 @@ function updateTsConfigFiles(tree, options) {
19
19
  experimentalDecorators: true,
20
20
  importHelpers: true,
21
21
  target: 'es2022',
22
+ moduleResolution: 'bundler',
22
23
  ...(options.strict
23
24
  ? {
24
25
  strict: true,
@@ -37,10 +38,10 @@ function updateTsConfigFiles(tree, options) {
37
38
  compilerOptions.module = 'preserve';
38
39
  }
39
40
  else {
40
- compilerOptions.moduleResolution = 'bundler';
41
41
  compilerOptions.module = 'es2022';
42
42
  }
43
- (0, devkit_1.updateJson)(tree, `${options.projectRoot}/tsconfig.json`, (json) => {
43
+ const tsconfigPath = (0, devkit_1.joinPathFragments)(options.projectRoot, 'tsconfig.json');
44
+ (0, devkit_1.updateJson)(tree, tsconfigPath, (json) => {
44
45
  json.compilerOptions = {
45
46
  ...json.compilerOptions,
46
47
  ...compilerOptions,
@@ -57,6 +58,18 @@ function updateTsConfigFiles(tree, options) {
57
58
  }
58
59
  return json;
59
60
  });
61
+ if (options.unitTestRunner === 'jest') {
62
+ const tsconfigSpecPath = (0, devkit_1.joinPathFragments)(options.projectRoot, 'tsconfig.spec.json');
63
+ (0, devkit_1.updateJson)(tree, tsconfigSpecPath, (json) => {
64
+ json.compilerOptions = {
65
+ ...json.compilerOptions,
66
+ module: 'commonjs',
67
+ moduleResolution: 'node10',
68
+ };
69
+ json.compilerOptions = (0, configuration_1.getNeededCompilerOptionOverrides)(tree, json.compilerOptions, tsconfigPath);
70
+ return json;
71
+ });
72
+ }
60
73
  }
61
74
  function updateProjectConfig(host, options) {
62
75
  (0, devkit_1.updateJson)(host, `${options.projectRoot}/tsconfig.lib.json`, (json) => {
@@ -50,8 +50,8 @@ async function libraryGenerator(tree, schema) {
50
50
  }
51
51
  const project = await (0, add_project_1.addProject)(tree, libraryOptions);
52
52
  (0, create_files_1.createFiles)(tree, options, project);
53
- (0, update_tsconfig_files_1.updateTsConfigFiles)(tree, libraryOptions);
54
53
  await addUnitTestRunner(tree, libraryOptions);
54
+ (0, update_tsconfig_files_1.updateTsConfigFiles)(tree, libraryOptions);
55
55
  updateNpmScopeIfBuildableOrPublishable(tree, libraryOptions);
56
56
  (0, set_generator_defaults_1.setGeneratorDefaults)(tree, options);
57
57
  if (!libraryOptions.standalone) {