@nx/js 23.0.0-beta.17 → 23.0.0-beta.19

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.
@@ -267,6 +267,21 @@ Please update the local dependency on "${depName}" to be a valid semantic versio
267
267
  * to running from the package root directly), then special attention should be paid to the fact that npm/pnpm publish will nest its
268
268
  * JSON output under the name of the package in that case (and it would need to be handled below).
269
269
  */
270
+ return runPublish({
271
+ pm,
272
+ options,
273
+ context,
274
+ packageRoot,
275
+ packageJson,
276
+ registry,
277
+ registryConfigKey,
278
+ tag,
279
+ isDryRun,
280
+ isNpmInstalled,
281
+ });
282
+ }
283
+ function runPublish(ctx) {
284
+ const { pm, options, context, packageRoot, packageJson, registry, registryConfigKey, tag, isDryRun, isNpmInstalled, } = ctx;
270
285
  const pmCommand = (0, devkit_1.getPackageManagerCommand)(pm);
271
286
  const publishCommandSegments = [
272
287
  pmCommand.publish(packageRoot, registry, registryConfigKey, tag),
@@ -342,9 +357,20 @@ Please update the local dependency on "${depName}" to be a valid semantic versio
342
357
  try {
343
358
  // bun publish does not support outputting JSON, so we cannot perform any further processing
344
359
  if (pm === 'bun') {
360
+ const bunStderr = err.stderr?.toString() || '';
361
+ const bunStdout = err.stdout?.toString() || '';
362
+ // bun publish does not yet support npm's OIDC trusted publishing flow. If the failure
363
+ // looks like an authentication error and npm is available, retry via npm to recover.
364
+ // Other failures (e.g. version conflict, 403) would produce the same error from npm,
365
+ // so we surface bun's error directly instead.
366
+ const looksLikeAuthError = /missing authentication|bunx npm login|unauthorized|\b401\b/i.test(bunStderr + bunStdout);
367
+ if (isNpmInstalled && looksLikeAuthError) {
368
+ console.warn(`bun publish failed with an authentication error; falling back to npm publish (bun does not support npm OIDC trusted publishing).`);
369
+ return runPublish({ ...ctx, pm: 'npm' });
370
+ }
345
371
  console.error(`bun publish error:`);
346
- console.error(err.stderr?.toString() || '');
347
- console.error(err.stdout?.toString() || '');
372
+ console.error(bunStderr);
373
+ console.error(bunStdout);
348
374
  return {
349
375
  success: false,
350
376
  };
@@ -3,10 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.convertToSwcGenerator = convertToSwcGenerator;
4
4
  const devkit_1 = require("@nx/devkit");
5
5
  const path_1 = require("path");
6
+ const assert_supported_typescript_version_1 = require("../../utils/assert-supported-typescript-version");
6
7
  const add_swc_config_1 = require("../../utils/swc/add-swc-config");
7
8
  const add_swc_dependencies_1 = require("../../utils/swc/add-swc-dependencies");
8
9
  const versions_1 = require("../../utils/versions");
9
10
  async function convertToSwcGenerator(tree, schema) {
11
+ (0, assert_supported_typescript_version_1.assertSupportedTypescriptVersion)(tree);
10
12
  const options = normalizeOptions(schema);
11
13
  const projectConfiguration = (0, devkit_1.readProjectConfiguration)(tree, options.project);
12
14
  const updated = updateProjectBuildTargets(tree, projectConfiguration, options.project, options.targets);
@@ -50,7 +52,7 @@ function checkSwcDependencies(tree, projectConfiguration) {
50
52
  (0, add_swc_dependencies_1.addSwcDependencies)(tree);
51
53
  }
52
54
  if (!hasSwcHelpers) {
53
- (0, devkit_1.addDependenciesToPackageJson)(tree, { '@swc/helpers': versions_1.swcHelpersVersion }, {}, projectPackageJsonPath);
55
+ (0, devkit_1.addDependenciesToPackageJson)(tree, { '@swc/helpers': versions_1.swcHelpersVersion }, {}, projectPackageJsonPath, true);
54
56
  }
55
57
  return () => {
56
58
  if (!hasSwcDependency) {
@@ -4,38 +4,13 @@ exports.initGenerator = initGenerator;
4
4
  exports.initGeneratorInternal = initGeneratorInternal;
5
5
  const internal_1 = require("@nx/devkit/internal");
6
6
  const devkit_1 = require("@nx/devkit");
7
- const package_json_1 = require("nx/src/utils/package-json");
8
7
  const path_1 = require("path");
9
- const semver_1 = require("semver");
10
8
  const plugin_1 = require("../../plugins/typescript/plugin");
9
+ const assert_supported_typescript_version_1 = require("../../utils/assert-supported-typescript-version");
11
10
  const prettier_1 = require("../../utils/prettier");
12
11
  const ts_config_1 = require("../../utils/typescript/ts-config");
13
12
  const ts_solution_setup_1 = require("../../utils/typescript/ts-solution-setup");
14
13
  const versions_1 = require("../../utils/versions");
15
- async function getInstalledTypescriptVersion(tree) {
16
- const tsVersionInRootPackageJson = (0, devkit_1.getDependencyVersionFromPackageJson)(tree, 'typescript');
17
- if (!tsVersionInRootPackageJson) {
18
- return null;
19
- }
20
- if ((0, semver_1.valid)(tsVersionInRootPackageJson)) {
21
- // it's a pinned version, return it
22
- return tsVersionInRootPackageJson;
23
- }
24
- // it's a version range, check whether the installed version matches it
25
- try {
26
- const tsPackageJson = (0, package_json_1.readModulePackageJson)('typescript').packageJson;
27
- const installedTsVersion = tsPackageJson.devDependencies?.['typescript'] ??
28
- tsPackageJson.dependencies?.['typescript'];
29
- // the installed version matches the package.json version range
30
- if (installedTsVersion &&
31
- (0, semver_1.satisfies)(installedTsVersion, tsVersionInRootPackageJson)) {
32
- return installedTsVersion;
33
- }
34
- }
35
- finally {
36
- return (0, internal_1.checkAndCleanWithSemver)(tree, 'typescript', tsVersionInRootPackageJson);
37
- }
38
- }
39
14
  async function initGenerator(tree, schema) {
40
15
  schema.addTsPlugin ??= false;
41
16
  const isUsingNewTsSetup = schema.addTsPlugin || (0, ts_solution_setup_1.isUsingTsSolutionSetup)(tree);
@@ -46,6 +21,7 @@ async function initGenerator(tree, schema) {
46
21
  });
47
22
  }
48
23
  async function initGeneratorInternal(tree, schema) {
24
+ (0, assert_supported_typescript_version_1.assertSupportedTypescriptVersion)(tree);
49
25
  const tasks = [];
50
26
  const nxJson = (0, devkit_1.readNxJson)(tree);
51
27
  schema.addPlugin ??=
@@ -109,14 +85,8 @@ async function initGeneratorInternal(tree, schema) {
109
85
  // Node.js type stripping handles .ts config loading on Node 23+ (or 22.6+
110
86
  // with --experimental-strip-types). loadTsFile registers swc/ts-node lazily
111
87
  // when a config uses syntax native strip can't handle.
112
- if (!schema.js && !schema.keepExistingVersions) {
113
- const installedTsVersion = await getInstalledTypescriptVersion(tree);
114
- if (!installedTsVersion ||
115
- !(0, semver_1.satisfies)(installedTsVersion, versions_1.supportedTypescriptVersions, {
116
- includePrerelease: true,
117
- })) {
118
- devDependencies['typescript'] = versions_1.typescriptVersion;
119
- }
88
+ if (!schema.js) {
89
+ devDependencies['typescript'] = versions_1.typescriptVersion;
120
90
  }
121
91
  if (schema.formatter === 'prettier') {
122
92
  const prettierTask = (0, prettier_1.generatePrettierSetup)(tree, {
@@ -134,7 +104,7 @@ async function initGeneratorInternal(tree, schema) {
134
104
  }
135
105
  }
136
106
  const installTask = !schema.skipPackageJson
137
- ? (0, devkit_1.addDependenciesToPackageJson)(tree, {}, devDependencies, undefined, schema.keepExistingVersions)
107
+ ? (0, devkit_1.addDependenciesToPackageJson)(tree, {}, devDependencies, undefined, schema.keepExistingVersions ?? true)
138
108
  : () => { };
139
109
  tasks.push(installTask);
140
110
  if (!schema.skipPackageJson &&
@@ -31,7 +31,7 @@
31
31
  "type": "boolean",
32
32
  "x-priority": "internal",
33
33
  "description": "Keep existing dependencies versions",
34
- "default": false
34
+ "default": true
35
35
  },
36
36
  "addTsConfigBase": {
37
37
  "type": "boolean",
@@ -7,6 +7,7 @@ const tslib_1 = require("tslib");
7
7
  const internal_1 = require("@nx/devkit/internal");
8
8
  const devkit_1 = require("@nx/devkit");
9
9
  const path_1 = require("path");
10
+ const assert_supported_typescript_version_1 = require("../../utils/assert-supported-typescript-version");
10
11
  const generator_prompts_1 = require("../../utils/generator-prompts");
11
12
  const sort_fields_1 = require("../../utils/package-json/sort-fields");
12
13
  const update_package_json_1 = require("../../utils/package-json/update-package-json");
@@ -30,6 +31,7 @@ async function libraryGenerator(tree, schema) {
30
31
  });
31
32
  }
32
33
  async function libraryGeneratorInternal(tree, schema) {
34
+ (0, assert_supported_typescript_version_1.assertSupportedTypescriptVersion)(tree);
33
35
  const tasks = [];
34
36
  const addTsPlugin = (0, ts_solution_setup_1.shouldConfigureTsSolutionSetup)(tree, schema.addPlugin);
35
37
  tasks.push(await (0, init_1.default)(tree, {
@@ -654,7 +656,7 @@ function addProjectDependencies(tree, options) {
654
656
  '@types/node': versions_1.typesNodeVersion,
655
657
  esbuild: (0, devkit_1.getDependencyVersionFromPackageJson)(tree, 'esbuild') ??
656
658
  versions_1.esbuildVersion,
657
- });
659
+ }, undefined, true);
658
660
  }
659
661
  else if (options.bundler == 'rollup') {
660
662
  const { dependencies, devDependencies } = (0, add_swc_dependencies_1.getSwcDependencies)();
@@ -662,17 +664,17 @@ function addProjectDependencies(tree, options) {
662
664
  ...devDependencies,
663
665
  '@nx/rollup': versions_1.nxVersion,
664
666
  '@types/node': versions_1.typesNodeVersion,
665
- });
667
+ }, undefined, true);
666
668
  }
667
669
  else if (options.bundler === 'tsc') {
668
- return (0, devkit_1.addDependenciesToPackageJson)(tree, {}, { tslib: versions_1.tsLibVersion, '@types/node': versions_1.typesNodeVersion });
670
+ return (0, devkit_1.addDependenciesToPackageJson)(tree, {}, { tslib: versions_1.tsLibVersion, '@types/node': versions_1.typesNodeVersion }, undefined, true);
669
671
  }
670
672
  else if (options.bundler === 'swc') {
671
673
  const { dependencies, devDependencies } = (0, add_swc_dependencies_1.getSwcDependencies)();
672
- return (0, devkit_1.addDependenciesToPackageJson)(tree, { ...dependencies }, { ...devDependencies, '@types/node': versions_1.typesNodeVersion });
674
+ return (0, devkit_1.addDependenciesToPackageJson)(tree, { ...dependencies }, { ...devDependencies, '@types/node': versions_1.typesNodeVersion }, undefined, true);
673
675
  }
674
676
  else {
675
- return (0, devkit_1.addDependenciesToPackageJson)(tree, {}, { '@types/node': versions_1.typesNodeVersion });
677
+ return (0, devkit_1.addDependenciesToPackageJson)(tree, {}, { '@types/node': versions_1.typesNodeVersion }, undefined, true);
676
678
  }
677
679
  // Vite is being installed in the next step if bundler is vite
678
680
  // noop
@@ -5,6 +5,7 @@ const internal_1 = require("@nx/devkit/internal");
5
5
  const devkit_1 = require("@nx/devkit");
6
6
  const posix_1 = require("node:path/posix");
7
7
  const devkit_internals_1 = require("nx/src/devkit-internals");
8
+ const assert_supported_typescript_version_1 = require("../../utils/assert-supported-typescript-version");
8
9
  const get_import_path_1 = require("../../utils/get-import-path");
9
10
  const update_package_json_1 = require("../../utils/package-json/update-package-json");
10
11
  const add_swc_config_1 = require("../../utils/swc/add-swc-config");
@@ -16,6 +17,7 @@ const ts_solution_setup_1 = require("../../utils/typescript/ts-solution-setup");
16
17
  const versions_1 = require("../../utils/versions");
17
18
  let ts;
18
19
  async function setupBuildGenerator(tree, options) {
20
+ (0, assert_supported_typescript_version_1.assertSupportedTypescriptVersion)(tree);
19
21
  const tasks = [];
20
22
  const project = (0, devkit_1.readProjectConfiguration)(tree, options.project);
21
23
  options.buildTarget ??= 'build';
@@ -2,9 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.setupPrettierGenerator = setupPrettierGenerator;
4
4
  const devkit_1 = require("@nx/devkit");
5
+ const assert_supported_typescript_version_1 = require("../../utils/assert-supported-typescript-version");
5
6
  const prettier_1 = require("../../utils/prettier");
6
7
  const versions_1 = require("../../utils/versions");
7
8
  async function setupPrettierGenerator(tree, options) {
9
+ (0, assert_supported_typescript_version_1.assertSupportedTypescriptVersion)(tree);
8
10
  const prettierTask = (0, prettier_1.generatePrettierSetup)(tree, {
9
11
  skipPackageJson: options.skipPackageJson,
10
12
  });
@@ -4,10 +4,12 @@ exports.setupVerdaccio = setupVerdaccio;
4
4
  const tslib_1 = require("tslib");
5
5
  const devkit_1 = require("@nx/devkit");
6
6
  const path = tslib_1.__importStar(require("path"));
7
+ const assert_supported_typescript_version_1 = require("../../utils/assert-supported-typescript-version");
7
8
  const ts_solution_setup_1 = require("../../utils/typescript/ts-solution-setup");
8
9
  const versions_1 = require("../../utils/versions");
9
10
  const npm_config_1 = require("../../utils/npm-config");
10
11
  async function setupVerdaccio(tree, options) {
12
+ (0, assert_supported_typescript_version_1.assertSupportedTypescriptVersion)(tree);
11
13
  if (!tree.exists('.verdaccio/config.yml')) {
12
14
  (0, devkit_1.generateFiles)(tree, path.join(__dirname, 'files'), '.verdaccio', {
13
15
  npmUplinkRegistry: (await (0, npm_config_1.getNpmRegistry)(tree.root)) ?? 'https://registry.npmjs.org',
@@ -54,6 +56,6 @@ async function setupVerdaccio(tree, options) {
54
56
  if (!options.skipFormat) {
55
57
  await (0, devkit_1.formatFiles)(tree);
56
58
  }
57
- return (0, devkit_1.addDependenciesToPackageJson)(tree, {}, { verdaccio: versions_1.verdaccioVersion });
59
+ return (0, devkit_1.addDependenciesToPackageJson)(tree, {}, { verdaccio: versions_1.verdaccioVersion }, undefined, true);
58
60
  }
59
61
  exports.default = setupVerdaccio;
@@ -8,6 +8,7 @@ const jsonc_parser_1 = require("jsonc-parser");
8
8
  const posix_1 = require("node:path/posix");
9
9
  const sync_generators_1 = require("nx/src/utils/sync-generators");
10
10
  const ts = tslib_1.__importStar(require("typescript"));
11
+ const assert_supported_typescript_version_1 = require("../../utils/assert-supported-typescript-version");
11
12
  const COMMON_RUNTIME_TS_CONFIG_FILE_NAMES = [
12
13
  'tsconfig.app.json',
13
14
  'tsconfig.lib.json',
@@ -17,6 +18,7 @@ const COMMON_RUNTIME_TS_CONFIG_FILE_NAMES = [
17
18
  'tsconfig.runtime.json',
18
19
  ];
19
20
  async function syncGenerator(tree) {
21
+ (0, assert_supported_typescript_version_1.assertSupportedTypescriptVersion)(tree);
20
22
  // Ensure that the plugin has been wired up in nx.json
21
23
  const nxJson = (0, devkit_1.readNxJson)(tree);
22
24
  const tsconfigInfoCaches = {
@@ -0,0 +1,87 @@
1
+ #### Migrate `development` custom condition to unique workspace-specific name
2
+
3
+ Replace the TypeScript `development` custom condition with a unique workspace-specific name to avoid conflicts when consuming packages in other workspaces.
4
+
5
+ #### Examples
6
+
7
+ The migration will update the custom condition name in both `tsconfig.base.json` and all workspace package.json files that use the `development` custom condition:
8
+
9
+ ##### Before
10
+
11
+ ```json title="tsconfig.base.json" {3}
12
+ {
13
+ "compilerOptions": {
14
+ "customConditions": ["development"]
15
+ }
16
+ }
17
+ ```
18
+
19
+ ##### After
20
+
21
+ ```json title="tsconfig.base.json" {3}
22
+ {
23
+ "compilerOptions": {
24
+ "customConditions": ["@my-org/source"] // assuming the root package.json name is `@my-org/source`
25
+ }
26
+ }
27
+ ```
28
+
29
+ The migration also updates `package.json` files that use the `development` condition in their `exports` field and point to TypeScript files:
30
+
31
+ ##### Before
32
+
33
+ ```json title="libs/my-lib/package.json" {5}
34
+ {
35
+ "name": "@myorg/my-lib",
36
+ "exports": {
37
+ ".": {
38
+ "development": "./src/index.ts",
39
+ "default": "./dist/index.js"
40
+ }
41
+ }
42
+ }
43
+ ```
44
+
45
+ ##### After
46
+
47
+ ```json title="libs/my-lib/package.json" {5}
48
+ {
49
+ "name": "@myorg/my-lib",
50
+ "exports": {
51
+ ".": {
52
+ "@my-org/source": "./src/index.ts",
53
+ "default": "./dist/index.js"
54
+ }
55
+ }
56
+ }
57
+ ```
58
+
59
+ If the custom condition is not set to `["development"]` or the `package.json`'s `exports` field doesn't point to TypeScript files, the migration will not modify the configuration:
60
+
61
+ ##### Before
62
+
63
+ ```json title="libs/my-lib/package.json" {5}
64
+ {
65
+ "name": "@myorg/my-lib",
66
+ "exports": {
67
+ ".": {
68
+ "development": "./dist/index.js",
69
+ "default": "./dist/index.js"
70
+ }
71
+ }
72
+ }
73
+ ```
74
+
75
+ ##### After
76
+
77
+ ```json title="libs/my-lib/package.json" {5}
78
+ {
79
+ "name": "@myorg/my-lib",
80
+ "exports": {
81
+ ".": {
82
+ "development": "./dist/index.js",
83
+ "default": "./dist/index.js"
84
+ }
85
+ }
86
+ }
87
+ ```
@@ -0,0 +1,79 @@
1
+ #### Remove the `external` and `externalBuildTargets` Options from the `@nx/js:swc` and `@nx/js:tsc` Executors
2
+
3
+ Remove the deprecated `external` and `externalBuildTargets` options from the `@nx/js:swc` and `@nx/js:tsc` executors. These options were used for inlining dependencies, which was an experimental feature and has been deprecated for a long time. The migration only removes the options from the project configuration and target defaults. If you rely on inlining dependencies, you need to make sure they are all buildable or use a different build tool that supports bundling.
4
+
5
+ #### Sample Code Changes
6
+
7
+ Remove `external` and `externalBuildTargets` from the `@nx/js:swc` or `@nx/js:tsc` executor options in project configuration.
8
+
9
+ ##### Before
10
+
11
+ ```json title="libs/my-lib/project.json" {9-10}
12
+ {
13
+ "targets": {
14
+ "build": {
15
+ "executor": "@nx/js:swc",
16
+ "options": {
17
+ "main": "libs/my-lib/src/index.ts",
18
+ "outputPath": "dist/libs/my-lib",
19
+ "tsConfig": "libs/my-lib/tsconfig.lib.json",
20
+ "external": ["react", "react-dom"],
21
+ "externalBuildTargets": ["build"]
22
+ }
23
+ }
24
+ }
25
+ }
26
+ ```
27
+
28
+ ##### After
29
+
30
+ ```json title="libs/my-lib/project.json"
31
+ {
32
+ "targets": {
33
+ "build": {
34
+ "executor": "@nx/js:swc",
35
+ "options": {
36
+ "main": "libs/my-lib/src/index.ts",
37
+ "outputPath": "dist/libs/my-lib",
38
+ "tsConfig": "libs/my-lib/tsconfig.lib.json"
39
+ }
40
+ }
41
+ }
42
+ }
43
+ ```
44
+
45
+ Remove `external` and `externalBuildTargets` from the `@nx/js:swc` or `@nx/js:tsc` executor target defaults in `nx.json`.
46
+
47
+ ##### Before
48
+
49
+ ```json title="nx.json" {8-9}
50
+ {
51
+ "targetDefaults": {
52
+ "@nx/js:swc": {
53
+ "options": {
54
+ "main": "{projectRoot}/src/index.ts",
55
+ "outputPath": "dist/{projectRoot}",
56
+ "tsConfig": "{projectRoot}/tsconfig.lib.json",
57
+ "external": "all",
58
+ "externalBuildTargets": ["build"]
59
+ }
60
+ }
61
+ }
62
+ }
63
+ ```
64
+
65
+ ##### After
66
+
67
+ ```json title="nx.json"
68
+ {
69
+ "targetDefaults": {
70
+ "@nx/js:swc": {
71
+ "options": {
72
+ "main": "{projectRoot}/src/index.ts",
73
+ "outputPath": "dist/{projectRoot}",
74
+ "tsConfig": "{projectRoot}/tsconfig.lib.json"
75
+ }
76
+ }
77
+ }
78
+ }
79
+ ```
@@ -0,0 +1,143 @@
1
+ #### Removes Redundant TypeScript Project References from tsconfig.json Files
2
+
3
+ Removes redundant TypeScript project references from `tsconfig.json` files when runtime tsconfig files (e.g., `tsconfig.lib.json`, `tsconfig.app.json`) exist. Previously, external project references were duplicated in both the project's `tsconfig.json` and runtime tsconfig files. This migration syncs the TypeScript project references to match the project graph, ensuring that external references only appear in runtime tsconfig files when they exist.
4
+
5
+ #### Examples
6
+
7
+ When a project has runtime tsconfig files like `tsconfig.lib.json`, the migration will remove external project references from the project's `tsconfig.json` file:
8
+
9
+ ##### Before
10
+
11
+ ```jsonc {7-9}
12
+ // libs/my-lib/tsconfig.json
13
+ {
14
+ "compilerOptions": {
15
+ "composite": true,
16
+ },
17
+ "references": [
18
+ {
19
+ "path": "../other-lib",
20
+ },
21
+ ],
22
+ }
23
+ ```
24
+
25
+ ##### After
26
+
27
+ ```jsonc {6}
28
+ // libs/my-lib/tsconfig.json
29
+ {
30
+ "compilerOptions": {
31
+ "composite": true,
32
+ },
33
+ "references": [],
34
+ }
35
+ ```
36
+
37
+ The external references remain in the runtime tsconfig file where they belong:
38
+
39
+ ##### Before
40
+
41
+ ```jsonc {7-9}
42
+ // libs/my-lib/tsconfig.lib.json
43
+ {
44
+ "compilerOptions": {
45
+ "composite": true,
46
+ },
47
+ "references": [
48
+ {
49
+ "path": "../other-lib/tsconfig.lib.json",
50
+ },
51
+ ],
52
+ }
53
+ ```
54
+
55
+ ##### After
56
+
57
+ ```jsonc {7-9}
58
+ // libs/my-lib/tsconfig.lib.json
59
+ {
60
+ "compilerOptions": {
61
+ "composite": true,
62
+ },
63
+ "references": [
64
+ {
65
+ "path": "../other-lib/tsconfig.lib.json",
66
+ },
67
+ ],
68
+ }
69
+ ```
70
+
71
+ For projects without runtime tsconfig files, the project's `tsconfig.json` file will continue to contain external project references:
72
+
73
+ ##### Before
74
+
75
+ ```jsonc {7-9}
76
+ // libs/legacy-lib/tsconfig.json
77
+ {
78
+ "compilerOptions": {
79
+ "composite": true,
80
+ },
81
+ "references": [
82
+ {
83
+ "path": "../other-lib",
84
+ },
85
+ ],
86
+ }
87
+ ```
88
+
89
+ ##### After
90
+
91
+ ```jsonc {7-9}
92
+ // libs/legacy-lib/tsconfig.json
93
+ {
94
+ "compilerOptions": {
95
+ "composite": true,
96
+ },
97
+ "references": [
98
+ {
99
+ "path": "../other-lib",
100
+ },
101
+ ],
102
+ }
103
+ ```
104
+
105
+ Internal project references (references within the same project directory) are preserved in the project's `tsconfig.json`:
106
+
107
+ ##### Before
108
+
109
+ ```jsonc {7-12}
110
+ // libs/my-lib/tsconfig.json
111
+ {
112
+ "compilerOptions": {
113
+ "composite": true,
114
+ },
115
+ "references": [
116
+ {
117
+ "path": "./tsconfig.lib.json",
118
+ },
119
+ {
120
+ "path": "./tsconfig.spec.json",
121
+ },
122
+ ],
123
+ }
124
+ ```
125
+
126
+ ##### After
127
+
128
+ ```jsonc {7-12}
129
+ // libs/my-lib/tsconfig.json
130
+ {
131
+ "compilerOptions": {
132
+ "composite": true,
133
+ },
134
+ "references": [
135
+ {
136
+ "path": "./tsconfig.lib.json",
137
+ },
138
+ {
139
+ "path": "./tsconfig.spec.json",
140
+ },
141
+ ],
142
+ }
143
+ ```
@@ -91,19 +91,34 @@ function collectCallExpressionRewrites(sourceFile, changes) {
91
91
  shouldRewriteSpecifier(node.arguments[0].text)) {
92
92
  replaceSpecifier(sourceFile, node.arguments[0], changes);
93
93
  }
94
+ else if (ts.isImportTypeNode(node)) {
95
+ // `typeof import('...')` parses as an `ImportTypeNode`, not a
96
+ // CallExpression — its argument is `LiteralTypeNode<StringLiteral>`.
97
+ // The whole module is referenced, so it can't be symbol-split.
98
+ const literal = getImportTypeStringLiteral(node);
99
+ if (literal && shouldRewriteSpecifier(literal.text)) {
100
+ replaceSpecifier(sourceFile, literal, changes);
101
+ }
102
+ }
94
103
  ts.forEachChild(node, visit);
95
104
  };
96
105
  visit(sourceFile);
97
106
  }
107
+ function getImportTypeStringLiteral(node) {
108
+ const arg = node.argument;
109
+ if (arg && ts.isLiteralTypeNode(arg) && ts.isStringLiteral(arg.literal)) {
110
+ return arg.literal;
111
+ }
112
+ return undefined;
113
+ }
98
114
  function shouldRewriteCallExpression(call) {
99
115
  const callee = call.expression;
100
116
  // `require('...')`
101
117
  if (ts.isIdentifier(callee) && callee.text === 'require')
102
118
  return true;
103
119
  // dynamic `import('...')` (runtime form parses as a CallExpression whose
104
- // callee is the `import` keyword). The type-position form
105
- // (`typeof import('...')`) is an `ImportTypeNode`, not a CallExpression, so
106
- // we don't touch it.
120
+ // callee is the `import` keyword). The `typeof import('...')` type-position
121
+ // form is an `ImportTypeNode` (handled in `collectCallExpressionRewrites`).
107
122
  if (callee.kind === ts.SyntaxKind.ImportKeyword)
108
123
  return true;
109
124
  // `jest.mock(...)` / `vi.mock(...)` and friends.
@@ -10,8 +10,20 @@ const picomatch = require("picomatch");
10
10
  // eslint-disable-next-line @typescript-eslint/no-restricted-imports
11
11
  const lock_file_1 = require("nx/src/plugins/js/lock-file/lock-file");
12
12
  const cache_directory_1 = require("nx/src/utils/cache-directory");
13
+ const installation_directory_1 = require("nx/src/utils/installation-directory");
13
14
  const util_1 = require("./util");
14
15
  let ts;
16
+ const resolvedTypescriptPaths = {};
17
+ function resolveTypescriptPath(projectRoot, workspaceRoot) {
18
+ // Resolve from projectRoot first, then workspace paths, with __dirname as a
19
+ // last resort. Required so the lookup works under layouts where @nx/js's real
20
+ // path is outside the workspace tree (e.g. pnpm's enableGlobalVirtualStore),
21
+ // since typescript is not a declared dep.
22
+ resolvedTypescriptPaths[projectRoot] ??= require.resolve('typescript', {
23
+ paths: [projectRoot, ...(0, installation_directory_1.getNxRequirePaths)(workspaceRoot), __dirname],
24
+ });
25
+ return resolvedTypescriptPaths[projectRoot];
26
+ }
15
27
  const TSCONFIG_CACHE_VERSION = 2;
16
28
  const TS_CONFIG_CACHE_PATH = (0, node_path_1.join)(cache_directory_1.workspaceDataDirectory, 'tsconfig-files.hash');
17
29
  // Module-level cache store — each invocation gets a unique Symbol key
@@ -356,7 +368,7 @@ function getInputs(namedInputs, config, tsConfig, internalProjectReferences, wor
356
368
  ];
357
369
  const absoluteProjectRoot = config.project.absolute;
358
370
  if (!ts) {
359
- ts = require('typescript');
371
+ ts = require(resolveTypescriptPath(absoluteProjectRoot, workspaceRoot));
360
372
  }
361
373
  // https://github.com/microsoft/TypeScript/blob/19b777260b26aac5707b1efd34202054164d4a9d/src/compiler/utilities.ts#L9869
362
374
  const supportedTSExtensions = [
@@ -821,7 +833,7 @@ function getExtendedFilesHash(extendedConfigFiles, workspaceRoot, cache) {
821
833
  }
822
834
  function readTsConfig(tsConfigPath, workspaceRoot, cache) {
823
835
  if (!ts) {
824
- ts = require('typescript');
836
+ ts = require(resolveTypescriptPath(workspaceRoot, workspaceRoot));
825
837
  }
826
838
  // Normalize to forward slashes for TypeScript compatibility on Windows.
827
839
  // TypeScript's parser normalizes paths inconsistently — diagnostics use
@@ -0,0 +1,2 @@
1
+ import { type Tree } from '@nx/devkit';
2
+ export declare function assertSupportedTypescriptVersion(tree: Tree): void;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertSupportedTypescriptVersion = assertSupportedTypescriptVersion;
4
+ const internal_1 = require("@nx/devkit/internal");
5
+ const versions_1 = require("./versions");
6
+ function assertSupportedTypescriptVersion(tree) {
7
+ (0, internal_1.assertSupportedPackageVersion)(tree, 'typescript', versions_1.minSupportedTypescriptVersion);
8
+ }
@@ -17,8 +17,8 @@ function getSwcDependencies() {
17
17
  }
18
18
  function addSwcDependencies(tree) {
19
19
  const { dependencies, devDependencies } = getSwcDependencies();
20
- return (0, devkit_1.addDependenciesToPackageJson)(tree, dependencies, devDependencies);
20
+ return (0, devkit_1.addDependenciesToPackageJson)(tree, dependencies, devDependencies, undefined, true);
21
21
  }
22
22
  function addSwcRegisterDependencies(tree) {
23
- return (0, devkit_1.addDependenciesToPackageJson)(tree, {}, { '@swc-node/register': versions_1.swcNodeVersion, '@swc/core': versions_1.swcCoreVersion });
23
+ return (0, devkit_1.addDependenciesToPackageJson)(tree, {}, { '@swc-node/register': versions_1.swcNodeVersion, '@swc/core': versions_1.swcCoreVersion }, undefined, true);
24
24
  }
@@ -14,4 +14,4 @@ export declare const typescriptVersion = "~5.9.2";
14
14
  * that's supported by the lowest Angular supported version, e.g.
15
15
  * `npm view @angular/compiler-cli@18.0.0 peerDependencies.typescript`
16
16
  */
17
- export declare const supportedTypescriptVersions = ">=5.4.0";
17
+ export declare const minSupportedTypescriptVersion = "5.4.0";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.supportedTypescriptVersions = exports.typescriptVersion = exports.verdaccioVersion = exports.typesNodeVersion = exports.tsLibVersion = exports.swcNodeVersion = exports.swcHelpersVersion = exports.swcCoreVersion = exports.swcCliVersion = exports.prettierVersion = exports.esbuildVersion = exports.nxVersion = void 0;
3
+ exports.minSupportedTypescriptVersion = exports.typescriptVersion = exports.verdaccioVersion = exports.typesNodeVersion = exports.tsLibVersion = exports.swcNodeVersion = exports.swcHelpersVersion = exports.swcCoreVersion = exports.swcCliVersion = exports.prettierVersion = exports.esbuildVersion = exports.nxVersion = void 0;
4
4
  const path_1 = require("path");
5
5
  exports.nxVersion = require((0, path_1.join)('@nx/js', 'package.json')).version;
6
6
  exports.esbuildVersion = '^0.27.0';
@@ -19,4 +19,4 @@ exports.typescriptVersion = '~5.9.2';
19
19
  * that's supported by the lowest Angular supported version, e.g.
20
20
  * `npm view @angular/compiler-cli@18.0.0 peerDependencies.typescript`
21
21
  */
22
- exports.supportedTypescriptVersions = '>=5.4.0';
22
+ exports.minSupportedTypescriptVersion = '5.4.0';
package/migrations.json CHANGED
@@ -59,6 +59,9 @@
59
59
  },
60
60
  "20.7.1-beta.0": {
61
61
  "version": "20.7.1-beta.0",
62
+ "requires": {
63
+ "@swc/cli": ">=0.3.0 <0.6.0"
64
+ },
62
65
  "packages": {
63
66
  "@swc/cli": {
64
67
  "version": "~0.6.0",
@@ -99,10 +102,6 @@
99
102
  "version": "^1.15.5",
100
103
  "alwaysAddToPackageJson": false
101
104
  },
102
- "@swc/cli": {
103
- "version": "^0.7.10",
104
- "alwaysAddToPackageJson": false
105
- },
106
105
  "@swc/helpers": {
107
106
  "version": "^0.5.18",
108
107
  "alwaysAddToPackageJson": false
@@ -113,6 +112,18 @@
113
112
  }
114
113
  }
115
114
  },
115
+ "22.5.0-swc-cli": {
116
+ "version": "22.5.0-beta.1",
117
+ "requires": {
118
+ "@swc/cli": ">=0.6.0 <0.7.0"
119
+ },
120
+ "packages": {
121
+ "@swc/cli": {
122
+ "version": "^0.7.10",
123
+ "alwaysAddToPackageJson": false
124
+ }
125
+ }
126
+ },
116
127
  "22.6.4": {
117
128
  "version": "22.6.4",
118
129
  "packages": {
@@ -121,6 +132,18 @@
121
132
  "alwaysAddToPackageJson": false
122
133
  }
123
134
  }
135
+ },
136
+ "23.0.0-swc-cli": {
137
+ "version": "23.0.0-beta.17",
138
+ "requires": {
139
+ "@swc/cli": ">=0.7.0 <0.8.0"
140
+ },
141
+ "packages": {
142
+ "@swc/cli": {
143
+ "version": "~0.8.0",
144
+ "alwaysAddToPackageJson": false
145
+ }
146
+ }
124
147
  }
125
148
  }
126
149
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/js",
3
- "version": "23.0.0-beta.17",
3
+ "version": "23.0.0-beta.19",
4
4
  "private": false,
5
5
  "type": "commonjs",
6
6
  "files": [
@@ -136,16 +136,20 @@
136
136
  "source-map-support": "0.5.19",
137
137
  "tinyglobby": "^0.2.12",
138
138
  "tslib": "^2.3.0",
139
- "@nx/devkit": "23.0.0-beta.17",
140
- "@nx/workspace": "23.0.0-beta.17"
139
+ "@nx/workspace": "23.0.0-beta.19",
140
+ "@nx/devkit": "23.0.0-beta.19"
141
141
  },
142
142
  "devDependencies": {
143
- "nx": "23.0.0-beta.17"
143
+ "nx": "23.0.0-beta.19"
144
144
  },
145
145
  "peerDependencies": {
146
+ "@swc/cli": ">=0.6.0 <0.9.0",
146
147
  "verdaccio": "^6.0.5"
147
148
  },
148
149
  "peerDependenciesMeta": {
150
+ "@swc/cli": {
151
+ "optional": true
152
+ },
149
153
  "verdaccio": {
150
154
  "optional": true
151
155
  }