@nx/playwright 23.0.0-pr.35465.2bc2643 → 23.0.0-rc.1

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.
Files changed (67) hide show
  1. package/{index.d.ts → dist/index.d.ts} +0 -1
  2. package/{plugin.d.ts → dist/plugin.d.ts} +0 -1
  3. package/{preset.d.ts → dist/preset.d.ts} +0 -1
  4. package/{src → dist/src}/executors/merge-reports/merge-reports.impl.d.ts +0 -1
  5. package/{src → dist/src}/executors/merge-reports/merge-reports.impl.js +8 -2
  6. package/{src → dist/src}/executors/playwright/playwright.impl.d.ts +0 -1
  7. package/{src → dist/src}/executors/playwright/playwright.impl.js +2 -0
  8. package/{src → dist/src}/executors/playwright/schema.json +1 -0
  9. package/{src → dist/src}/generators/configuration/configuration.d.ts +0 -1
  10. package/{src → dist/src}/generators/configuration/configuration.js +55 -27
  11. package/{src/generators/configuration/files/playwright.config.ts.template → dist/src/generators/configuration/files/playwright.config.mts.template} +10 -3
  12. package/{src → dist/src}/generators/convert-to-inferred/convert-to-inferred.d.ts +0 -1
  13. package/{src → dist/src}/generators/convert-to-inferred/convert-to-inferred.js +5 -3
  14. package/{src → dist/src}/generators/init/init.d.ts +0 -1
  15. package/{src → dist/src}/generators/init/init.js +5 -3
  16. package/{src → dist/src}/generators/init/schema.json +1 -1
  17. package/dist/src/migrations/update-23-0-0/migrate-create-nodes-v2-to-create-nodes.d.ts +9 -0
  18. package/dist/src/migrations/update-23-0-0/migrate-create-nodes-v2-to-create-nodes.js +225 -0
  19. package/dist/src/plugins/plugin.d.ts +7 -0
  20. package/{src → dist/src}/plugins/plugin.js +57 -28
  21. package/{src → dist/src}/utils/add-linter.d.ts +0 -1
  22. package/{src → dist/src}/utils/add-linter.js +12 -14
  23. package/dist/src/utils/assert-supported-playwright-version.d.ts +2 -0
  24. package/dist/src/utils/assert-supported-playwright-version.js +8 -0
  25. package/dist/src/utils/deprecation.d.ts +3 -0
  26. package/dist/src/utils/deprecation.js +16 -0
  27. package/{src → dist/src}/utils/preset.d.ts +4 -2
  28. package/{src → dist/src}/utils/preset.js +15 -3
  29. package/{src → dist/src}/utils/reporters.d.ts +0 -1
  30. package/dist/src/utils/versions.d.ts +5 -0
  31. package/dist/src/utils/versions.js +9 -0
  32. package/executors.json +4 -4
  33. package/generators.json +6 -6
  34. package/migrations.json +8 -1
  35. package/package.json +61 -34
  36. package/index.d.ts.map +0 -1
  37. package/plugin.d.ts.map +0 -1
  38. package/preset.d.ts.map +0 -1
  39. package/src/executors/merge-reports/merge-reports.impl.d.ts.map +0 -1
  40. package/src/executors/playwright/playwright.impl.d.ts.map +0 -1
  41. package/src/generators/configuration/configuration.d.ts.map +0 -1
  42. package/src/generators/convert-to-inferred/convert-to-inferred.d.ts.map +0 -1
  43. package/src/generators/init/init.d.ts.map +0 -1
  44. package/src/migrations/update-19-6-0/use-serve-static-preview-for-command.d.ts +0 -1
  45. package/src/migrations/update-19-6-0/use-serve-static-preview-for-command.d.ts.map +0 -1
  46. package/src/migrations/update-19-6-0/use-serve-static-preview-for-command.js +0 -0
  47. package/src/plugins/plugin.d.ts +0 -8
  48. package/src/plugins/plugin.d.ts.map +0 -1
  49. package/src/utils/add-linter.d.ts.map +0 -1
  50. package/src/utils/preset.d.ts.map +0 -1
  51. package/src/utils/reporters.d.ts.map +0 -1
  52. package/src/utils/versions.d.ts +0 -4
  53. package/src/utils/versions.d.ts.map +0 -1
  54. package/src/utils/versions.js +0 -6
  55. /package/{LICENSE → dist/LICENSE} +0 -0
  56. /package/{PLUGIN.md → dist/PLUGIN.md} +0 -0
  57. /package/{index.js → dist/index.js} +0 -0
  58. /package/{plugin.js → dist/plugin.js} +0 -0
  59. /package/{preset.js → dist/preset.js} +0 -0
  60. /package/{src → dist/src}/executors/merge-reports/schema.d.ts +0 -0
  61. /package/{src → dist/src}/executors/merge-reports/schema.json +0 -0
  62. /package/{src → dist/src}/generators/configuration/files/__directory__/example.spec.ts.template +0 -0
  63. /package/{src → dist/src}/generators/configuration/schema.d.ts +0 -0
  64. /package/{src → dist/src}/generators/configuration/schema.json +0 -0
  65. /package/{src → dist/src}/generators/convert-to-inferred/schema.json +0 -0
  66. /package/{src → dist/src}/generators/init/schema.d.ts +0 -0
  67. /package/{src → dist/src}/utils/reporters.js +0 -0
@@ -1,4 +1,3 @@
1
1
  export { playwrightExecutor, PlaywrightExecutorSchema, } from './src/executors/playwright/playwright.impl';
2
2
  export { initGenerator } from './src/generators/init/init';
3
3
  export { configurationGenerator } from './src/generators/configuration/configuration';
4
- //# sourceMappingURL=index.d.ts.map
@@ -1,2 +1 @@
1
1
  export { createNodes, createNodesV2, PlaywrightPluginOptions, } from './src/plugins/plugin';
2
- //# sourceMappingURL=plugin.d.ts.map
@@ -1,2 +1 @@
1
1
  export * from './src/utils/preset';
2
- //# sourceMappingURL=preset.d.ts.map
@@ -4,4 +4,3 @@ export declare function mergeReportsExecutor(options: Schema, context: ExecutorC
4
4
  success: boolean;
5
5
  }>;
6
6
  export default mergeReportsExecutor;
7
- //# sourceMappingURL=merge-reports.impl.d.ts.map
@@ -1,17 +1,23 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.mergeReportsExecutor = mergeReportsExecutor;
4
+ const internal_1 = require("@nx/devkit/internal");
4
5
  const devkit_1 = require("@nx/devkit");
5
- const config_utils_1 = require("@nx/devkit/src/utils/config-utils");
6
6
  const node_child_process_1 = require("node:child_process");
7
7
  const node_fs_1 = require("node:fs");
8
8
  const node_path_1 = require("node:path");
9
+ const semver_1 = require("semver");
9
10
  const reporters_1 = require("../../utils/reporters");
11
+ const versions_1 = require("../../utils/versions");
10
12
  async function mergeReportsExecutor(options, context) {
13
+ const installed = (0, internal_1.getInstalledPackageVersion)('@playwright/test');
14
+ if (installed && (0, semver_1.lt)(installed, versions_1.minPlaywrightVersionForBlobReports)) {
15
+ throw new Error(`The "@nx/playwright:merge-reports" executor requires "@playwright/test" version ${versions_1.minPlaywrightVersionForBlobReports} or greater (the version that introduced the "blob" reporter and the "merge-reports" CLI). You are currently using version ${installed}.`);
16
+ }
11
17
  const { config, expectedSuites } = options;
12
18
  const projectRoot = (0, node_path_1.join)(context.root, context.projectsConfigurations.projects[context.projectName].root);
13
19
  const configPath = (0, node_path_1.join)(projectRoot, config);
14
- const playwrightConfig = await (0, config_utils_1.loadConfigFile)(configPath);
20
+ const playwrightConfig = await (0, internal_1.loadConfigFile)(configPath);
15
21
  const reporterOutputs = (0, reporters_1.getReporterOutputs)(playwrightConfig);
16
22
  const blobReporterOutput = reporterOutputs.find(([reporter]) => reporter === 'blob');
17
23
  if (!blobReporterOutput) {
@@ -37,4 +37,3 @@ export declare function playwrightExecutor(options: PlaywrightExecutorSchema, co
37
37
  success: boolean;
38
38
  }>;
39
39
  export default playwrightExecutor;
40
- //# sourceMappingURL=playwright.impl.d.ts.map
@@ -3,7 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.playwrightExecutor = playwrightExecutor;
4
4
  const devkit_1 = require("@nx/devkit");
5
5
  const child_process_1 = require("child_process");
6
+ const deprecation_1 = require("../../utils/deprecation");
6
7
  async function playwrightExecutor(options, context) {
8
+ (0, deprecation_1.warnPlaywrightExecutorDeprecation)();
7
9
  const projectRoot = context.projectGraph?.nodes?.[context?.projectName]?.data?.root;
8
10
  if (!projectRoot) {
9
11
  throw new Error(`Unable to find the Project Root for ${context.projectName}. Is it set in the project.json?`);
@@ -3,6 +3,7 @@
3
3
  "version": 2,
4
4
  "title": "Playwright executor",
5
5
  "description": "Run Playwright tests.",
6
+ "x-deprecated": "The `@nx/playwright:playwright` executor is deprecated and will be removed in Nx v24. Run `nx g @nx/playwright:convert-to-inferred` to migrate to the `@nx/playwright/plugin` inferred targets. See https://nx.dev/docs/guides/tasks--caching/convert-to-inferred for details.",
6
7
  "type": "object",
7
8
  "properties": {
8
9
  "browser": {
@@ -3,4 +3,3 @@ import type { ConfigurationGeneratorSchema } from './schema';
3
3
  export declare function configurationGenerator(tree: Tree, options: ConfigurationGeneratorSchema): Promise<GeneratorCallback>;
4
4
  export declare function configurationGeneratorInternal(tree: Tree, rawOptions: ConfigurationGeneratorSchema): Promise<GeneratorCallback>;
5
5
  export default configurationGenerator;
6
- //# sourceMappingURL=configuration.d.ts.map
@@ -3,24 +3,23 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.configurationGenerator = configurationGenerator;
4
4
  exports.configurationGeneratorInternal = configurationGeneratorInternal;
5
5
  const tslib_1 = require("tslib");
6
+ const internal_1 = require("@nx/devkit/internal");
6
7
  const devkit_1 = require("@nx/devkit");
7
- const project_name_and_root_utils_1 = require("@nx/devkit/src/generators/project-name-and-root-utils");
8
- const prompt_1 = require("@nx/devkit/src/generators/prompt");
9
8
  const js_1 = require("@nx/js");
10
- const generator_prompts_1 = require("@nx/js/src/utils/generator-prompts");
11
- const package_manager_workspaces_1 = require("@nx/js/src/utils/package-manager-workspaces");
12
- const ensure_typescript_1 = require("@nx/js/src/utils/typescript/ensure-typescript");
13
- const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-setup");
9
+ const internal_2 = require("@nx/js/internal");
10
+ const deprecation_1 = require("../../utils/deprecation");
14
11
  const child_process_1 = require("child_process");
15
12
  const path = tslib_1.__importStar(require("path"));
16
13
  const add_linter_1 = require("../../utils/add-linter");
14
+ const assert_supported_playwright_version_1 = require("../../utils/assert-supported-playwright-version");
17
15
  const versions_1 = require("../../utils/versions");
18
16
  const init_1 = require("../init/init");
19
- const eslint_file_1 = require("@nx/eslint/src/generators/utils/eslint-file");
17
+ const internal_3 = require("@nx/eslint/internal");
20
18
  function configurationGenerator(tree, options) {
21
19
  return configurationGeneratorInternal(tree, { addPlugin: false, ...options });
22
20
  }
23
21
  async function configurationGeneratorInternal(tree, rawOptions) {
22
+ (0, assert_supported_playwright_version_1.assertSupportedPlaywrightVersion)(tree);
24
23
  const options = await normalizeOptions(tree, rawOptions);
25
24
  const tasks = [];
26
25
  tasks.push(await (0, init_1.initGenerator)(tree, {
@@ -30,14 +29,25 @@ async function configurationGeneratorInternal(tree, rawOptions) {
30
29
  }));
31
30
  const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, options.project);
32
31
  const offsetFromProjectRoot = (0, devkit_1.offsetFromRoot)(projectConfig.root);
32
+ const isTsSolutionSetup = (0, internal_2.isUsingTsSolutionSetup)(tree);
33
+ // Always emit `playwright.config.mts`. Node forces `.mts` to ESM
34
+ // regardless of workspace `type`, so Playwright's runtime routes it
35
+ // through the ESM loader (`requireOrImport` -> dynamic `import()`),
36
+ // bypassing the pirates CJS-compile path that breaks ESM-shape `.ts`
37
+ // configs. Nx's native TS strip loads `.mts` directly via `loadTsFile`.
38
+ // Playwright's configLoader auto-discovers `.mts` (extension list at
39
+ // configLoader.js:313 is `.ts/.js/.mts/.mjs/.cts/.cjs`).
33
40
  (0, devkit_1.generateFiles)(tree, path.join(__dirname, 'files'), projectConfig.root, {
34
41
  offsetFromRoot: offsetFromProjectRoot,
35
42
  projectRoot: projectConfig.root,
36
43
  webServerCommand: options.webServerCommand ?? null,
37
44
  webServerAddress: options.webServerAddress ?? null,
45
+ isTsSolutionSetup,
38
46
  ...options,
39
47
  });
40
- const isTsSolutionSetup = (0, ts_solution_setup_1.isUsingTsSolutionSetup)(tree);
48
+ const playwrightConfigFile = options.js
49
+ ? 'playwright.config.mjs'
50
+ : 'playwright.config.mts';
41
51
  const tsconfigPath = (0, devkit_1.joinPathFragments)(projectConfig.root, 'tsconfig.json');
42
52
  if (tree.exists(tsconfigPath)) {
43
53
  if (isTsSolutionSetup) {
@@ -51,7 +61,7 @@ async function configurationGeneratorInternal(tree, rawOptions) {
51
61
  include: [
52
62
  (0, devkit_1.joinPathFragments)(options.directory, '**/*.ts'),
53
63
  (0, devkit_1.joinPathFragments)(options.directory, '**/*.js'),
54
- 'playwright.config.ts',
64
+ playwrightConfigFile,
55
65
  ],
56
66
  exclude: ['out-tsc', 'test-output'],
57
67
  };
@@ -79,7 +89,7 @@ async function configurationGeneratorInternal(tree, rawOptions) {
79
89
  include: [
80
90
  '**/*.ts',
81
91
  '**/*.js',
82
- 'playwright.config.ts',
92
+ playwrightConfigFile,
83
93
  'src/**/*.spec.ts',
84
94
  'src/**/*.spec.js',
85
95
  'src/**/*.test.ts',
@@ -112,7 +122,7 @@ async function configurationGeneratorInternal(tree, rawOptions) {
112
122
  if (isTsSolutionSetup) {
113
123
  const packageJsonPath = (0, devkit_1.joinPathFragments)(projectConfig.root, 'package.json');
114
124
  if (!tree.exists(packageJsonPath)) {
115
- const importPath = (0, project_name_and_root_utils_1.resolveImportPath)(tree, projectConfig.name, projectConfig.root);
125
+ const importPath = (0, internal_1.resolveImportPath)(tree, projectConfig.name, projectConfig.root);
116
126
  const packageJson = {
117
127
  name: importPath,
118
128
  version: '0.0.1',
@@ -129,6 +139,7 @@ async function configurationGeneratorInternal(tree, rawOptions) {
129
139
  ? p === '@nx/playwright/plugin'
130
140
  : p.plugin === '@nx/playwright/plugin');
131
141
  if (!hasPlugin) {
142
+ (0, deprecation_1.warnPlaywrightExecutorGenerating)();
132
143
  addE2eTarget(tree, options);
133
144
  setupE2ETargetDefaults(tree);
134
145
  }
@@ -143,8 +154,8 @@ async function configurationGeneratorInternal(tree, rawOptions) {
143
154
  addPlugin: options.addPlugin,
144
155
  }));
145
156
  if (options.js) {
146
- const { ModuleKind } = (0, ensure_typescript_1.ensureTypescript)();
147
- (0, devkit_1.toJS)(tree, { extension: '.cjs', module: ModuleKind.CommonJS });
157
+ const { ModuleKind } = (0, internal_2.ensureTypescript)();
158
+ (0, devkit_1.toJS)(tree, { extension: '.mjs', module: ModuleKind.ESNext });
148
159
  }
149
160
  recommendVsCodeExtensions(tree);
150
161
  if (!options.skipPackageJson) {
@@ -160,9 +171,9 @@ async function configurationGeneratorInternal(tree, rawOptions) {
160
171
  await (0, devkit_1.formatFiles)(tree);
161
172
  }
162
173
  if (isTsSolutionSetup) {
163
- const projectPackageManagerWorkspaceState = (0, package_manager_workspaces_1.getProjectPackageManagerWorkspaceState)(tree, projectConfig.root);
174
+ const projectPackageManagerWorkspaceState = (0, internal_2.getProjectPackageManagerWorkspaceState)(tree, projectConfig.root);
164
175
  if (projectPackageManagerWorkspaceState !== 'included') {
165
- tasks.push((0, package_manager_workspaces_1.getProjectPackageManagerWorkspaceStateWarningTask)(projectPackageManagerWorkspaceState, tree.root));
176
+ tasks.push((0, internal_2.getProjectPackageManagerWorkspaceStateWarningTask)(projectPackageManagerWorkspaceState, tree.root));
166
177
  }
167
178
  }
168
179
  return (0, devkit_1.runTasksInSerial)(...tasks);
@@ -172,7 +183,7 @@ async function normalizeOptions(tree, options) {
172
183
  const addPlugin = options.addPlugin ??
173
184
  (process.env.NX_ADD_PLUGINS !== 'false' &&
174
185
  nxJson.useInferencePlugins !== false);
175
- const linter = await (0, generator_prompts_1.normalizeLinterOption)(tree, options.linter);
186
+ const linter = await (0, internal_2.normalizeLinterOption)(tree, options.linter);
176
187
  if (!options.webServerCommand || !options.webServerAddress) {
177
188
  const { webServerCommand, webServerAddress } = await promptForMissingServeData(options.project);
178
189
  options.webServerCommand = webServerCommand;
@@ -186,7 +197,7 @@ async function normalizeOptions(tree, options) {
186
197
  };
187
198
  }
188
199
  async function promptForMissingServeData(projectName) {
189
- const { command, port } = await (0, prompt_1.promptWhenInteractive)([
200
+ const { command, port } = await (0, internal_1.promptWhenInteractive)([
190
201
  {
191
202
  type: 'input',
192
203
  name: 'command',
@@ -243,15 +254,30 @@ function setupE2ETargetDefaults(tree) {
243
254
  return;
244
255
  }
245
256
  // E2e targets depend on all their project's sources + production sources of dependencies
246
- nxJson.targetDefaults ??= {};
247
257
  const productionFileSet = !!nxJson.namedInputs?.production;
248
- nxJson.targetDefaults.e2e ??= {};
249
- nxJson.targetDefaults.e2e.cache ??= true;
250
- nxJson.targetDefaults.e2e.inputs ??= [
251
- 'default',
252
- productionFileSet ? '^production' : '^default',
253
- ];
254
- (0, devkit_1.updateNxJson)(tree, nxJson);
258
+ // Either a `target: 'e2e'` default or a default keyed on the executor
259
+ // we're about to scaffold will apply to the new target — consider both
260
+ // before deciding to add cache/inputs. Target-keyed wins when both are
261
+ // present.
262
+ const existingForTarget = (0, internal_1.findTargetDefault)(nxJson.targetDefaults, {
263
+ target: 'e2e',
264
+ });
265
+ const existingForExecutor = (0, internal_1.findTargetDefault)(nxJson.targetDefaults, {
266
+ executor: '@nx/playwright:playwright',
267
+ });
268
+ const existingCache = existingForTarget?.cache ?? existingForExecutor?.cache;
269
+ const existingInputs = existingForTarget?.inputs ?? existingForExecutor?.inputs;
270
+ const patch = {};
271
+ if (existingCache === undefined) {
272
+ patch.cache = true;
273
+ }
274
+ if (existingInputs === undefined) {
275
+ patch.inputs = ['default', productionFileSet ? '^production' : '^default'];
276
+ }
277
+ if (Object.keys(patch).length > 0) {
278
+ (0, internal_1.upsertTargetDefault)(tree, nxJson, { target: 'e2e', ...patch });
279
+ (0, devkit_1.updateNxJson)(tree, nxJson);
280
+ }
255
281
  }
256
282
  function addE2eTarget(tree, options) {
257
283
  const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, options.project);
@@ -264,7 +290,9 @@ Rename or remove the existing e2e target.`);
264
290
  executor: '@nx/playwright:playwright',
265
291
  outputs: [`{workspaceRoot}/dist/.playwright/${projectConfig.root}`],
266
292
  options: {
267
- config: `${projectConfig.root}/playwright.config.${options.js ? 'cjs' : 'ts'}`,
293
+ // Generator emits `playwright.config.mts` (`.mjs` for `--js`) so the
294
+ // legacy executor's `--config` flag must point at the same extension.
295
+ config: `${projectConfig.root}/playwright.config.${options.js ? 'mjs' : 'mts'}`,
268
296
  },
269
297
  };
270
298
  (0, devkit_1.updateProjectConfiguration)(tree, options.project, projectConfig);
@@ -272,7 +300,7 @@ Rename or remove the existing e2e target.`);
272
300
  function ignoreTestOutput(tree, options) {
273
301
  // Make sure playwright outputs are not linted.
274
302
  if (options.linter === 'eslint') {
275
- (0, eslint_file_1.addIgnoresToLintConfig)(tree, '', ['**/test-output']);
303
+ (0, internal_3.addIgnoresToLintConfig)(tree, '', ['**/test-output']);
276
304
  }
277
305
  // Handle gitignore
278
306
  if (!tree.exists('.gitignore')) {
@@ -9,13 +9,20 @@ const baseURL = process.env['BASE_URL'] || '<% if(webServerAddress) {%><%= webSe
9
9
  * Read environment variables from file.
10
10
  * https://github.com/motdotla/dotenv
11
11
  */
12
- // require('dotenv').config();
12
+ // import 'dotenv/config';
13
13
 
14
14
  /**
15
15
  * See https://playwright.dev/docs/test-configuration.
16
+ *
17
+ * Generated as a .mts file so Node forces ESM regardless of workspace
18
+ * `type`. Playwright routes `.mts` through its ESM loader (dynamic import,
19
+ * bypassing the pirates CJS-compile path), and Nx's native TS strip loads
20
+ * `.mts` directly. Playwright's configLoader auto-discovers
21
+ * `playwright.config.mts` via its extension list
22
+ * (.ts/.js/.mts/.mjs/.cts/.cjs).
16
23
  */
17
24
  export default defineConfig({
18
- ...nxE2EPreset(__filename, { testDir: './<%= directory %>' }),
25
+ ...nxE2EPreset(import.meta.dirname, { testDir: './<%= directory %>' }),
19
26
  /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
20
27
  use: {
21
28
  baseURL,
@@ -50,7 +57,7 @@ export default defineConfig({
50
57
  name: "webkit",
51
58
  use: { ...devices["Desktop Safari"] },
52
59
  },
53
-
60
+
54
61
  // Uncomment for mobile browsers support
55
62
  /* {
56
63
  name: 'Mobile Chrome',
@@ -6,4 +6,3 @@ interface Schema {
6
6
  }
7
7
  export declare function convertToInferred(tree: Tree, options: Schema): Promise<void>;
8
8
  export default convertToInferred;
9
- //# sourceMappingURL=convert-to-inferred.d.ts.map
@@ -1,12 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.convertToInferred = convertToInferred;
4
+ const internal_1 = require("@nx/devkit/internal");
4
5
  const devkit_1 = require("@nx/devkit");
5
6
  const plugin_1 = require("../../plugins/plugin");
6
- const executor_to_plugin_migrator_1 = require("@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator");
7
+ const assert_supported_playwright_version_1 = require("../../utils/assert-supported-playwright-version");
7
8
  async function convertToInferred(tree, options) {
9
+ (0, assert_supported_playwright_version_1.assertSupportedPlaywrightVersion)(tree);
8
10
  const projectGraph = await (0, devkit_1.createProjectGraphAsync)();
9
- const migratedProjects = await (0, executor_to_plugin_migrator_1.migrateProjectExecutorsToPlugin)(tree, projectGraph, '@nx/playwright/plugin', plugin_1.createNodesV2, { targetName: 'e2e', ciTargetName: 'e2e-ci' }, [
11
+ const migratedProjects = await (0, internal_1.migrateProjectExecutorsToPlugin)(tree, projectGraph, '@nx/playwright/plugin', plugin_1.createNodesV2, { targetName: 'e2e', ciTargetName: 'e2e-ci' }, [
10
12
  {
11
13
  executors: ['@nx/playwright:playwright'],
12
14
  postTargetTransformer,
@@ -14,7 +16,7 @@ async function convertToInferred(tree, options) {
14
16
  },
15
17
  ], options.project);
16
18
  if (migratedProjects.size === 0) {
17
- throw new executor_to_plugin_migrator_1.NoTargetsToMigrateError();
19
+ throw new internal_1.NoTargetsToMigrateError();
18
20
  }
19
21
  if (!options.skipFormat) {
20
22
  await (0, devkit_1.formatFiles)(tree);
@@ -3,4 +3,3 @@ import { InitGeneratorSchema } from './schema';
3
3
  export declare function initGenerator(tree: Tree, options: InitGeneratorSchema): Promise<GeneratorCallback>;
4
4
  export declare function initGeneratorInternal(tree: Tree, options: InitGeneratorSchema): Promise<GeneratorCallback>;
5
5
  export default initGenerator;
6
- //# sourceMappingURL=init.d.ts.map
@@ -2,14 +2,16 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.initGenerator = initGenerator;
4
4
  exports.initGeneratorInternal = initGeneratorInternal;
5
+ const internal_1 = require("@nx/devkit/internal");
5
6
  const devkit_1 = require("@nx/devkit");
6
- const add_plugin_1 = require("@nx/devkit/src/utils/add-plugin");
7
7
  const plugin_1 = require("../../plugins/plugin");
8
+ const assert_supported_playwright_version_1 = require("../../utils/assert-supported-playwright-version");
8
9
  const versions_1 = require("../../utils/versions");
9
10
  function initGenerator(tree, options) {
10
11
  return initGeneratorInternal(tree, { addPlugin: false, ...options });
11
12
  }
12
13
  async function initGeneratorInternal(tree, options) {
14
+ (0, assert_supported_playwright_version_1.assertSupportedPlaywrightVersion)(tree);
13
15
  const tasks = [];
14
16
  const nxJson = (0, devkit_1.readNxJson)(tree);
15
17
  const addPluginDefault = process.env.NX_ADD_PLUGINS !== 'false' &&
@@ -19,10 +21,10 @@ async function initGeneratorInternal(tree, options) {
19
21
  tasks.push((0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
20
22
  '@nx/playwright': versions_1.nxVersion,
21
23
  '@playwright/test': versions_1.playwrightVersion,
22
- }, undefined, options.keepExistingVersions));
24
+ }, undefined, options.keepExistingVersions ?? true));
23
25
  }
24
26
  if (options.addPlugin) {
25
- await (0, add_plugin_1.addPlugin)(tree, await (0, devkit_1.createProjectGraphAsync)(), '@nx/playwright/plugin', plugin_1.createNodesV2, { targetName: ['e2e', 'playwright:e2e', 'playwright-e2e'] }, options.updatePackageScripts);
27
+ await (0, internal_1.addPlugin)(tree, await (0, devkit_1.createProjectGraphAsync)(), '@nx/playwright/plugin', plugin_1.createNodesV2, { targetName: ['e2e', 'playwright:e2e', 'playwright-e2e'] }, options.updatePackageScripts);
26
28
  }
27
29
  if (!options.skipFormat) {
28
30
  await (0, devkit_1.formatFiles)(tree);
@@ -21,7 +21,7 @@
21
21
  "type": "boolean",
22
22
  "x-priority": "internal",
23
23
  "description": "Keep existing dependencies versions",
24
- "default": false
24
+ "default": true
25
25
  },
26
26
  "updatePackageScripts": {
27
27
  "type": "boolean",
@@ -0,0 +1,9 @@
1
+ import { type Tree } from '@nx/devkit';
2
+ export default function migrateCreateNodesV2ToCreateNodes(tree: Tree): Promise<void>;
3
+ /**
4
+ * Rewrites named imports and re-exports of `createNodesV2` to `createNodes`
5
+ * when they come from one of the given module specifiers. Only the named
6
+ * bindings are touched — the module specifier, the `import`/`export` keyword,
7
+ * any `type` modifier, and any default import are left untouched.
8
+ */
9
+ export declare function rewriteCreateNodesV2Imports(source: string, specifiers: ReadonlySet<string>): string;
@@ -0,0 +1,225 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = migrateCreateNodesV2ToCreateNodes;
4
+ exports.rewriteCreateNodesV2Imports = rewriteCreateNodesV2Imports;
5
+ const devkit_1 = require("@nx/devkit");
6
+ const TS_EXTENSIONS = ['.ts', '.tsx', '.cts', '.mts'];
7
+ const DEPRECATED_NAME = 'createNodesV2';
8
+ const CANONICAL_NAME = 'createNodes';
9
+ // Module specifiers from which `@nx/playwright` publicly exposes `createNodesV2`.
10
+ // A named import or re-export of `createNodesV2` from one of these is rewritten
11
+ // to the canonical `createNodes` export.
12
+ const TARGET_SPECIFIERS = new Set([
13
+ '@nx/playwright/plugin',
14
+ ]);
15
+ let ts;
16
+ async function migrateCreateNodesV2ToCreateNodes(tree) {
17
+ let touchedCount = 0;
18
+ (0, devkit_1.visitNotIgnoredFiles)(tree, '.', (filePath) => {
19
+ if (!TS_EXTENSIONS.some((ext) => filePath.endsWith(ext))) {
20
+ return;
21
+ }
22
+ const original = tree.read(filePath, 'utf-8');
23
+ if (!original || !original.includes(DEPRECATED_NAME)) {
24
+ return;
25
+ }
26
+ const updated = rewriteCreateNodesV2Imports(original, TARGET_SPECIFIERS);
27
+ if (updated !== original) {
28
+ tree.write(filePath, updated);
29
+ touchedCount += 1;
30
+ }
31
+ });
32
+ if (touchedCount > 0) {
33
+ devkit_1.logger.info(`Renamed \`${DEPRECATED_NAME}\` imports to \`${CANONICAL_NAME}\` in ${touchedCount} file(s).`);
34
+ }
35
+ await (0, devkit_1.formatFiles)(tree);
36
+ }
37
+ /**
38
+ * Rewrites named imports and re-exports of `createNodesV2` to `createNodes`
39
+ * when they come from one of the given module specifiers. Only the named
40
+ * bindings are touched — the module specifier, the `import`/`export` keyword,
41
+ * any `type` modifier, and any default import are left untouched.
42
+ */
43
+ function rewriteCreateNodesV2Imports(source, specifiers) {
44
+ ts ??= (0, devkit_1.ensurePackage)('typescript', '*');
45
+ const sourceFile = ts.createSourceFile('tmp.ts', source, ts.ScriptTarget.Latest,
46
+ /* setParentNodes */ true, ts.ScriptKind.TSX);
47
+ const changes = [];
48
+ let renameLocalUsages = false;
49
+ for (const stmt of sourceFile.statements) {
50
+ if (ts.isImportDeclaration(stmt)) {
51
+ renameLocalUsages =
52
+ collectImportRewrite(sourceFile, stmt, specifiers, changes) ||
53
+ renameLocalUsages;
54
+ }
55
+ else if (ts.isExportDeclaration(stmt)) {
56
+ collectExportRewrite(sourceFile, stmt, specifiers, changes);
57
+ }
58
+ }
59
+ // Renaming a local `createNodesV2` import binding to `createNodes` (a lone
60
+ // `{ createNodesV2 }`, or one deduped against an existing `createNodes`)
61
+ // changes the name in scope, so value references to `createNodesV2` in the
62
+ // file body must be renamed too — otherwise they dangle. Aliased imports and
63
+ // re-exports keep their local name, so they never trigger this.
64
+ if (renameLocalUsages) {
65
+ collectValueUsageRewrites(sourceFile, changes);
66
+ }
67
+ return changes.length > 0 ? (0, devkit_1.applyChangesToString)(source, changes) : source;
68
+ }
69
+ function isTargetSpecifier(node, specifiers) {
70
+ return ts.isStringLiteral(node) && specifiers.has(node.text);
71
+ }
72
+ function collectImportRewrite(sourceFile, stmt, specifiers, changes) {
73
+ if (!isTargetSpecifier(stmt.moduleSpecifier, specifiers)) {
74
+ return false;
75
+ }
76
+ const namedBindings = stmt.importClause?.namedBindings;
77
+ // Only `import { ... }` carries renameable named bindings. `import x`,
78
+ // `import * as ns`, and side-effect imports reference the module wholesale
79
+ // and keep working through the `createNodesV2` runtime alias, so we leave
80
+ // them be. A mixed `import def, { createNodesV2 }` still has its named
81
+ // bindings rewritten below — the default binding is untouched.
82
+ if (!namedBindings || !ts.isNamedImports(namedBindings)) {
83
+ return false;
84
+ }
85
+ // The local `createNodesV2` binding only disappears when it is imported
86
+ // without an alias — a lone `{ createNodesV2 }` or one deduped against an
87
+ // existing `createNodes`. `{ createNodesV2 as x }` keeps the local `x`, so
88
+ // its in-file usages are unaffected and must not be rewritten.
89
+ const localBindingRenamed = namedBindings.elements.some((el) => el.name.text === DEPRECATED_NAME &&
90
+ (el.propertyName ?? el.name).text === DEPRECATED_NAME);
91
+ rewriteNamedBindings(sourceFile, namedBindings, changes);
92
+ return localBindingRenamed;
93
+ }
94
+ function collectExportRewrite(sourceFile, stmt, specifiers, changes) {
95
+ if (!stmt.moduleSpecifier ||
96
+ !isTargetSpecifier(stmt.moduleSpecifier, specifiers)) {
97
+ return;
98
+ }
99
+ // `export { ... } from '...'` can be rewritten; `export * from '...'` has no
100
+ // named bindings to rename.
101
+ if (!stmt.exportClause || !ts.isNamedExports(stmt.exportClause)) {
102
+ return;
103
+ }
104
+ rewriteNamedBindings(sourceFile, stmt.exportClause, changes);
105
+ }
106
+ /**
107
+ * Re-renders the `{ ... }` of a named import/export, renaming any
108
+ * `createNodesV2` specifier to `createNodes`. If renaming would collide with a
109
+ * `createNodes` that is already present (e.g. `{ createNodes, createNodesV2 }`),
110
+ * the duplicate is dropped. Returns without recording a change when the binding
111
+ * list contains no `createNodesV2`.
112
+ */
113
+ function rewriteNamedBindings(sourceFile, namedBindings, changes) {
114
+ const elements = namedBindings.elements;
115
+ const hasDeprecated = elements.some((el) => (el.propertyName ?? el.name).text === DEPRECATED_NAME);
116
+ if (!hasDeprecated) {
117
+ return;
118
+ }
119
+ const seen = new Set();
120
+ const rendered = [];
121
+ for (const el of elements) {
122
+ const text = renderSpecifier(el);
123
+ if (!seen.has(text)) {
124
+ seen.add(text);
125
+ rendered.push(text);
126
+ }
127
+ }
128
+ const start = namedBindings.getStart(sourceFile);
129
+ changes.push({
130
+ type: devkit_1.ChangeType.Delete,
131
+ start,
132
+ length: namedBindings.getEnd() - start,
133
+ }, {
134
+ type: devkit_1.ChangeType.Insert,
135
+ index: start,
136
+ text: `{ ${rendered.join(', ')} }`,
137
+ });
138
+ }
139
+ function renderSpecifier(el) {
140
+ const typePrefix = el.isTypeOnly ? 'type ' : '';
141
+ const rename = (name) => name === DEPRECATED_NAME ? CANONICAL_NAME : name;
142
+ // `{ name }` — no alias, so the local binding follows the rename.
143
+ if (!el.propertyName) {
144
+ return `${typePrefix}${rename(el.name.text)}`;
145
+ }
146
+ // `{ propertyName as name }` — only the imported (left) side is renamed; the
147
+ // local alias is preserved. A now-redundant alias such as
148
+ // `createNodesV2 as createNodes` collapses to `createNodes`.
149
+ const canonicalImported = rename(el.propertyName.text);
150
+ const localName = el.name.text;
151
+ return canonicalImported === localName
152
+ ? `${typePrefix}${localName}`
153
+ : `${typePrefix}${canonicalImported} as ${localName}`;
154
+ }
155
+ /**
156
+ * Renames value references of `createNodesV2` to `createNodes` in the file
157
+ * body. Only called once a local `createNodesV2` import binding has actually
158
+ * been renamed, so these references would otherwise dangle. Occurrences that
159
+ * are not references to that binding are skipped: the import/export
160
+ * declarations themselves, property accesses (`x.createNodesV2`), qualified
161
+ * type names, object-literal keys, and declaration names that shadow the
162
+ * import. A shorthand property (`{ createNodesV2 }`) is expanded to
163
+ * `{ createNodesV2: createNodes }` so the property key is preserved. Strings
164
+ * and comments are never `Identifier` nodes, so they are left alone.
165
+ */
166
+ function collectValueUsageRewrites(sourceFile, changes) {
167
+ const visit = (node) => {
168
+ if (ts.isIdentifier(node) &&
169
+ node.text === DEPRECATED_NAME &&
170
+ isRenamableValueUsage(node)) {
171
+ const start = node.getStart(sourceFile);
172
+ changes.push({
173
+ type: devkit_1.ChangeType.Delete,
174
+ start,
175
+ length: node.getEnd() - start,
176
+ }, {
177
+ type: devkit_1.ChangeType.Insert,
178
+ index: start,
179
+ text: ts.isShorthandPropertyAssignment(node.parent)
180
+ ? `${DEPRECATED_NAME}: ${CANONICAL_NAME}`
181
+ : CANONICAL_NAME,
182
+ });
183
+ }
184
+ node.forEachChild(visit);
185
+ };
186
+ sourceFile.forEachChild(visit);
187
+ }
188
+ /**
189
+ * Whether a `createNodesV2` identifier is a value reference to the renamed
190
+ * import binding, as opposed to a position that must be left untouched.
191
+ */
192
+ function isRenamableValueUsage(node) {
193
+ const parent = node.parent;
194
+ if (!parent) {
195
+ return false;
196
+ }
197
+ // Import/export bindings — already handled by the declaration rewrite.
198
+ if (ts.isImportSpecifier(parent) ||
199
+ ts.isExportSpecifier(parent) ||
200
+ ts.isImportClause(parent) ||
201
+ ts.isNamespaceImport(parent)) {
202
+ return false;
203
+ }
204
+ // `x.createNodesV2` / `X.createNodesV2` — a member name, not the binding.
205
+ if (ts.isPropertyAccessExpression(parent) && parent.name === node) {
206
+ return false;
207
+ }
208
+ if (ts.isQualifiedName(parent) && parent.right === node) {
209
+ return false;
210
+ }
211
+ // `{ createNodesV2: ... }` — an object-literal key, not the binding.
212
+ if (ts.isPropertyAssignment(parent) && parent.name === node) {
213
+ return false;
214
+ }
215
+ // A declaration whose name shadows the import (variable, param, etc.).
216
+ if ((ts.isVariableDeclaration(parent) ||
217
+ ts.isParameter(parent) ||
218
+ ts.isBindingElement(parent) ||
219
+ ts.isFunctionDeclaration(parent) ||
220
+ ts.isClassDeclaration(parent)) &&
221
+ parent.name === node) {
222
+ return false;
223
+ }
224
+ return true;
225
+ }
@@ -0,0 +1,7 @@
1
+ import { type CreateNodes } from '@nx/devkit';
2
+ export interface PlaywrightPluginOptions {
3
+ targetName?: string;
4
+ ciTargetName?: string;
5
+ }
6
+ export declare const createNodes: CreateNodes<PlaywrightPluginOptions>;
7
+ export declare const createNodesV2: CreateNodes<PlaywrightPluginOptions>;