@nx/js 23.0.0 → 23.1.0-beta.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
@@ -7,13 +7,12 @@
7
7
 
8
8
  <div style="text-align: center;">
9
9
 
10
- [![CircleCI](https://circleci.com/gh/nrwl/nx.svg?style=svg)](https://circleci.com/gh/nrwl/nx)
11
10
  [![License](https://img.shields.io/npm/l/@nx/workspace.svg?style=flat-square)]()
12
11
  [![NPM Version](https://badge.fury.io/js/nx.svg)](https://www.npmjs.com/package/nx)
13
12
  [![Semantic Release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat-square)]()
14
13
  [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
15
- [![Join the chat at https://gitter.im/nrwl-nx/community](https://badges.gitter.im/nrwl-nx/community.svg)](https://gitter.im/nrwl-nx/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
16
14
  [![Join us on the Official Nx Discord Server](https://img.shields.io/discord/1143497901675401286?label=discord)](https://go.nx.dev/community)
15
+ [![Nx Sandboxing](https://staging.nx.app/workspaces/62d013ea0852fe0a2df74438/sandbox-badge.svg)](https://nx.dev/docs/features/ci-features/sandboxing)
17
16
 
18
17
  </div>
19
18
 
@@ -4,7 +4,9 @@ export { findProjectsNpmDependencies } from 'nx/src/plugins/js/package-json/crea
4
4
  export { walkTsconfigExtendsChain, type RawTsconfigJsonCache, } from './src/utils/typescript/raw-tsconfig';
5
5
  export { isEsmProject } from './src/utils/module-format/is-esm-project';
6
6
  export { TS_SOLUTION_SETUP_TSCONFIG_INPUT, addProjectToTsSolutionWorkspace, assertNotUsingTsSolutionSetup, findRuntimeTsConfigName, getDefinedCustomConditionName, getProjectSourceRoot, getProjectType, isUsingTsSolutionSetup, shouldConfigureTsSolutionSetup, updateTsconfigFiles, } from './src/utils/typescript/ts-solution-setup';
7
+ export { getTsConfigBaseOptions } from './src/utils/typescript/create-ts-config';
7
8
  export { ensureTypescript } from './src/utils/typescript/ensure-typescript';
9
+ export { getRangeMinimum, getTsConfigModuleResolution, isTypescriptVersionAtLeast, } from './src/utils/is-typescript-version-at-least';
8
10
  export { getNeededCompilerOptionOverrides } from './src/utils/typescript/configuration';
9
11
  export { compileTypeScript, type TypeScriptCompilationOptions, } from './src/utils/typescript/compilation';
10
12
  export { calculateProjectBuildableDependencies, calculateProjectDependencies, computeCompilerOptionsPaths, createTmpTsConfig, type DependentBuildableProjectNode, } from './src/utils/buildable-libs-utils';
package/dist/internal.js CHANGED
@@ -5,8 +5,8 @@
5
5
  // internal consumers and may change without semver protection. Consider it
6
6
  // the @nx/js equivalent of `@nx/devkit/internal`.
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.esbuildVersion = exports.nxVersion = exports.releaseTasks = exports.addReleaseConfigForTsSolution = exports.addReleaseConfigForNonTsSolution = exports.addLocalRegistryScripts = exports.stripGlobToBaseDir = exports.getImportPath = exports.createGlobPatternsForDependencies = exports.normalizeUnitTestRunnerOption = exports.normalizeLinterOption = exports.isValidPackageJsonBuildConfig = exports.addBuildAndWatchDepsTargets = exports.findNpmDependencies = exports.getProjectPackageManagerWorkspaceStateWarningTask = exports.getProjectPackageManagerWorkspaceState = exports.getNpmScope = exports.sortPackageJsonFields = exports.CopyAssetsHandler = exports.addSwcRegisterDependencies = exports.addSwcDependencies = exports.addSwcTestConfig = exports.addSwcConfig = exports.createTmpTsConfig = exports.computeCompilerOptionsPaths = exports.calculateProjectDependencies = exports.calculateProjectBuildableDependencies = exports.compileTypeScript = exports.getNeededCompilerOptionOverrides = exports.ensureTypescript = exports.updateTsconfigFiles = exports.shouldConfigureTsSolutionSetup = exports.isUsingTsSolutionSetup = exports.getProjectType = exports.getProjectSourceRoot = exports.getDefinedCustomConditionName = exports.findRuntimeTsConfigName = exports.assertNotUsingTsSolutionSetup = exports.addProjectToTsSolutionWorkspace = exports.TS_SOLUTION_SETUP_TSCONFIG_INPUT = exports.isEsmProject = exports.walkTsconfigExtendsChain = exports.findProjectsNpmDependencies = exports.isBuiltinModuleImport = exports.TargetProjectLocator = exports.requireWithTsconfigFallback = exports.registerTsConfigPaths = exports.registerTsProject = exports.loadTsFile = exports.forceRegisterEsmLoader = void 0;
9
- exports.typesNodeVersion = exports.tsLibVersion = exports.swcNodeVersion = exports.swcHelpersVersion = exports.swcCoreVersion = exports.swcCliVersion = exports.prettierVersion = void 0;
8
+ exports.addReleaseConfigForNonTsSolution = exports.addLocalRegistryScripts = exports.stripGlobToBaseDir = exports.getImportPath = exports.createGlobPatternsForDependencies = exports.normalizeUnitTestRunnerOption = exports.normalizeLinterOption = exports.isValidPackageJsonBuildConfig = exports.addBuildAndWatchDepsTargets = exports.findNpmDependencies = exports.getProjectPackageManagerWorkspaceStateWarningTask = exports.getProjectPackageManagerWorkspaceState = exports.getNpmScope = exports.sortPackageJsonFields = exports.CopyAssetsHandler = exports.addSwcRegisterDependencies = exports.addSwcDependencies = exports.addSwcTestConfig = exports.addSwcConfig = exports.createTmpTsConfig = exports.computeCompilerOptionsPaths = exports.calculateProjectDependencies = exports.calculateProjectBuildableDependencies = exports.compileTypeScript = exports.getNeededCompilerOptionOverrides = exports.isTypescriptVersionAtLeast = exports.getTsConfigModuleResolution = exports.getRangeMinimum = exports.ensureTypescript = exports.getTsConfigBaseOptions = exports.updateTsconfigFiles = exports.shouldConfigureTsSolutionSetup = exports.isUsingTsSolutionSetup = exports.getProjectType = exports.getProjectSourceRoot = exports.getDefinedCustomConditionName = exports.findRuntimeTsConfigName = exports.assertNotUsingTsSolutionSetup = exports.addProjectToTsSolutionWorkspace = exports.TS_SOLUTION_SETUP_TSCONFIG_INPUT = exports.isEsmProject = exports.walkTsconfigExtendsChain = exports.findProjectsNpmDependencies = exports.isBuiltinModuleImport = exports.TargetProjectLocator = exports.requireWithTsconfigFallback = exports.registerTsConfigPaths = exports.registerTsProject = exports.loadTsFile = exports.forceRegisterEsmLoader = void 0;
9
+ exports.typesNodeVersion = exports.tsLibVersion = exports.swcNodeVersion = exports.swcHelpersVersion = exports.swcCoreVersion = exports.swcCliVersion = exports.prettierVersion = exports.esbuildVersion = exports.nxVersion = exports.releaseTasks = exports.addReleaseConfigForTsSolution = void 0;
10
10
  // Re-exports of nx-source internals (need `no-restricted-imports` overrides).
11
11
  // eslint-disable-next-line @typescript-eslint/no-restricted-imports
12
12
  var register_1 = require("nx/src/plugins/js/utils/register");
@@ -41,11 +41,18 @@ Object.defineProperty(exports, "getProjectType", { enumerable: true, get: functi
41
41
  Object.defineProperty(exports, "isUsingTsSolutionSetup", { enumerable: true, get: function () { return ts_solution_setup_1.isUsingTsSolutionSetup; } });
42
42
  Object.defineProperty(exports, "shouldConfigureTsSolutionSetup", { enumerable: true, get: function () { return ts_solution_setup_1.shouldConfigureTsSolutionSetup; } });
43
43
  Object.defineProperty(exports, "updateTsconfigFiles", { enumerable: true, get: function () { return ts_solution_setup_1.updateTsconfigFiles; } });
44
- // TypeScript helpers (resolvePathsBaseUrl, extractTsConfigBase,
45
- // tsConfigBaseOptions, addTsLibDependencies, resolveModuleByImport all ship
46
- // via the public @nx/js entry)
44
+ // TypeScript helpers. resolvePathsBaseUrl, extractTsConfigBase,
45
+ // tsConfigBaseOptions, addTsLibDependencies, and resolveModuleByImport ship via
46
+ // the public @nx/js entry. getTsConfigBaseOptions is public too, but is
47
+ // re-exported here so internal consumers can import it from @nx/js/internal.
48
+ var create_ts_config_1 = require("./src/utils/typescript/create-ts-config");
49
+ Object.defineProperty(exports, "getTsConfigBaseOptions", { enumerable: true, get: function () { return create_ts_config_1.getTsConfigBaseOptions; } });
47
50
  var ensure_typescript_1 = require("./src/utils/typescript/ensure-typescript");
48
51
  Object.defineProperty(exports, "ensureTypescript", { enumerable: true, get: function () { return ensure_typescript_1.ensureTypescript; } });
52
+ var is_typescript_version_at_least_1 = require("./src/utils/is-typescript-version-at-least");
53
+ Object.defineProperty(exports, "getRangeMinimum", { enumerable: true, get: function () { return is_typescript_version_at_least_1.getRangeMinimum; } });
54
+ Object.defineProperty(exports, "getTsConfigModuleResolution", { enumerable: true, get: function () { return is_typescript_version_at_least_1.getTsConfigModuleResolution; } });
55
+ Object.defineProperty(exports, "isTypescriptVersionAtLeast", { enumerable: true, get: function () { return is_typescript_version_at_least_1.isTypescriptVersionAtLeast; } });
49
56
  var configuration_1 = require("./src/utils/typescript/configuration");
50
57
  Object.defineProperty(exports, "getNeededCompilerOptionOverrides", { enumerable: true, get: function () { return configuration_1.getNeededCompilerOptionOverrides; } });
51
58
  var compilation_1 = require("./src/utils/typescript/compilation");
@@ -4,7 +4,7 @@
4
4
  "rootDir": ".",
5
5
  "sourceMap": true,
6
6
  "declaration": false,
7
- "moduleResolution": "node",
7
+ "moduleResolution": "<%= moduleResolution %>",
8
8
  "emitDecoratorMetadata": true,
9
9
  "experimentalDecorators": true,
10
10
  "importHelpers": true,
@@ -13,6 +13,7 @@
13
13
  "lib": ["es2020", "dom"],
14
14
  "skipLibCheck": true,
15
15
  "skipDefaultLibCheck": true,
16
+ "strict": false,
16
17
  "paths": {}
17
18
  },
18
19
  "exclude": ["node_modules", "tmp"]
@@ -8,6 +8,7 @@ const path_1 = require("path");
8
8
  const plugin_1 = require("../../plugins/typescript/plugin");
9
9
  const assert_supported_typescript_version_1 = require("../../utils/assert-supported-typescript-version");
10
10
  const prettier_1 = require("../../utils/prettier");
11
+ const create_ts_config_1 = require("../../utils/typescript/create-ts-config");
11
12
  const ts_config_1 = require("../../utils/typescript/ts-config");
12
13
  const ts_solution_setup_1 = require("../../utils/typescript/ts-solution-setup");
13
14
  const versions_1 = require("../../utils/versions");
@@ -70,6 +71,7 @@ async function initGeneratorInternal(tree, schema) {
70
71
  else {
71
72
  (0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, './files/non-ts-solution'), '.', {
72
73
  fileName: schema.tsConfigName ?? 'tsconfig.base.json',
74
+ moduleResolution: (0, create_ts_config_1.getTsConfigBaseOptions)(tree).moduleResolution,
73
75
  });
74
76
  }
75
77
  }
@@ -771,7 +771,7 @@ function createProjectTsConfigs(tree, options) {
771
771
  ? undefined
772
772
  : (0, ts_config_1.getRelativePathToRootTsConfig)(tree, options.projectRoot),
773
773
  compilerOptions: {
774
- ...(options.rootProject ? create_ts_config_1.tsConfigBaseOptions : {}),
774
+ ...(options.rootProject ? (0, create_ts_config_1.getTsConfigBaseOptions)(tree) : {}),
775
775
  ...compilerOptionOverrides,
776
776
  },
777
777
  files: [],
@@ -0,0 +1,28 @@
1
+ import { type Tree } from '@nx/devkit';
2
+ /**
3
+ * Two independent passes over every tsconfig*.json in the workspace:
4
+ *
5
+ * 1. ignoreDeprecations pass - adds `ignoreDeprecations: "6.0"` to any
6
+ * compilerOptions (or ts-node.compilerOptions) block that directly carries a
7
+ * TS6 hard-deprecated option value (moduleResolution node/node10/classic,
8
+ * baseUrl, target es5, esModuleInterop false, outFile, module
9
+ * amd/umd/system/none, alwaysStrict false, allowSyntheticDefaultImports
10
+ * false, downlevelIteration set to any value).
11
+ *
12
+ * 2. default-preserving pass - for every chain root (no "extends" key), pins
13
+ * the TS6 compiler-option defaults that flipped to a stricter value back to
14
+ * their pre-TS6 value, but only when the root does not set them explicitly:
15
+ * - "strict": false - TS6 treats an absent "strict" as true; TS5 as false.
16
+ * - "noUncheckedSideEffectImports": false - TS6 defaults it to true, which
17
+ * turns a bare side-effect import of an asset lacking an ambient
18
+ * declaration (e.g. `import './styles.css'`) into a hard TS2882 error; it
19
+ * is a semantic diagnostic, not a deprecation, so `ignoreDeprecations`
20
+ * cannot silence it.
21
+ * Files with "extends" inherit from their chain root and are left untouched.
22
+ * Pure solution-style containers (root has `"files": []` and no "include")
23
+ * select no source files, so pinning there is noise and they are skipped.
24
+ *
25
+ * Only runs on TS6 workspaces (gated by `requires` in migrations.json), because
26
+ * `ignoreDeprecations: "6.0"` is itself a hard error (TS5103) on TS 5.x.
27
+ */
28
+ export default function (tree: Tree): Promise<void>;
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = default_1;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const node_path_1 = require("node:path");
6
+ const jsonc_parser_1 = require("jsonc-parser");
7
+ const FORMATTING_OPTIONS = {
8
+ formattingOptions: { keepLines: true, insertSpaces: true, tabSize: 2 },
9
+ };
10
+ /**
11
+ * Two independent passes over every tsconfig*.json in the workspace:
12
+ *
13
+ * 1. ignoreDeprecations pass - adds `ignoreDeprecations: "6.0"` to any
14
+ * compilerOptions (or ts-node.compilerOptions) block that directly carries a
15
+ * TS6 hard-deprecated option value (moduleResolution node/node10/classic,
16
+ * baseUrl, target es5, esModuleInterop false, outFile, module
17
+ * amd/umd/system/none, alwaysStrict false, allowSyntheticDefaultImports
18
+ * false, downlevelIteration set to any value).
19
+ *
20
+ * 2. default-preserving pass - for every chain root (no "extends" key), pins
21
+ * the TS6 compiler-option defaults that flipped to a stricter value back to
22
+ * their pre-TS6 value, but only when the root does not set them explicitly:
23
+ * - "strict": false - TS6 treats an absent "strict" as true; TS5 as false.
24
+ * - "noUncheckedSideEffectImports": false - TS6 defaults it to true, which
25
+ * turns a bare side-effect import of an asset lacking an ambient
26
+ * declaration (e.g. `import './styles.css'`) into a hard TS2882 error; it
27
+ * is a semantic diagnostic, not a deprecation, so `ignoreDeprecations`
28
+ * cannot silence it.
29
+ * Files with "extends" inherit from their chain root and are left untouched.
30
+ * Pure solution-style containers (root has `"files": []` and no "include")
31
+ * select no source files, so pinning there is noise and they are skipped.
32
+ *
33
+ * Only runs on TS6 workspaces (gated by `requires` in migrations.json), because
34
+ * `ignoreDeprecations: "6.0"` is itself a hard error (TS5103) on TS 5.x.
35
+ */
36
+ async function default_1(tree) {
37
+ let deprecationCount = 0;
38
+ let defaultsPinCount = 0;
39
+ (0, devkit_1.visitNotIgnoredFiles)(tree, '.', (filePath) => {
40
+ const name = (0, node_path_1.basename)(filePath);
41
+ if (!name.startsWith('tsconfig') || !name.endsWith('.json')) {
42
+ return;
43
+ }
44
+ if (addIgnoreDeprecations(tree, filePath)) {
45
+ deprecationCount += 1;
46
+ }
47
+ if (pinPreTs6Defaults(tree, filePath)) {
48
+ defaultsPinCount += 1;
49
+ }
50
+ });
51
+ if (deprecationCount > 0) {
52
+ devkit_1.logger.info(`Added "ignoreDeprecations": "6.0" to ${deprecationCount} tsconfig file(s) carrying TS6-deprecated options.`);
53
+ }
54
+ if (defaultsPinCount > 0) {
55
+ devkit_1.logger.info(`Pinned pre-TS6 compiler option defaults ("strict", "noUncheckedSideEffectImports") on ${defaultsPinCount} tsconfig chain root(s) to preserve existing behavior.`);
56
+ }
57
+ await (0, devkit_1.formatFiles)(tree);
58
+ }
59
+ function addIgnoreDeprecations(tree, tsconfigPath) {
60
+ const original = tree.read(tsconfigPath, 'utf-8');
61
+ if (!original) {
62
+ return false;
63
+ }
64
+ // Each entry targets a distinct compilerOptions block within the same file.
65
+ const blocks = [
66
+ ['compilerOptions'],
67
+ ['ts-node', 'compilerOptions'],
68
+ ];
69
+ let contents = original;
70
+ let changed = false;
71
+ for (const blockPath of blocks) {
72
+ // Re-parse each iteration: a prior edit shifts offsets in `contents`.
73
+ const root = (0, jsonc_parser_1.parseTree)(contents);
74
+ const blockNode = root && (0, jsonc_parser_1.findNodeAtLocation)(root, blockPath);
75
+ if (!blockNode || blockNode.type !== 'object') {
76
+ continue;
77
+ }
78
+ const compilerOptions = (0, jsonc_parser_1.getNodeValue)(blockNode);
79
+ if (!hasDeprecatedValue(compilerOptions)) {
80
+ continue;
81
+ }
82
+ // An existing non-"6.0" value (e.g. "5.0") does NOT silence 6.0-class
83
+ // deprecations, so upgrade it; only "6.0" is already correct.
84
+ if (compilerOptions.ignoreDeprecations === '6.0') {
85
+ continue;
86
+ }
87
+ const edits = (0, jsonc_parser_1.modify)(contents, [...blockPath, 'ignoreDeprecations'], '6.0', FORMATTING_OPTIONS);
88
+ contents = (0, jsonc_parser_1.applyEdits)(contents, edits);
89
+ changed = true;
90
+ }
91
+ if (changed) {
92
+ tree.write(tsconfigPath, contents);
93
+ }
94
+ return changed;
95
+ }
96
+ // Values that compile silently on TS 5.8 but are hard deprecation errors
97
+ // (TS5101/TS5107) on TS 6.0 - derived by differential 5.8-vs-6.0 probing.
98
+ function hasDeprecatedValue(compilerOptions) {
99
+ const moduleResolution = asLowerString(compilerOptions.moduleResolution);
100
+ if (moduleResolution === 'node' ||
101
+ moduleResolution === 'node10' ||
102
+ moduleResolution === 'classic') {
103
+ return true;
104
+ }
105
+ // `baseUrl`/`outFile` only deprecate when set to a real value; `null`/unset
106
+ // is inert on TS6.
107
+ if (compilerOptions.baseUrl != null) {
108
+ return true;
109
+ }
110
+ if (asLowerString(compilerOptions.target) === 'es5') {
111
+ return true;
112
+ }
113
+ if (compilerOptions.esModuleInterop === false) {
114
+ return true;
115
+ }
116
+ if (compilerOptions.outFile != null) {
117
+ return true;
118
+ }
119
+ const moduleValue = asLowerString(compilerOptions.module);
120
+ if (moduleValue === 'amd' ||
121
+ moduleValue === 'umd' ||
122
+ moduleValue === 'system' ||
123
+ moduleValue === 'none') {
124
+ return true;
125
+ }
126
+ // Only the explicit `false` value triggers TS5107 for these two flags.
127
+ if (compilerOptions.alwaysStrict === false) {
128
+ return true;
129
+ }
130
+ if (compilerOptions.allowSyntheticDefaultImports === false) {
131
+ return true;
132
+ }
133
+ // A real boolean triggers TS5101; `null`/unset is inert. `!= null` also flags
134
+ // non-boolean JSON, but that only adds a harmless no-op `ignoreDeprecations`.
135
+ if (compilerOptions.downlevelIteration != null) {
136
+ return true;
137
+ }
138
+ return false;
139
+ }
140
+ // TS6 compiler-option defaults that flipped to a stricter value. We pin each
141
+ // back to its pre-TS6 value on chain roots that don't set it, so existing
142
+ // workspaces keep building without adopting a legit TS6 setup.
143
+ const DEFAULT_PRESERVING_PINS = [
144
+ ['strict', false],
145
+ ['noUncheckedSideEffectImports', false],
146
+ ];
147
+ function pinPreTs6Defaults(tree, tsconfigPath) {
148
+ const original = tree.read(tsconfigPath, 'utf-8');
149
+ if (!original) {
150
+ return false;
151
+ }
152
+ const root = (0, jsonc_parser_1.parseTree)(original);
153
+ if (!root || root.type !== 'object') {
154
+ return false;
155
+ }
156
+ const rootValue = (0, jsonc_parser_1.getNodeValue)(root);
157
+ // Only touch chain roots - files with "extends" inherit from their ancestor.
158
+ if ('extends' in rootValue) {
159
+ return false;
160
+ }
161
+ // Skip pure solution-style containers: root has "files": [] and no "include".
162
+ // They select no source files, so pinning defaults there is noise.
163
+ const filesNode = (0, jsonc_parser_1.findNodeAtLocation)(root, ['files']);
164
+ const hasEmptyFiles = filesNode?.type === 'array' && filesNode.children?.length === 0;
165
+ if (hasEmptyFiles && !('include' in rootValue)) {
166
+ return false;
167
+ }
168
+ const compilerOptionsNode = (0, jsonc_parser_1.findNodeAtLocation)(root, ['compilerOptions']);
169
+ // A present-but-non-object compilerOptions can't receive pinned keys; bailing
170
+ // avoids modify() throwing and aborting the whole migration.
171
+ if (compilerOptionsNode && compilerOptionsNode.type !== 'object') {
172
+ return false;
173
+ }
174
+ const compilerOptions = compilerOptionsNode
175
+ ? (0, jsonc_parser_1.getNodeValue)(compilerOptionsNode)
176
+ : {};
177
+ let contents = original;
178
+ let changed = false;
179
+ for (const [key, value] of DEFAULT_PRESERVING_PINS) {
180
+ // An explicit value (true or false) means the user opted in - leave it.
181
+ if (key in compilerOptions) {
182
+ continue;
183
+ }
184
+ const edits = (0, jsonc_parser_1.modify)(contents, ['compilerOptions', key], value, FORMATTING_OPTIONS);
185
+ contents = (0, jsonc_parser_1.applyEdits)(contents, edits);
186
+ changed = true;
187
+ }
188
+ if (changed) {
189
+ tree.write(tsconfigPath, contents);
190
+ }
191
+ return changed;
192
+ }
193
+ function asLowerString(value) {
194
+ return typeof value === 'string' ? value.toLowerCase() : undefined;
195
+ }
@@ -0,0 +1,37 @@
1
+ #### Keep Existing Workspaces Compiling on TypeScript 6
2
+
3
+ TypeScript 6 turns several long-deprecated compiler options into hard errors and flips a few option defaults to stricter values. So that an existing workspace keeps compiling on TypeScript 6 without being migrated to a full TypeScript 6 setup, this migration makes two edits to the `tsconfig*.json` files in the workspace:
4
+
5
+ - Adds `"ignoreDeprecations": "6.0"` to any `compilerOptions` (or `ts-node.compilerOptions`) block that directly sets a TypeScript 6 deprecated option - for example `moduleResolution` set to `node`/`node10`/`classic`, `baseUrl`, `target` set to `es5`, `esModuleInterop: false`, `outFile`, `module` set to `amd`/`umd`/`system`/`none`, `alwaysStrict: false`, `allowSyntheticDefaultImports: false`, or `downlevelIteration`.
6
+ - Pins `"strict": false` and `"noUncheckedSideEffectImports": false` on every chain-root tsconfig (one without an `extends`) that does not already set them. TypeScript 6 treats an absent `strict` as `true` (it was `false` when unset before) and defaults `noUncheckedSideEffectImports` to `true`, which turns a bare side-effect import such as `import './styles.css'` without an ambient module declaration into an error. Pinning both preserves the pre-TypeScript 6 behavior.
7
+
8
+ Files that use `extends` inherit these settings from their chain root and are left untouched, and pure solution-style tsconfigs (`"files": []` with no `include`) are skipped. The migration only runs when the workspace is on TypeScript 6.
9
+
10
+ #### Sample Code Changes
11
+
12
+ ##### Before
13
+
14
+ ```json title="tsconfig.json"
15
+ {
16
+ "compilerOptions": {
17
+ "target": "es5",
18
+ "module": "esnext",
19
+ "moduleResolution": "bundler"
20
+ }
21
+ }
22
+ ```
23
+
24
+ ##### After
25
+
26
+ ```json title="tsconfig.json" {6-8}
27
+ {
28
+ "compilerOptions": {
29
+ "target": "es5",
30
+ "module": "esnext",
31
+ "moduleResolution": "bundler",
32
+ "ignoreDeprecations": "6.0",
33
+ "strict": false,
34
+ "noUncheckedSideEffectImports": false
35
+ }
36
+ }
37
+ ```
@@ -0,0 +1,37 @@
1
+ import { type Tree } from '@nx/devkit';
2
+ /**
3
+ * Checks whether the workspace's `typescript` is at or above the given version.
4
+ *
5
+ * Resolution order:
6
+ * - When `typescript` is declared and the installed version satisfies that
7
+ * declared range, the installed version decides. This resolves open ranges
8
+ * (e.g. `>=5.8.0`, `^5 || ^6`) to what is actually installed.
9
+ * - Otherwise the declared range's minimum is used (e.g. `^5.9.2` -> `5.9.2`,
10
+ * `<6` -> `0.0.0`). This is the fresh-workspace path (nothing installed yet)
11
+ * and the case where a generator is mid-flight re-pinning `typescript` - the
12
+ * new range no longer satisfies the still-installed version, so intent wins.
13
+ * - When `typescript` is not declared at all, Nx's default install version is
14
+ * assumed; a transitively-hoisted install is ignored as it does not reflect
15
+ * a workspace choice.
16
+ *
17
+ * Dist-tags and unparseable ranges (e.g. `latest`, `next`) have no resolvable
18
+ * floor, so they are treated as meeting any version.
19
+ *
20
+ * Use from generators to emit version-appropriate config when a single value
21
+ * is not valid across the supported TypeScript range.
22
+ */
23
+ export declare function isTypescriptVersionAtLeast(tree: Tree, version: string): boolean;
24
+ /**
25
+ * The `moduleResolution` to emit in generated tsconfig files, chosen for the
26
+ * workspace's TypeScript version: `bundler` on TS >= 6, `node10` on TS < 6.
27
+ * node-family resolution is a TS5107 deprecation error on TS 6, and `bundler`
28
+ * is invalid in a commonjs setup on TS < 6 (TS5095); `node10` also preserves
29
+ * classic node resolution for pre-TS6 workspaces.
30
+ */
31
+ export declare function getTsConfigModuleResolution(tree: Tree): 'bundler' | 'node10';
32
+ /**
33
+ * Returns the minimum satisfying version for a semver range, stripping
34
+ * prerelease so `>=6.0.0-beta.1` still counts as 6.0. Falls back to coerce()
35
+ * for dist-tags and garbage inputs that minVersion() cannot parse.
36
+ */
37
+ export declare function getRangeMinimum(range: string): string | undefined;
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isTypescriptVersionAtLeast = isTypescriptVersionAtLeast;
4
+ exports.getTsConfigModuleResolution = getTsConfigModuleResolution;
5
+ exports.getRangeMinimum = getRangeMinimum;
6
+ const devkit_1 = require("@nx/devkit");
7
+ const semver_1 = require("semver");
8
+ const versions_1 = require("./versions");
9
+ /**
10
+ * Checks whether the workspace's `typescript` is at or above the given version.
11
+ *
12
+ * Resolution order:
13
+ * - When `typescript` is declared and the installed version satisfies that
14
+ * declared range, the installed version decides. This resolves open ranges
15
+ * (e.g. `>=5.8.0`, `^5 || ^6`) to what is actually installed.
16
+ * - Otherwise the declared range's minimum is used (e.g. `^5.9.2` -> `5.9.2`,
17
+ * `<6` -> `0.0.0`). This is the fresh-workspace path (nothing installed yet)
18
+ * and the case where a generator is mid-flight re-pinning `typescript` - the
19
+ * new range no longer satisfies the still-installed version, so intent wins.
20
+ * - When `typescript` is not declared at all, Nx's default install version is
21
+ * assumed; a transitively-hoisted install is ignored as it does not reflect
22
+ * a workspace choice.
23
+ *
24
+ * Dist-tags and unparseable ranges (e.g. `latest`, `next`) have no resolvable
25
+ * floor, so they are treated as meeting any version.
26
+ *
27
+ * Use from generators to emit version-appropriate config when a single value
28
+ * is not valid across the supported TypeScript range.
29
+ */
30
+ function isTypescriptVersionAtLeast(tree, version) {
31
+ const declared = (0, devkit_1.getDependencyVersionFromPackageJson)(tree, 'typescript');
32
+ if (declared) {
33
+ const installed = getInstalledTypescriptVersion(tree);
34
+ if (installed && (0, semver_1.satisfies)(installed, declared)) {
35
+ return (0, semver_1.gte)(installed, version);
36
+ }
37
+ }
38
+ const minimum = getRangeMinimum(declared ?? versions_1.typescriptVersion);
39
+ return !minimum || (0, semver_1.gte)(minimum, version);
40
+ }
41
+ /**
42
+ * Reads the installed `typescript` version via the tree (not `require`), so it
43
+ * reflects in-flight tree changes and stays controllable in tests. Returns
44
+ * undefined when not resolvable.
45
+ */
46
+ function getInstalledTypescriptVersion(tree) {
47
+ try {
48
+ const pkgJson = tree.read('node_modules/typescript/package.json', 'utf-8');
49
+ if (!pkgJson) {
50
+ return undefined;
51
+ }
52
+ // Strip any prerelease (e.g. `6.0.0-rc.1` -> `6.0.0`) so it compares
53
+ // consistently with getRangeMinimum's normalization.
54
+ return (0, semver_1.coerce)(JSON.parse(pkgJson).version)?.version;
55
+ }
56
+ catch {
57
+ return undefined;
58
+ }
59
+ }
60
+ /**
61
+ * The `moduleResolution` to emit in generated tsconfig files, chosen for the
62
+ * workspace's TypeScript version: `bundler` on TS >= 6, `node10` on TS < 6.
63
+ * node-family resolution is a TS5107 deprecation error on TS 6, and `bundler`
64
+ * is invalid in a commonjs setup on TS < 6 (TS5095); `node10` also preserves
65
+ * classic node resolution for pre-TS6 workspaces.
66
+ */
67
+ function getTsConfigModuleResolution(tree) {
68
+ return isTypescriptVersionAtLeast(tree, '6.0.0') ? 'bundler' : 'node10';
69
+ }
70
+ /**
71
+ * Returns the minimum satisfying version for a semver range, stripping
72
+ * prerelease so `>=6.0.0-beta.1` still counts as 6.0. Falls back to coerce()
73
+ * for dist-tags and garbage inputs that minVersion() cannot parse.
74
+ */
75
+ function getRangeMinimum(range) {
76
+ try {
77
+ const min = (0, semver_1.minVersion)(range);
78
+ if (min) {
79
+ return `${min.major}.${min.minor}.${min.patch}`;
80
+ }
81
+ }
82
+ catch {
83
+ // fall through to coerce for dist-tags and other unparseable inputs
84
+ }
85
+ return (0, semver_1.coerce)(range)?.version;
86
+ }
@@ -12,6 +12,23 @@ export declare const tsConfigBaseOptions: {
12
12
  lib: string[];
13
13
  skipLibCheck: boolean;
14
14
  skipDefaultLibCheck: boolean;
15
+ strict: boolean;
15
16
  paths: {};
16
17
  };
18
+ export declare function getTsConfigBaseOptions(tree: Tree): {
19
+ rootDir: string;
20
+ sourceMap: boolean;
21
+ declaration: boolean;
22
+ emitDecoratorMetadata: boolean;
23
+ experimentalDecorators: boolean;
24
+ importHelpers: boolean;
25
+ target: string;
26
+ module: string;
27
+ lib: string[];
28
+ skipLibCheck: boolean;
29
+ skipDefaultLibCheck: boolean;
30
+ strict: boolean;
31
+ paths: {};
32
+ moduleResolution: "bundler" | "node10";
33
+ };
17
34
  export declare function extractTsConfigBase(host: Tree): void;
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.tsConfigBaseOptions = void 0;
4
+ exports.getTsConfigBaseOptions = getTsConfigBaseOptions;
4
5
  exports.extractTsConfigBase = extractTsConfigBase;
5
6
  const json_1 = require("nx/src/generators/utils/json");
7
+ const is_typescript_version_at_least_1 = require("../is-typescript-version-at-least");
6
8
  exports.tsConfigBaseOptions = {
7
9
  rootDir: '.',
8
10
  sourceMap: true,
@@ -16,8 +18,17 @@ exports.tsConfigBaseOptions = {
16
18
  lib: ['es2020', 'dom'],
17
19
  skipLibCheck: true,
18
20
  skipDefaultLibCheck: true,
21
+ // TS 6.0 flips the `strict` default to true; pin false to keep this base
22
+ // config's behavior identical on TS 5.8 and 6.0.
23
+ strict: false,
19
24
  paths: {},
20
25
  };
26
+ function getTsConfigBaseOptions(tree) {
27
+ return {
28
+ ...exports.tsConfigBaseOptions,
29
+ moduleResolution: (0, is_typescript_version_at_least_1.getTsConfigModuleResolution)(tree),
30
+ };
31
+ }
21
32
  function extractTsConfigBase(host) {
22
33
  if (host.exists('tsconfig.base.json'))
23
34
  return;
@@ -8,10 +8,10 @@ export declare const swcNodeVersion = "~1.11.1";
8
8
  export declare const tsLibVersion = "^2.3.0";
9
9
  export declare const typesNodeVersion = "^22.0.0";
10
10
  export declare const verdaccioVersion = "^6.3.2";
11
- export declare const typescriptVersion = "~5.9.2";
11
+ export declare const typescriptVersion = "~6.0.3";
12
12
  /**
13
13
  * The minimum version is currently determined from the lowest version
14
14
  * that's supported by the lowest Angular supported version, e.g.
15
- * `npm view @angular/compiler-cli@18.0.0 peerDependencies.typescript`
15
+ * `npm view @angular/compiler-cli@20.0.0 peerDependencies.typescript`
16
16
  */
17
- export declare const minSupportedTypescriptVersion = "5.4.0";
17
+ export declare const minSupportedTypescriptVersion = "5.8.0";
@@ -13,10 +13,10 @@ exports.tsLibVersion = '^2.3.0';
13
13
  exports.typesNodeVersion = '^22.0.0';
14
14
  exports.verdaccioVersion = '^6.3.2';
15
15
  // Typescript
16
- exports.typescriptVersion = '~5.9.2';
16
+ exports.typescriptVersion = '~6.0.3';
17
17
  /**
18
18
  * The minimum version is currently determined from the lowest version
19
19
  * that's supported by the lowest Angular supported version, e.g.
20
- * `npm view @angular/compiler-cli@18.0.0 peerDependencies.typescript`
20
+ * `npm view @angular/compiler-cli@20.0.0 peerDependencies.typescript`
21
21
  */
22
- exports.minSupportedTypescriptVersion = '5.4.0';
22
+ exports.minSupportedTypescriptVersion = '5.8.0';
package/migrations.json CHANGED
@@ -28,6 +28,15 @@
28
28
  "description": "Rename imports of `createNodesV2` from `@nx/js/typescript` to the canonical `createNodes` export.",
29
29
  "implementation": "./dist/src/migrations/update-23-0-0/migrate-create-nodes-v2-to-create-nodes",
30
30
  "documentation": "./dist/src/migrations/update-23-0-0/migrate-create-nodes-v2-to-create-nodes.md"
31
+ },
32
+ "23-1-0-add-ignore-deprecations-for-ts6": {
33
+ "version": "23.1.0-beta.0",
34
+ "description": "Adds `\"ignoreDeprecations\": \"6.0\"` to tsconfig files whose compilerOptions (or ts-node.compilerOptions) directly carry a TypeScript 6 deprecated option value (e.g. moduleResolution node/node10/classic, baseUrl, target es5, esModuleInterop false, outFile, module amd/umd/system/none, alwaysStrict false, allowSyntheticDefaultImports false, downlevelIteration set). Also pins `\"strict\": false` and `\"noUncheckedSideEffectImports\": false` in chain-root tsconfigs (no \"extends\") that lack each key, preserving pre-TS6 behavior where their defaults were less strict.",
35
+ "requires": {
36
+ "typescript": ">=6.0.0"
37
+ },
38
+ "factory": "./dist/src/migrations/update-23-1-0/add-ignore-deprecations-for-ts6",
39
+ "documentation": "./dist/src/migrations/update-23-1-0/add-ignore-deprecations-for-ts6.md"
31
40
  }
32
41
  },
33
42
  "packageJsonUpdates": {
@@ -106,6 +115,21 @@
106
115
  "alwaysAddToPackageJson": false
107
116
  }
108
117
  }
118
+ },
119
+ "23.1.0-typescript": {
120
+ "version": "23.1.0-beta.0",
121
+ "incompatibleWith": {
122
+ "@remix-run/dev": "*"
123
+ },
124
+ "requires": {
125
+ "typescript": ">=5.9.0 <6.0.0"
126
+ },
127
+ "packages": {
128
+ "typescript": {
129
+ "version": "~6.0.3",
130
+ "alwaysAddToPackageJson": false
131
+ }
132
+ }
109
133
  }
110
134
  }
111
135
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/js",
3
- "version": "23.0.0",
3
+ "version": "23.1.0-beta.0",
4
4
  "private": false,
5
5
  "type": "commonjs",
6
6
  "files": [
@@ -144,11 +144,11 @@
144
144
  "source-map-support": "0.5.19",
145
145
  "tinyglobby": "^0.2.12",
146
146
  "tslib": "^2.3.0",
147
- "@nx/devkit": "23.0.0",
148
- "@nx/workspace": "23.0.0"
147
+ "@nx/devkit": "23.1.0-beta.0",
148
+ "@nx/workspace": "23.1.0-beta.0"
149
149
  },
150
150
  "devDependencies": {
151
- "nx": "23.0.0"
151
+ "nx": "23.1.0-beta.0"
152
152
  },
153
153
  "peerDependencies": {
154
154
  "@swc/cli": ">=0.6.0 <0.9.0",