@nx/vite 24.0.0-beta.2 → 24.0.0-beta.3
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/dist/executors.d.ts +0 -3
- package/dist/executors.js +0 -7
- package/dist/plugins/nx-copy-assets.plugin.d.ts +4 -5
- package/dist/plugins/nx-copy-assets.plugin.js +5 -49
- package/dist/plugins/nx-tsconfig-paths.plugin.d.ts +5 -7
- package/dist/plugins/nx-tsconfig-paths.plugin.js +6 -247
- package/dist/src/generators/configuration/configuration.js +2 -39
- package/dist/src/generators/configuration/schema.d.ts +0 -1
- package/dist/src/generators/convert-to-inferred/lib/build-post-target-transformer.d.ts +0 -1
- package/dist/src/generators/convert-to-inferred/lib/build-post-target-transformer.js +3 -66
- package/dist/src/generators/init/init.js +20 -32
- package/dist/src/generators/init/schema.d.ts +0 -1
- package/dist/src/generators/init/schema.json +1 -1
- package/dist/src/generators/setup-paths-plugin/schema.d.ts +0 -1
- package/dist/src/generators/setup-paths-plugin/schema.json +2 -2
- package/dist/src/generators/setup-paths-plugin/setup-paths-plugin.js +16 -91
- package/dist/src/migrations/update-23-0-0/ai-instructions-for-vitest-3.md +5 -5
- package/dist/src/migrations/update-23-0-0/ai-instructions-for-vitest-4.md +6 -6
- package/dist/src/migrations/update-24-0-0/finish-inferred-conversion.md +12 -0
- package/dist/src/migrations/update-24-0-0/migrate-config-helpers.md +86 -0
- package/dist/src/migrations/update-24-0-0/migrate-nx-vite-ts-paths.d.ts +2 -0
- package/dist/src/migrations/update-24-0-0/migrate-nx-vite-ts-paths.js +154 -0
- package/dist/src/migrations/update-24-0-0/register-typescript-plugin-for-typecheck.d.ts +4 -0
- package/dist/src/migrations/update-24-0-0/register-typescript-plugin-for-typecheck.js +11 -0
- package/dist/src/migrations/update-24-0-0/register-typescript-plugin-for-typecheck.md +37 -0
- package/dist/src/migrations/update-24-0-0/remove-deprecated-executors.d.ts +6 -0
- package/dist/src/migrations/update-24-0-0/remove-deprecated-executors.js +46 -0
- package/dist/src/migrations/update-24-0-0/remove-deprecated-executors.md +71 -0
- package/dist/src/plugins/plugin.d.ts +9 -5
- package/dist/src/plugins/plugin.js +34 -45
- package/dist/src/utils/deprecation.d.ts +2 -9
- package/dist/src/utils/deprecation.js +5 -35
- package/dist/src/utils/e2e-web-server-info-utils.d.ts +2 -2
- package/dist/src/utils/e2e-web-server-info-utils.js +4 -4
- package/dist/src/utils/executor-utils.d.ts +0 -10
- package/dist/src/utils/executor-utils.js +0 -51
- package/dist/src/utils/generator-utils.d.ts +0 -10
- package/dist/src/utils/generator-utils.js +36 -106
- package/dist/src/utils/options-utils.d.ts +0 -16
- package/dist/src/utils/options-utils.js +0 -73
- package/dist/src/utils/versions.d.ts +2 -0
- package/dist/src/utils/versions.js +3 -1
- package/dist/src/utils/vite-config-edit-utils.d.ts +9 -1
- package/dist/src/utils/vite-config-edit-utils.js +143 -1
- package/executors.json +2 -34
- package/generators.json +1 -1
- package/migrations.json +19 -0
- package/package.json +6 -7
- package/dist/src/executors/build/build.impl.d.ts +0 -11
- package/dist/src/executors/build/build.impl.js +0 -205
- package/dist/src/executors/build/compat.d.ts +0 -2
- package/dist/src/executors/build/compat.js +0 -6
- package/dist/src/executors/build/schema.json +0 -82
- package/dist/src/executors/dev-server/compat.d.ts +0 -2
- package/dist/src/executors/dev-server/compat.js +0 -6
- package/dist/src/executors/dev-server/dev-server.impl.d.ts +0 -7
- package/dist/src/executors/dev-server/dev-server.impl.js +0 -137
- package/dist/src/executors/dev-server/schema.json +0 -40
- package/dist/src/executors/preview-server/compat.d.ts +0 -2
- package/dist/src/executors/preview-server/compat.js +0 -6
- package/dist/src/executors/preview-server/preview-server.impl.d.ts +0 -7
- package/dist/src/executors/preview-server/preview-server.impl.js +0 -184
- package/dist/src/executors/preview-server/schema.json +0 -44
- package/dist/src/utils/nx-tsconfig-paths-find-file.d.ts +0 -2
- package/dist/src/utils/nx-tsconfig-paths-find-file.js +0 -22
- package/dist/src/utils/nx-tsconfig-paths-load-file.d.ts +0 -12
- package/dist/src/utils/nx-tsconfig-paths-load-file.js +0 -71
|
@@ -5,6 +5,7 @@ exports.initGenerator = initGenerator;
|
|
|
5
5
|
exports.initGeneratorInternal = initGeneratorInternal;
|
|
6
6
|
const internal_1 = require("@nx/devkit/internal");
|
|
7
7
|
const devkit_1 = require("@nx/devkit");
|
|
8
|
+
const internal_2 = require("@nx/js/internal");
|
|
8
9
|
const setup_paths_plugin_1 = require("../setup-paths-plugin/setup-paths-plugin");
|
|
9
10
|
const plugin_1 = require("../../plugins/plugin");
|
|
10
11
|
const utils_1 = require("./lib/utils");
|
|
@@ -20,48 +21,35 @@ function updateNxJsonSettings(tree) {
|
|
|
20
21
|
(0, devkit_1.updateNxJson)(tree, nxJson);
|
|
21
22
|
}
|
|
22
23
|
function initGenerator(tree, schema) {
|
|
23
|
-
return initGeneratorInternal(tree,
|
|
24
|
+
return initGeneratorInternal(tree, schema);
|
|
24
25
|
}
|
|
25
26
|
async function initGeneratorInternal(tree, schema) {
|
|
26
27
|
(0, assert_supported_vite_version_1.assertSupportedViteVersion)(tree);
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
typecheckTargetName: ['typecheck', 'vite:typecheck', 'vite-typecheck'],
|
|
43
|
-
buildDepsTargetName: [
|
|
44
|
-
'build-deps',
|
|
45
|
-
'vite:build-deps',
|
|
46
|
-
'vite-build-deps',
|
|
47
|
-
],
|
|
48
|
-
watchDepsTargetName: [
|
|
49
|
-
'watch-deps',
|
|
50
|
-
'vite:watch-deps',
|
|
51
|
-
'vite-watch-deps',
|
|
52
|
-
],
|
|
53
|
-
}, schema.updatePackageScripts);
|
|
54
|
-
}
|
|
28
|
+
await (0, internal_1.addPlugin)(tree, await (0, devkit_1.createProjectGraphAsync)(), '@nx/vite/plugin', plugin_1.createNodesV2, {
|
|
29
|
+
buildTargetName: ['build', 'vite:build', 'vite-build'],
|
|
30
|
+
serveTargetName: ['serve', 'vite:serve', 'vite-serve'],
|
|
31
|
+
devTargetName: ['dev', 'vite:dev', 'vite-dev'],
|
|
32
|
+
previewTargetName: ['preview', 'vite:preview', 'vite-preview'],
|
|
33
|
+
serveStaticTargetName: [
|
|
34
|
+
'serve-static',
|
|
35
|
+
'vite:serve-static',
|
|
36
|
+
'vite-serve-static',
|
|
37
|
+
],
|
|
38
|
+
typecheckTargetName: ['typecheck', 'vite:typecheck', 'vite-typecheck'],
|
|
39
|
+
buildDepsTargetName: ['build-deps', 'vite:build-deps', 'vite-build-deps'],
|
|
40
|
+
watchDepsTargetName: ['watch-deps', 'vite:watch-deps', 'vite-watch-deps'],
|
|
41
|
+
}, schema.updatePackageScripts);
|
|
42
|
+
await (0, internal_2.ensureTypescriptPlugin)(tree, schema.updatePackageScripts, '@nx/vite/plugin');
|
|
55
43
|
updateNxJsonSettings(tree);
|
|
56
44
|
await (0, ignore_vite_temp_files_1.ignoreViteTempFiles)(tree, schema.projectRoot);
|
|
57
|
-
if (schema.setupPathsPlugin) {
|
|
58
|
-
await (0, setup_paths_plugin_1.setupPathsPlugin)(tree, { skipFormat: true });
|
|
59
|
-
}
|
|
60
45
|
const tasks = [];
|
|
61
46
|
if (!schema.skipPackageJson) {
|
|
62
47
|
tasks.push((0, utils_1.moveToDevDependencies)(tree));
|
|
63
48
|
tasks.push(await (0, utils_1.checkDependenciesInstalled)(tree, schema));
|
|
64
49
|
}
|
|
50
|
+
if (schema.setupPathsPlugin) {
|
|
51
|
+
await (0, setup_paths_plugin_1.setupPathsPlugin)(tree, { skipFormat: true });
|
|
52
|
+
}
|
|
65
53
|
if (!schema.skipFormat) {
|
|
66
54
|
await (0, devkit_1.formatFiles)(tree);
|
|
67
55
|
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
},
|
|
18
18
|
"setupPathsPlugin": {
|
|
19
19
|
"type": "boolean",
|
|
20
|
-
"description": "Updates vite config files to enable support for workspace libraries via
|
|
20
|
+
"description": "Updates vite config files to enable support for workspace libraries via Vite's native `resolve.tsconfigPaths` option.",
|
|
21
21
|
"default": false
|
|
22
22
|
},
|
|
23
23
|
"keepExistingVersions": {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"cli": "nx",
|
|
3
|
-
"title": "
|
|
4
|
-
"description": "Updates vite config files to enable support for workspace libraries via
|
|
3
|
+
"title": "Enables Vite's native tsconfig paths resolution.",
|
|
4
|
+
"description": "Updates vite config files to enable support for workspace libraries via Vite's native `resolve.tsconfigPaths` option.",
|
|
5
5
|
"$id": "setup-paths-plugin-vite-plugin",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"properties": {
|
|
@@ -2,107 +2,32 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.setupPathsPlugin = setupPathsPlugin;
|
|
4
4
|
const devkit_1 = require("@nx/devkit");
|
|
5
|
+
const version_utils_1 = require("../../utils/version-utils");
|
|
6
|
+
const versions_1 = require("../../utils/versions");
|
|
5
7
|
const assert_supported_vite_version_1 = require("../../utils/assert-supported-vite-version");
|
|
8
|
+
const vite_config_edit_utils_1 = require("../../utils/vite-config-edit-utils");
|
|
6
9
|
async function setupPathsPlugin(tree, schema) {
|
|
7
10
|
(0, assert_supported_vite_version_1.assertSupportedViteVersion)(tree);
|
|
8
11
|
const files = await (0, devkit_1.globAsync)(tree, [
|
|
9
12
|
'**/vite.config.{js,ts,mjs,mts,cjs,cts}',
|
|
10
13
|
]);
|
|
14
|
+
const useNativePaths = ((0, version_utils_1.getInstalledViteMajorVersion)(tree) ?? 8) >= 8;
|
|
15
|
+
let addedPlugin = false;
|
|
11
16
|
for (const file of files) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
function ensureImportExists(tree, file) {
|
|
20
|
-
const { tsquery } = require('@phenomnomnominal/tsquery');
|
|
21
|
-
let content = tree.read(file, 'utf-8');
|
|
22
|
-
const ast = tsquery.ast(content);
|
|
23
|
-
const allImports = tsquery.query(ast, 'ImportDeclaration');
|
|
24
|
-
if (content.includes('@nx/vite/plugins/nx-tsconfig-paths.plugin')) {
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
if (allImports.length) {
|
|
28
|
-
const lastImport = allImports[allImports.length - 1];
|
|
29
|
-
tree.write(file, (0, devkit_1.applyChangesToString)(content, [
|
|
30
|
-
{
|
|
31
|
-
type: devkit_1.ChangeType.Insert,
|
|
32
|
-
index: lastImport.end + 1,
|
|
33
|
-
text: `import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';\n`,
|
|
34
|
-
},
|
|
35
|
-
]));
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
if (file.endsWith('.cts') || file.endsWith('.cjs')) {
|
|
39
|
-
tree.write(file, (0, devkit_1.applyChangesToString)(content, [
|
|
40
|
-
{
|
|
41
|
-
type: devkit_1.ChangeType.Insert,
|
|
42
|
-
index: 0,
|
|
43
|
-
text: `const { nxViteTsPaths } = require('@nx/vite/plugins/nx-tsconfig-paths.plugin');\n`,
|
|
44
|
-
},
|
|
45
|
-
]));
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
tree.write(file, (0, devkit_1.applyChangesToString)(content, [
|
|
49
|
-
{
|
|
50
|
-
type: devkit_1.ChangeType.Insert,
|
|
51
|
-
index: 0,
|
|
52
|
-
text: `import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';\n`,
|
|
53
|
-
},
|
|
54
|
-
]));
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
function ensurePluginAdded(tree, file) {
|
|
59
|
-
const { tsquery } = require('@phenomnomnominal/tsquery');
|
|
60
|
-
const content = tree.read(file, 'utf-8');
|
|
61
|
-
const ast = tsquery.ast(content);
|
|
62
|
-
const foundDefineConfig = tsquery.query(ast, 'CallExpression:has(Identifier[name="defineConfig"])');
|
|
63
|
-
if (!foundDefineConfig.length)
|
|
64
|
-
return content;
|
|
65
|
-
// Do not update defineConfig if it has an arrow function since it can be tricky and error-prone.
|
|
66
|
-
const defineUsingArrowFunction = tsquery.query(foundDefineConfig[0], 'ArrowFunction');
|
|
67
|
-
if (defineUsingArrowFunction.length)
|
|
68
|
-
return content;
|
|
69
|
-
const propertyAssignments = tsquery.query(foundDefineConfig[0], 'PropertyAssignment');
|
|
70
|
-
if (propertyAssignments.length) {
|
|
71
|
-
const pluginsNode = tsquery.query(foundDefineConfig[0], 'PropertyAssignment:has(Identifier[name="plugins"])');
|
|
72
|
-
if (pluginsNode.length) {
|
|
73
|
-
const updated = tsquery.replace(content, 'PropertyAssignment:has(Identifier[name="plugins"])', (node) => {
|
|
74
|
-
const found = tsquery.query(node, 'ArrayLiteralExpression');
|
|
75
|
-
let updatedPluginsString = '';
|
|
76
|
-
const existingPluginNodes = found?.[0].elements ?? [];
|
|
77
|
-
for (const plugin of existingPluginNodes) {
|
|
78
|
-
updatedPluginsString += `${plugin.getText()},`;
|
|
79
|
-
}
|
|
80
|
-
if (!existingPluginNodes?.some((node) => node.getText().includes('nxViteTsPaths'))) {
|
|
81
|
-
updatedPluginsString += ` nxViteTsPaths(),`;
|
|
82
|
-
}
|
|
83
|
-
return `plugins: [${updatedPluginsString}]`;
|
|
84
|
-
});
|
|
17
|
+
const content = tree.read(file, 'utf-8');
|
|
18
|
+
const updated = useNativePaths
|
|
19
|
+
? (0, vite_config_edit_utils_1.addTsconfigPathsResolution)(content)
|
|
20
|
+
: (0, vite_config_edit_utils_1.addTsconfigPathsPlugin)(content, /\.c[jt]s$/.test(file));
|
|
21
|
+
if (updated !== content) {
|
|
85
22
|
tree.write(file, updated);
|
|
86
|
-
|
|
87
|
-
else {
|
|
88
|
-
tree.write(file, (0, devkit_1.applyChangesToString)(content, [
|
|
89
|
-
{
|
|
90
|
-
type: devkit_1.ChangeType.Insert,
|
|
91
|
-
index: propertyAssignments[0].getStart(),
|
|
92
|
-
text: `plugins: [nxViteTsPaths()],
|
|
93
|
-
`,
|
|
94
|
-
},
|
|
95
|
-
]));
|
|
23
|
+
addedPlugin ||= !useNativePaths;
|
|
96
24
|
}
|
|
97
25
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
text: `plugins: [nxViteTsPaths()],`,
|
|
104
|
-
},
|
|
105
|
-
]));
|
|
26
|
+
if (addedPlugin) {
|
|
27
|
+
(0, devkit_1.addDependenciesToPackageJson)(tree, {}, { 'vite-tsconfig-paths': versions_1.viteTsconfigPathsVersion }, undefined, true);
|
|
28
|
+
}
|
|
29
|
+
if (!schema.skipFormat) {
|
|
30
|
+
await (0, devkit_1.formatFiles)(tree);
|
|
106
31
|
}
|
|
107
32
|
}
|
|
108
33
|
exports.default = setupPathsPlugin;
|
|
@@ -20,19 +20,19 @@ The pre-pass handled, mechanically:
|
|
|
20
20
|
- `browser.provider: 'none'` → `'preview'` (only when the value is a direct string literal under `test.browser.provider`)
|
|
21
21
|
- `browser.indexScripts` → `orchestratorScripts` (only as a direct property name)
|
|
22
22
|
|
|
23
|
-
The pre-pass **does not** edit CI provider configs (`.github/workflows/*.yml`, `.gitlab-ci.yml`, `azure-pipelines.yml`, `.circleci/config.yml`, `bitbucket-pipelines.yml`)
|
|
23
|
+
The pre-pass **does not** edit CI provider configs (`.github/workflows/*.yml`, `.gitlab-ci.yml`, `azure-pipelines.yml`, `.circleci/config.yml`, `bitbucket-pipelines.yml`), because YAML structure varies too much. Any matches it finds there are forwarded to you in `impl.agentContext`.
|
|
24
24
|
|
|
25
25
|
**The vast majority of action items below are NOT covered by the pre-pass** and still require your attention — every section other than the six items above.
|
|
26
26
|
|
|
27
|
-
How to read the
|
|
27
|
+
How to read the `impl` fields of the step's `nx_migrate_prompt` block:
|
|
28
28
|
|
|
29
|
-
-
|
|
30
|
-
-
|
|
29
|
+
- `impl.changes` lists files the pre-pass already wrote to. Verify the new shape is in place; do not re-apply the same edit.
|
|
30
|
+
- `impl.agentContext` lists detections the pre-pass forwarded because it could not safely complete them. **Every entry is pending work.** Address each one in the relevant section below, not as a separate task.
|
|
31
31
|
|
|
32
32
|
</pre_pass_summary>
|
|
33
33
|
|
|
34
34
|
<handoff_guidance>
|
|
35
|
-
In your handoff `summary` (1
|
|
35
|
+
In your handoff `summary` (1-3 sentences, per the handoff format), name the breaking-change categories you applied; explicitly call out any you skipped because they didn't apply (e.g., "no browser-mode configs in this workspace").
|
|
36
36
|
</handoff_guidance>
|
|
37
37
|
|
|
38
38
|
## Pre-Migration Checklist
|
|
@@ -19,21 +19,21 @@ The pre-pass handled, mechanically:
|
|
|
19
19
|
- `'verbose'` → `'tree'` and `'basic'` → `['default', { summary: false }]` inside `test.reporters`
|
|
20
20
|
- `VITEST_MAX_{THREADS,FORKS}` → `VITEST_MAX_WORKERS` and `VITE_NODE_DEPS_MODULE_DIRECTORIES` → `VITEST_MODULE_DIRECTORIES` renames in: `package.json` scripts, `.env` / `.env.*` files, `project.json` `options.env` keys, and inline `VAR=value` prefixes inside `project.json` `options.{args,command,commands}`
|
|
21
21
|
|
|
22
|
-
The pre-pass **skips the rename when both `VITEST_MAX_THREADS` and `VITEST_MAX_FORKS` appear in the same file/scope** (they collapse to a single `VITEST_MAX_WORKERS` whose value depends on which pool the project uses
|
|
22
|
+
The pre-pass **skips the rename when both `VITEST_MAX_THREADS` and `VITEST_MAX_FORKS` appear in the same file/scope** (they collapse to a single `VITEST_MAX_WORKERS` whose value depends on which pool the project uses, a decision the pre-pass can't make safely). It also **does not** edit CI provider configs (`.github/workflows/*.yml`, `.gitlab-ci.yml`, `azure-pipelines.yml`, `.circleci/config.yml`, `bitbucket-pipelines.yml`), because YAML structure varies too much. Any conflicts and any CI matches are forwarded to you in `impl.agentContext`.
|
|
23
23
|
|
|
24
24
|
**The cross-cutting changes below still require your attention** — pool option flattening (`singleThread`/`singleFork`, `maxThreads`/`maxForks`, `poolOptions.<pool>.{execArgv,isolate}`, `poolOptions.vmThreads.memoryLimit`), `test.deps.{external,inline,fallbackCJS}` → `test.server.deps.*` move, `test.{poolMatchGlobs,environmentMatchGlobs}` projects rewrite, browser provider function-form rewrite, `browser.testerScripts` → `testerHtmlPath`, inlining of `vitest.workspace.*` files the pre-pass could not inline automatically (+ `defineWorkspace` removal), custom reporter callback API updates, and `@vitest/browser` package replacement with per-provider packages.
|
|
25
25
|
|
|
26
|
-
How to read the
|
|
26
|
+
How to read the `impl` fields of the step's `nx_migrate_prompt` block:
|
|
27
27
|
|
|
28
|
-
-
|
|
29
|
-
-
|
|
28
|
+
- `impl.changes` lists files the pre-pass already wrote to. Verify the new shape is in place; do not re-apply the same edit.
|
|
29
|
+
- `impl.agentContext` lists detections the pre-pass forwarded because it could not safely complete them. **Every entry is pending work.** Address each one in the relevant section below, not as a separate task.
|
|
30
30
|
|
|
31
31
|
A workspace-wide reminder is also emitted as a post-run "next step" about env vars set in CI provider dashboards — those can't be detected from the workspace tree.
|
|
32
32
|
|
|
33
33
|
</pre_pass_summary>
|
|
34
34
|
|
|
35
35
|
<handoff_guidance>
|
|
36
|
-
In your handoff `summary` (1
|
|
36
|
+
In your handoff `summary` (1-3 sentences, per the handoff format), name the breaking-change categories you applied; explicitly call out any you skipped because they didn't apply (e.g., "no custom reporters in this workspace", "no browser-mode configs").
|
|
37
37
|
</handoff_guidance>
|
|
38
38
|
|
|
39
39
|
<prerequisites note="hard runtime requirements; do not edit any vitest config until these are satisfied">
|
|
@@ -198,7 +198,7 @@ export default defineConfig({
|
|
|
198
198
|
**Action Items**:
|
|
199
199
|
|
|
200
200
|
- [ ] Rename `workspace` property to `projects` in all config files.
|
|
201
|
-
- [ ] Inline any external `vitest.workspace.*` content into `test.projects` and delete the workspace file (external file references are no longer supported). The pre-pass already inlined workspace files containing a plain static array of glob strings; the ones you see in
|
|
201
|
+
- [ ] Inline any external `vitest.workspace.*` content into `test.projects` and delete the workspace file (external file references are no longer supported). The pre-pass already inlined workspace files containing a plain static array of glob strings; the ones you see in `impl.agentContext` were skipped because of dynamic content or because the sibling config could not be merged into mechanically (existing `test.projects`/`test.workspace`, non-object-literal config, or a directory with only a `vite.config.*`). For an existing `test.projects`, merge the workspace entries into it; for a `vite.config.*`-only directory, decide whether its `test` block (if any) and the project list belong in that file or a new `vitest.config.*`.
|
|
202
202
|
- [ ] If projects need different pool/environment options, set them inside each project entry rather than via the (now-removed) `poolMatchGlobs` / `environmentMatchGlobs` — see section 1.5.
|
|
203
203
|
|
|
204
204
|
When you inline a workspace file yourself, also apply these checks (the pre-pass applies them for the files it inlines):
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Replace removed @nx/vite executors with inferred tasks
|
|
2
|
+
|
|
3
|
+
Nx 24 removed `@nx/vite:build`, `@nx/vite:dev-server`, `@nx/vite:preview-server` (including old `@nrwl` aliases) and `@nx/vitest:test` (including the old `@nx/vite:test` and `@nrwl/vite:test` names). This migration also converts Vitest targets because `@nx/vitest` may only be installed transitively, so its own migration might not run.
|
|
4
|
+
|
|
5
|
+
Before changing anything, check for leftover work: a project target, a package.json target or a `targetDefaults` entry still uses a removed executor, or the advisory context reports a conversion error. If none applies, make no changes and stop. Treat each advisory-context item as pending work.
|
|
6
|
+
|
|
7
|
+
1. Inspect all affected projects and workspace defaults. Repair config-loading errors first. Do not restore executor registrations or install older Nx packages.
|
|
8
|
+
2. Move build/serve/preview options into Vite configuration or supported CLI flags. Preserve environment modes, output directories, aliases, framework plugins, library entrypoints, assets and server ports. Register `@nx/vitest` for test targets and keep Vitest options in the Vitest config.
|
|
9
|
+
3. Register `@nx/vite/plugin` with options/includes that preserve custom target names and mixed inferred/explicit projects. Replace remaining removed-executor targets, including those in package.json and filtered targetDefaults. Transfer their behavior before removing obsolete defaults. Preserve configurations, dependencies, cache inputs/outputs and environment behavior. Do not silently delete unsupported options or unrelated targets. Migrate old @nrwl aliases too.
|
|
10
|
+
4. Run project graph creation with the daemon and graph cache disabled (`NX_DAEMON=false NX_CACHE_PROJECT_GRAPH=false`), using the workspace package manager. Inspect resolved project targets and verify each migrated entrypoint exists and is inferred (a thin alias to an inferred target is acceptable). Resolve graph errors before completing this migration, even if task validation was skipped. Configs must load for subsequent migrations.
|
|
11
|
+
5. By default run relevant real builds/tests with task cache disabled, including alternate configurations. Honor an existing preference to skip expensive task validation; otherwise offer that option when validation is slow. Skipping expensive tasks never skips conversion or the graph check. Report each skipped task as unverified. Never weaken assertions or change application behavior to make checks pass.
|
|
12
|
+
6. Report converted projects, graph validation, task results and any skipped checks. Unconverted targets or a broken graph mean the migration is incomplete. Investigate task failures and distinguish missing environment prerequisites from conversion regressions; do not claim a working workspace with unresolved regressions.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Migrate Vite config helpers
|
|
2
|
+
|
|
3
|
+
Replace `nxViteTsPaths` and `nxCopyAssetsPlugin`. Their imports remain available for
|
|
4
|
+
compatibility only. Helper behavior was removed in Nx 24; the stubs do not configure builds. Preserve installed Vite versions, bundlers and commands.
|
|
5
|
+
Do not upgrade Vite merely to simplify this migration. Nx 24 also removed the `@nx/vite`
|
|
6
|
+
executors, and a separate migration converts their targets, so do not add them back.
|
|
7
|
+
|
|
8
|
+
## Inventory and baseline
|
|
9
|
+
|
|
10
|
+
Find Vite and Vitest configurations (`.ts`, `.mts`, `.cts`, `.js`, `.mjs`, `.cjs`),
|
|
11
|
+
imported config factories, aliased helper imports, and configuration-specific target
|
|
12
|
+
options. Inspect each config's root, workspace tsconfigs and references, package
|
|
13
|
+
exports, helper options, assets, build output, and modes.
|
|
14
|
+
|
|
15
|
+
Record build/test/serve commands and baseline output. If the currently installed
|
|
16
|
+
packages cannot build the old config, use a separate checkout with the prior
|
|
17
|
+
lockfile. Do not downgrade the workspace or describe untested output as equivalent.
|
|
18
|
+
|
|
19
|
+
## Paths resolution
|
|
20
|
+
|
|
21
|
+
A codemod ran first, but only on workspaces with Vite 8 or newer installed. Where
|
|
22
|
+
it ran it removed `nxViteTsPaths` from `vite.config.*` and `vitest.config.*` and
|
|
23
|
+
set `resolve.tsconfigPaths: true`. It dropped any `buildLibsFromSource` option
|
|
24
|
+
the helper carried, because native resolution has no equivalent; if a project
|
|
25
|
+
relied on building library dependencies instead of resolving their source,
|
|
26
|
+
restore that through the dependency's `package.json` entry points.
|
|
27
|
+
|
|
28
|
+
Confirm the codemod's edits, then handle everything it left: every config if the
|
|
29
|
+
installed Vite is older than 8, and otherwise helper imports under an alias,
|
|
30
|
+
calls outside a plugins array, configs assembled by a factory with branching
|
|
31
|
+
returns, and config files named something else.
|
|
32
|
+
|
|
33
|
+
Check the installed Vite version's types/docs for native `resolve.tsconfigPaths`.
|
|
34
|
+
Verify the relevant source files are included by the intended tsconfig and that
|
|
35
|
+
inherited paths/references are resolved. Preserve existing `resolve` options.
|
|
36
|
+
|
|
37
|
+
Where native support is unavailable or does not preserve the required behavior,
|
|
38
|
+
use a compatible `vite-tsconfig-paths` version. Check its peer dependencies and
|
|
39
|
+
module format against the installed Vite/Node versions before adding it to the
|
|
40
|
+
workspace's dependencies. Preserve CJS/ESM loading; use a supported async import
|
|
41
|
+
when needed instead of requiring an ESM-only package from CommonJS.
|
|
42
|
+
|
|
43
|
+
Map any custom `nxViteTsPaths` options deliberately. Test actual alias imports and
|
|
44
|
+
workspace packages, including exports and buildable-library behavior. Do not
|
|
45
|
+
assume `vite-tsconfig-paths` reproduces Nx's package fallback/remapping logic or
|
|
46
|
+
that TypeScript's editor resolution proves Vite runtime resolution. Check Vitest
|
|
47
|
+
separately if it shares or imports the config. Keep unrelated plugins and their order.
|
|
48
|
+
|
|
49
|
+
## Asset copying
|
|
50
|
+
|
|
51
|
+
Use `publicDir` only for a single directory copied unchanged to the expected output
|
|
52
|
+
root, with equivalent serving behavior. Do not move a user's source assets merely
|
|
53
|
+
to fit that option.
|
|
54
|
+
|
|
55
|
+
For globs, multiple sources/destinations, or assets outside the project, use a
|
|
56
|
+
compatible `vite-plugin-static-copy` version or a local Vite plugin where necessary.
|
|
57
|
+
Inspect the installed replacement's options instead of assuming a one-to-one map.
|
|
58
|
+
|
|
59
|
+
For every string pattern or `{ input, glob, output, ignore }` entry:
|
|
60
|
+
|
|
61
|
+
- Resolve the original source using the old plugin's actual project/workspace root
|
|
62
|
+
semantics. Resolve replacement paths against the Vite root. Include sibling libs.
|
|
63
|
+
- Preserve output-relative subdirectories and filenames; do not flatten directories
|
|
64
|
+
or accidentally add another source-directory segment.
|
|
65
|
+
- Preserve excludes and glob behavior. Translate ignores using syntax supported by
|
|
66
|
+
the selected replacement version and verify excluded files are absent after a
|
|
67
|
+
completed build. Do not simply drop `ignore`.
|
|
68
|
+
- Preserve any existing public directory and collision/overwrite behavior.
|
|
69
|
+
- Verify serving/watch updates as well as production copying. Check copied files
|
|
70
|
+
exist before downstream tasks consume the completed build output.
|
|
71
|
+
|
|
72
|
+
Remove old helper imports/calls after preserving their behavior. Leave unrelated
|
|
73
|
+
configuration and installed framework versions alone.
|
|
74
|
+
|
|
75
|
+
## Acceptance
|
|
76
|
+
|
|
77
|
+
1. Recreate the project graph without disk-cache reuse and verify required targets.
|
|
78
|
+
2. Run affected builds and tests without task-cache reuse.
|
|
79
|
+
3. Compare output file paths and asset bytes with the baseline; confirm expected
|
|
80
|
+
excludes after build completion. Verify alias imports execute/render correctly.
|
|
81
|
+
4. Start the existing dev command on an available user-approved port. Load the app
|
|
82
|
+
and asset, edit a source asset, confirm the served update, then restore it and
|
|
83
|
+
stop the server. Never infer watch behavior from a successful production build.
|
|
84
|
+
5. Search imported configs for deprecated helpers. Already migrated configs should
|
|
85
|
+
need no edits. Report checks and unresolved behavior; do not weaken assertions,
|
|
86
|
+
remove targets, or discard user assets to make the migration pass.
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = migrateNxViteTsPaths;
|
|
4
|
+
const devkit_1 = require("@nx/devkit");
|
|
5
|
+
const vite_config_edit_utils_1 = require("../../utils/vite-config-edit-utils");
|
|
6
|
+
const version_utils_1 = require("../../utils/version-utils");
|
|
7
|
+
const CONFIG_FILE = /(?:^|\/)(?:vite|vitest)\.config\.[cm]?[jt]s$/;
|
|
8
|
+
const PLUGIN_SPECIFIER = '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
|
9
|
+
// Generated configs carry a commented-out worker example that calls the plugin.
|
|
10
|
+
const WORKER_EXAMPLE = /^([ \t]*\/\/)\s*plugins: \(\) => \[ nxViteTsPaths\(\) \],[ \t]*$/m;
|
|
11
|
+
async function migrateNxViteTsPaths(tree) {
|
|
12
|
+
// `resolve.tsconfigPaths` landed in Vite 8. On anything older the option is
|
|
13
|
+
// ignored, so swapping the plugin for it would silently drop alias
|
|
14
|
+
// resolution; the prompt picks those workspaces up instead.
|
|
15
|
+
const installedMajor = (0, version_utils_1.getInstalledViteMajorVersion)(tree);
|
|
16
|
+
if (!installedMajor || installedMajor < 8) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
let changed = false;
|
|
20
|
+
(0, devkit_1.visitNotIgnoredFiles)(tree, '.', (filePath) => {
|
|
21
|
+
if (!CONFIG_FILE.test(filePath))
|
|
22
|
+
return;
|
|
23
|
+
const original = tree.read(filePath, 'utf-8');
|
|
24
|
+
if (!original?.includes('nxViteTsPaths'))
|
|
25
|
+
return;
|
|
26
|
+
const withResolution = (0, vite_config_edit_utils_1.addTsconfigPathsResolution)(original);
|
|
27
|
+
if (!(0, vite_config_edit_utils_1.hasTsconfigPathsResolution)(withResolution))
|
|
28
|
+
return;
|
|
29
|
+
let updated = removePluginUsage(withResolution);
|
|
30
|
+
if (updated === withResolution)
|
|
31
|
+
return;
|
|
32
|
+
updated = updated.replace(WORKER_EXAMPLE, '$1 plugins: [],');
|
|
33
|
+
tree.write(filePath, updated);
|
|
34
|
+
changed = true;
|
|
35
|
+
});
|
|
36
|
+
if (changed) {
|
|
37
|
+
await (0, devkit_1.formatFiles)(tree);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Drops every `nxViteTsPaths()` call and its import. Bails on the whole file if
|
|
42
|
+
* any call sits somewhere other than directly inside an array, since removing
|
|
43
|
+
* one from an arbitrary expression leaves a syntax hole. The shipped prompt
|
|
44
|
+
* handles what this leaves behind.
|
|
45
|
+
*/
|
|
46
|
+
function removePluginUsage(content) {
|
|
47
|
+
const { tsquery } = require('@phenomnomnominal/tsquery');
|
|
48
|
+
const tsModule = require('typescript');
|
|
49
|
+
const file = tsquery.ast(content);
|
|
50
|
+
const importsPlugin = file.statements.some((statement) => {
|
|
51
|
+
if (tsModule.isImportDeclaration(statement) &&
|
|
52
|
+
tsModule.isStringLiteral(statement.moduleSpecifier) &&
|
|
53
|
+
statement.moduleSpecifier.text === PLUGIN_SPECIFIER) {
|
|
54
|
+
const bindings = statement.importClause?.namedBindings;
|
|
55
|
+
return (bindings &&
|
|
56
|
+
tsModule.isNamedImports(bindings) &&
|
|
57
|
+
bindings.elements.some((element) => !element.propertyName && element.name.text === 'nxViteTsPaths'));
|
|
58
|
+
}
|
|
59
|
+
if (!tsModule.isVariableStatement(statement))
|
|
60
|
+
return false;
|
|
61
|
+
return statement.declarationList.declarations.some(({ name, initializer }) => tsModule.isObjectBindingPattern(name) &&
|
|
62
|
+
name.elements.some((element) => !element.propertyName &&
|
|
63
|
+
element.name.getText() === 'nxViteTsPaths') &&
|
|
64
|
+
initializer &&
|
|
65
|
+
tsModule.isCallExpression(initializer) &&
|
|
66
|
+
initializer.expression.getText() === 'require' &&
|
|
67
|
+
initializer.arguments.length === 1 &&
|
|
68
|
+
tsModule.isStringLiteral(initializer.arguments[0]) &&
|
|
69
|
+
initializer.arguments[0].text === PLUGIN_SPECIFIER);
|
|
70
|
+
});
|
|
71
|
+
if (!importsPlugin)
|
|
72
|
+
return content;
|
|
73
|
+
const calls = tsquery.query(file, 'CallExpression:has(Identifier[name="nxViteTsPaths"])').filter((call) => call.expression.getText() === 'nxViteTsPaths');
|
|
74
|
+
if (!calls.length)
|
|
75
|
+
return content;
|
|
76
|
+
const arrays = new Map();
|
|
77
|
+
for (const call of calls) {
|
|
78
|
+
const parent = call.parent;
|
|
79
|
+
if (!parent || !tsModule.isArrayLiteralExpression(parent))
|
|
80
|
+
return content;
|
|
81
|
+
const siblings = arrays.get(parent) ?? [];
|
|
82
|
+
siblings.push(call);
|
|
83
|
+
arrays.set(parent, siblings);
|
|
84
|
+
}
|
|
85
|
+
const changes = [];
|
|
86
|
+
// Reprinting the array from its surviving elements keeps separators valid no
|
|
87
|
+
// matter how many entries are dropped; formatting is restored afterwards.
|
|
88
|
+
for (const [array, removed] of arrays) {
|
|
89
|
+
const survivors = array.elements.filter((element) => !removed.includes(element));
|
|
90
|
+
changes.push({
|
|
91
|
+
type: devkit_1.ChangeType.Delete,
|
|
92
|
+
start: array.getStart(),
|
|
93
|
+
length: array.getEnd() - array.getStart(),
|
|
94
|
+
});
|
|
95
|
+
changes.push({
|
|
96
|
+
type: devkit_1.ChangeType.Insert,
|
|
97
|
+
index: array.getStart(),
|
|
98
|
+
text: `[${survivors.map((element) => element.getText()).join(', ')}]`,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
// A reference outside the removed calls still needs the (inert) stub import.
|
|
102
|
+
const survivingReference = tsquery.query(file, 'Identifier[name="nxViteTsPaths"]').some((id) => !calls.some((call) => call.expression === id) &&
|
|
103
|
+
!tsModule.isImportSpecifier(id.parent) &&
|
|
104
|
+
!tsModule.isBindingElement(id.parent));
|
|
105
|
+
if (survivingReference)
|
|
106
|
+
return (0, devkit_1.applyChangesToString)(content, changes);
|
|
107
|
+
for (const node of findSolePluginImports(tsModule, tsquery, file)) {
|
|
108
|
+
changes.push({
|
|
109
|
+
type: devkit_1.ChangeType.Delete,
|
|
110
|
+
start: node.getStart(),
|
|
111
|
+
length: trailingNewlineEnd(content, node.getEnd()) - node.getStart(),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return (0, devkit_1.applyChangesToString)(content, changes);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Import and require statements that bring in nothing but the plugin. Anything
|
|
118
|
+
* sharing the statement stays put; an unused binding is harmless next to a
|
|
119
|
+
* broken one.
|
|
120
|
+
*/
|
|
121
|
+
function findSolePluginImports(tsModule, tsquery, file) {
|
|
122
|
+
const imports = tsquery.query(file, `ImportDeclaration:has(StringLiteral[value="${PLUGIN_SPECIFIER}"])`);
|
|
123
|
+
const requires = tsquery.query(file, `VariableStatement:has(StringLiteral[value="${PLUGIN_SPECIFIER}"])`);
|
|
124
|
+
const sole = [];
|
|
125
|
+
for (const node of imports) {
|
|
126
|
+
const bindings = node.importClause?.namedBindings;
|
|
127
|
+
if (!node.importClause?.name &&
|
|
128
|
+
bindings &&
|
|
129
|
+
tsModule.isNamedImports(bindings) &&
|
|
130
|
+
bindings.elements.length === 1) {
|
|
131
|
+
sole.push(node);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
for (const node of requires) {
|
|
135
|
+
const declarations = node.declarationList.declarations;
|
|
136
|
+
if (declarations.length !== 1)
|
|
137
|
+
continue;
|
|
138
|
+
const name = declarations[0].name;
|
|
139
|
+
if (tsModule.isObjectBindingPattern(name) &&
|
|
140
|
+
name.elements.length === 1 &&
|
|
141
|
+
name.elements[0].name.getText() === 'nxViteTsPaths') {
|
|
142
|
+
sole.push(node);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return sole;
|
|
146
|
+
}
|
|
147
|
+
function trailingNewlineEnd(content, end) {
|
|
148
|
+
while (content[end] === ' ' ||
|
|
149
|
+
content[end] === '\t' ||
|
|
150
|
+
content[end] === ';') {
|
|
151
|
+
end++;
|
|
152
|
+
}
|
|
153
|
+
return content[end] === '\n' ? end + 1 : end;
|
|
154
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = update;
|
|
4
|
+
const devkit_1 = require("@nx/devkit");
|
|
5
|
+
const internal_1 = require("@nx/js/internal");
|
|
6
|
+
async function update(tree) {
|
|
7
|
+
if (!(0, internal_1.registerTypescriptPluginForTypecheck)(tree, '@nx/vite/plugin')) {
|
|
8
|
+
return { skipAgentic: true };
|
|
9
|
+
}
|
|
10
|
+
await (0, devkit_1.formatFiles)(tree);
|
|
11
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#### Register `@nx/js/typescript` for typecheck targets
|
|
2
|
+
|
|
3
|
+
`@nx/vite/plugin` no longer infers a `typecheck` target, except for Vue projects, which keep their `vue-tsc` target. `@nx/js/typescript` provides the `typecheck` target instead, in all workspaces. This migration registers `@nx/js/typescript` with only its typecheck target when the workspace uses `@nx/vite/plugin` and doesn't register `@nx/js/typescript` yet, so your projects keep a `typecheck` target.
|
|
4
|
+
|
|
5
|
+
The new registration reuses the plugin's `typecheckTargetName` and, when it's `tsgo`, its `compiler`. Registrations with `typecheckTargetName: false` are skipped. `@nx/js/typescript` is registered before `@nx/vite/plugin`, so the Vue projects' `vue-tsc` target wins. Keep that order.
|
|
6
|
+
|
|
7
|
+
#### Sample code changes
|
|
8
|
+
|
|
9
|
+
##### Before
|
|
10
|
+
|
|
11
|
+
```json title="nx.json"
|
|
12
|
+
{
|
|
13
|
+
"plugins": [
|
|
14
|
+
{
|
|
15
|
+
"plugin": "@nx/vite/plugin",
|
|
16
|
+
"options": { "typecheckTargetName": "typecheck" }
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
##### After
|
|
23
|
+
|
|
24
|
+
```json title="nx.json"
|
|
25
|
+
{
|
|
26
|
+
"plugins": [
|
|
27
|
+
{
|
|
28
|
+
"plugin": "@nx/js/typescript",
|
|
29
|
+
"options": { "typecheck": { "targetName": "typecheck" } }
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"plugin": "@nx/vite/plugin",
|
|
33
|
+
"options": { "typecheckTargetName": "typecheck" }
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
```
|