@nx/plugin 23.2.0-beta.1 → 23.2.0-beta.11

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 (27) hide show
  1. package/README.md +2 -2
  2. package/dist/src/generators/create-package/create-package.js +6 -4
  3. package/dist/src/generators/create-package/files/create-framework-package/bin/index.ts__tmpl__ +1 -1
  4. package/dist/src/generators/create-package/files/e2e/__cliName__.spec.ts__tmpl__ +3 -1
  5. package/dist/src/generators/create-package/schema.d.ts +2 -2
  6. package/dist/src/generators/create-package/schema.json +2 -2
  7. package/dist/src/generators/create-package/utils/normalize-schema.d.ts +1 -1
  8. package/dist/src/generators/e2e-project/e2e.d.ts +1 -1
  9. package/dist/src/generators/e2e-project/e2e.js +118 -7
  10. package/dist/src/generators/e2e-project/files/src/__simplePluginName__.spec.ts__tmpl__ +5 -2
  11. package/dist/src/generators/e2e-project/schema.d.ts +3 -2
  12. package/dist/src/generators/e2e-project/schema.json +8 -2
  13. package/dist/src/generators/lint-checks/generator.d.ts +1 -1
  14. package/dist/src/generators/lint-checks/generator.js +5 -6
  15. package/dist/src/generators/migration/migration.js +1 -2
  16. package/dist/src/generators/plugin/files/plugin/src/index.ts__tmpl__ +1 -0
  17. package/dist/src/generators/plugin/plugin.js +6 -0
  18. package/dist/src/generators/plugin/schema.d.ts +7 -3
  19. package/dist/src/generators/plugin/schema.json +11 -5
  20. package/dist/src/generators/plugin/utils/normalize-schema.d.ts +1 -1
  21. package/dist/src/generators/preset/generator.js +8 -4
  22. package/dist/src/generators/preset/schema.d.ts +5 -2
  23. package/dist/src/generators/preset/schema.json +5 -0
  24. package/dist/src/utils/testing-utils/nx-project.js +3 -4
  25. package/dist/src/utils/testing-utils/utils.d.ts +1 -1
  26. package/dist/src/utils/testing-utils/utils.js +4 -4
  27. package/package.json +14 -6
package/README.md CHANGED
@@ -7,9 +7,9 @@
7
7
 
8
8
  <div style="text-align: center;">
9
9
 
10
- [![License](https://img.shields.io/npm/l/@nx/workspace.svg?style=flat-square)]()
10
+ [![License](https://img.shields.io/npm/l/@nx/workspace.svg?style=flat-square)](<>)
11
11
  [![NPM Version](https://badge.fury.io/js/nx.svg)](https://www.npmjs.com/package/nx)
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)]()
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)](<>)
13
13
  [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
14
14
  [![Join us on the Official Nx Discord Server](https://img.shields.io/discord/1143497901675401286?label=discord)](https://go.nx.dev/community)
15
15
  [![Nx Sandboxing](https://staging.nx.app/workspaces/62d013ea0852fe0a2df74438/sandbox-badge.svg)](https://nx.dev/docs/features/ci-features/sandboxing)
@@ -5,11 +5,11 @@ exports.createPackageGeneratorInternal = createPackageGeneratorInternal;
5
5
  const devkit_1 = require("@nx/devkit");
6
6
  const js_1 = require("@nx/js");
7
7
  const internal_1 = require("@nx/js/internal");
8
- const versions_1 = require("nx/src/utils/versions");
9
8
  const path_1 = require("path");
10
9
  const has_generator_1 = require("../../utils/has-generator");
11
10
  const generator_1 = require("../generator/generator");
12
11
  const normalize_schema_1 = require("./utils/normalize-schema");
12
+ const internal_2 = require("@nx/devkit/internal");
13
13
  async function createPackageGenerator(host, schema) {
14
14
  return await createPackageGeneratorInternal(host, {
15
15
  useProjectJson: true,
@@ -25,7 +25,7 @@ async function createPackageGeneratorInternal(host, schema) {
25
25
  tasks.push((0, js_1.addTsLibDependencies)(host));
26
26
  }
27
27
  const installTask = (0, devkit_1.addDependenciesToPackageJson)(host, {
28
- 'create-nx-workspace': versions_1.nxVersion,
28
+ 'create-nx-workspace': internal_2.nxVersion,
29
29
  }, {});
30
30
  tasks.push(installTask);
31
31
  const cliPackageTask = await createCliPackage(host, options, pluginPackageName);
@@ -52,7 +52,9 @@ async function addPresetGenerator(host, schema) {
52
52
  path: (0, path_1.join)(projectRoot, 'src/generators/preset/generator'),
53
53
  unitTestRunner: schema.unitTestRunner,
54
54
  skipFormat: true,
55
- skipLintChecks: schema.linter === 'none',
55
+ // Lint checks are an ESLint-only feature; asking for them under any other
56
+ // linter makes `pluginLintCheckGenerator` log an error and do nothing.
57
+ skipLintChecks: schema.linter !== 'eslint',
56
58
  });
57
59
  }
58
60
  return (0, devkit_1.readJson)(host, (0, devkit_1.joinPathFragments)(projectRoot, 'package.json'))?.name;
@@ -86,7 +88,7 @@ async function createCliPackage(host, options, pluginPackageName) {
86
88
  delete packageJson.exports;
87
89
  }
88
90
  packageJson.dependencies = {
89
- 'create-nx-workspace': versions_1.nxVersion,
91
+ 'create-nx-workspace': internal_2.nxVersion,
90
92
  ...(options.bundler === 'tsc' && { tslib: internal_1.tsLibVersion }),
91
93
  };
92
94
  return packageJson;
@@ -3,7 +3,7 @@
3
3
  import { createWorkspace } from 'create-nx-workspace';
4
4
 
5
5
  async function main() {
6
- const name = process.argv[2]; // TODO: use libraries like yargs or enquirer to set your workspace name
6
+ const name = process.argv[2]; // TODO: use libraries like yargs, <%= unitTestRunner === 'jest' ? 'enquirer' : '@clack/prompts' %>, or another prompting library to set your workspace name
7
7
  if (!name) {
8
8
  throw new Error('Please provide a name for the workspace');
9
9
  }
@@ -16,6 +16,8 @@ describe('<%= cliName %>', () => {
16
16
  });
17
17
 
18
18
 
19
+ // This test shells out synchronously, so its budget has to cover a cold
20
+ // package manager cache. Otherwise work that succeeded still fails on return.
19
21
  it('should be installed', () => {
20
22
  projectDirectory = createTestProject();
21
23
 
@@ -24,7 +26,7 @@ describe('<%= cliName %>', () => {
24
26
  cwd: projectDirectory,
25
27
  stdio: 'inherit',
26
28
  });
27
- });
29
+ }, 180_000);
28
30
  });
29
31
 
30
32
  /**
@@ -1,4 +1,4 @@
1
- import type { Linter, LinterType } from '@nx/eslint';
1
+ import type { LinterType } from '@nx/js';
2
2
 
3
3
  export interface CreatePackageSchema {
4
4
  name: string;
@@ -9,7 +9,7 @@ export interface CreatePackageSchema {
9
9
  skipFormat?: boolean;
10
10
  tags?: string;
11
11
  unitTestRunner?: 'jest' | 'vitest' | 'none';
12
- linter?: Linter | LinterType;
12
+ linter?: LinterType;
13
13
  compiler?: 'swc' | 'tsc';
14
14
 
15
15
  // options to create e2e project, passed to e2e project generator
@@ -37,9 +37,9 @@
37
37
  "description": "Test runner to use for unit tests."
38
38
  },
39
39
  "linter": {
40
- "description": "The tool to use for running lint checks.",
40
+ "description": "The tool to use for running lint checks. Defaults to the linter the workspace already uses.",
41
41
  "type": "string",
42
- "enum": ["none", "eslint"]
42
+ "enum": ["none", "eslint", "oxlint"]
43
43
  },
44
44
  "tags": {
45
45
  "type": "string",
@@ -1,5 +1,5 @@
1
1
  import { Tree } from '@nx/devkit';
2
- import type { LinterType } from '@nx/eslint';
2
+ import type { LinterType } from '@nx/js';
3
3
  import { CreatePackageSchema } from '../schema';
4
4
  export interface NormalizedSchema extends CreatePackageSchema {
5
5
  bundler: 'swc' | 'tsc';
@@ -1,4 +1,4 @@
1
- import { type GeneratorCallback, type Tree } from '@nx/devkit';
1
+ import { Tree, type GeneratorCallback } from '@nx/devkit';
2
2
  import type { Schema } from './schema';
3
3
  export declare function e2eProjectGenerator(host: Tree, schema: Schema): Promise<GeneratorCallback>;
4
4
  export declare function e2eProjectGeneratorInternal(host: Tree, schema: Schema): Promise<GeneratorCallback>;
@@ -4,11 +4,11 @@ exports.e2eProjectGenerator = e2eProjectGenerator;
4
4
  exports.e2eProjectGeneratorInternal = e2eProjectGeneratorInternal;
5
5
  const internal_1 = require("@nx/devkit/internal");
6
6
  const devkit_1 = require("@nx/devkit");
7
- const eslint_1 = require("@nx/eslint");
8
7
  const jest_1 = require("@nx/jest");
9
8
  const js_1 = require("@nx/js");
10
9
  const internal_2 = require("@nx/js/internal");
11
10
  const path_1 = require("path");
11
+ const versions_1 = require("../../utils/versions");
12
12
  async function normalizeOptions(host, options) {
13
13
  const linter = await (0, internal_2.normalizeLinterOption)(host, options.linter);
14
14
  const projectName = options.rootProject ? 'e2e' : `${options.pluginName}-e2e`;
@@ -112,19 +112,122 @@ async function addJest(host, options) {
112
112
  }
113
113
  return jestTask;
114
114
  }
115
+ async function addVitest(host, options) {
116
+ const projectConfiguration = {
117
+ name: options.projectName,
118
+ root: options.projectRoot,
119
+ projectType: 'application',
120
+ sourceRoot: `${options.projectRoot}/src`,
121
+ implicitDependencies: [options.pluginName],
122
+ };
123
+ if (options.isTsSolutionSetup) {
124
+ (0, devkit_1.writeJson)(host, (0, devkit_1.joinPathFragments)(options.projectRoot, 'package.json'), {
125
+ name: options.projectName,
126
+ version: '0.0.1',
127
+ private: true,
128
+ });
129
+ (0, devkit_1.updateProjectConfiguration)(host, options.projectName, projectConfiguration);
130
+ }
131
+ else {
132
+ projectConfiguration.targets = {};
133
+ (0, devkit_1.addProjectConfiguration)(host, options.projectName, projectConfiguration);
134
+ }
135
+ (0, devkit_1.ensurePackage)('@nx/vitest', versions_1.nxVersion);
136
+ // Use `require` rather than a dynamic `import()`: `ensurePackage` makes the
137
+ // on-demand-installed package resolvable via CJS resolution only, so a true
138
+ // ESM dynamic import cannot see the temp install.
139
+ const { configurationGenerator: vitestConfigurationGenerator, } = require('@nx/vitest/generators');
140
+ const vitestTask = await vitestConfigurationGenerator(host, {
141
+ project: options.projectName,
142
+ testTarget: 'e2e',
143
+ skipFormat: true,
144
+ addPlugin: options.addPlugin,
145
+ testEnvironment: 'node',
146
+ coverageProvider: 'none',
147
+ });
148
+ (0, internal_2.addLocalRegistryScripts)(host);
149
+ // Vitest has no `globalTeardown` option. Its `globalSetup` file must export
150
+ // both `setup` and `teardown`, so wire the local registry scripts through a
151
+ // wrapper module. Without the teardown, the verdaccio process started in
152
+ // setup outlives the test run.
153
+ const vitestGlobalSetupPath = 'tools/scripts/vitest-global-setup.ts';
154
+ if (!host.exists(vitestGlobalSetupPath)) {
155
+ host.write(vitestGlobalSetupPath, `/**
156
+ * This script adapts the local registry scripts to vitest's globalSetup
157
+ * lifecycle: vitest calls the exported setup and teardown functions around
158
+ * the test run.
159
+ */
160
+
161
+ export { default as setup } from './start-local-registry';
162
+ export { default as teardown } from './stop-local-registry';
163
+ `);
164
+ }
165
+ // Add globalSetup to vitest config
166
+ // Check for both .mts and .ts extensions (mts is checked first as it's the default created by @nx/vitest)
167
+ const vitestConfigExtensions = ['mts', 'ts'];
168
+ let vitestConfigPath;
169
+ for (const ext of vitestConfigExtensions) {
170
+ const configPath = (0, devkit_1.joinPathFragments)(options.projectRoot, `vitest.config.${ext}`);
171
+ if (host.exists(configPath)) {
172
+ vitestConfigPath = configPath;
173
+ break;
174
+ }
175
+ }
176
+ if (vitestConfigPath) {
177
+ let vitestConfig = host.read(vitestConfigPath, 'utf-8');
178
+ const globalSetupPath = (0, path_1.join)((0, devkit_1.offsetFromRoot)(options.projectRoot), vitestGlobalSetupPath);
179
+ // Insert globalSetup in the test config
180
+ // Look for 'test: {' and insert our properties right after the opening brace
181
+ const testConfigRegex = /(test:\s*\{\s*)/;
182
+ const match = testConfigRegex.exec(vitestConfig);
183
+ if (match) {
184
+ // Extract the indentation from the next line to maintain consistent formatting
185
+ const afterMatch = vitestConfig.slice(match.index + match[0].length);
186
+ const nextLineMatch = afterMatch.match(/\n(\s*)/);
187
+ const indent = nextLineMatch ? nextLineMatch[1] : ' ';
188
+ vitestConfig = vitestConfig.replace(testConfigRegex, `$1\n${indent}globalSetup: '${globalSetupPath}',`);
189
+ host.write(vitestConfigPath, vitestConfig);
190
+ }
191
+ else {
192
+ // If we can't find the test config block, log a warning
193
+ throw new Error(`Could not find test configuration block in ${vitestConfigPath}. Please manually add the globalSetup property.`);
194
+ }
195
+ }
196
+ else {
197
+ // This should not happen as the vitest configuration generator should create the config file
198
+ throw new Error(`Could not find Vitest config for project ${options.projectName} at ${options.projectRoot}`);
199
+ }
200
+ const project = (0, devkit_1.readProjectConfiguration)(host, options.projectName);
201
+ project.targets ??= {};
202
+ if (project.targets.e2e) {
203
+ const e2eTarget = project.targets.e2e;
204
+ // The suites share a single tmp/test-project directory, so they have to run
205
+ // one at a time. Vitest 4 removed `poolOptions`, and nested options do not
206
+ // survive the executor's argv round-trip anyway, so use the scalar options.
207
+ project.targets.e2e = {
208
+ ...e2eTarget,
209
+ dependsOn: [`^build`],
210
+ options: {
211
+ ...e2eTarget.options,
212
+ maxWorkers: 1,
213
+ isolate: false,
214
+ },
215
+ };
216
+ (0, devkit_1.updateProjectConfiguration)(host, options.projectName, project);
217
+ }
218
+ return vitestTask;
219
+ }
115
220
  async function addLintingToApplication(tree, options) {
116
- const lintTask = await (0, eslint_1.lintProjectGenerator)(tree, {
221
+ return (0, internal_2.addLintingToProject)(tree, {
117
222
  linter: options.linter,
118
223
  project: options.projectName,
119
224
  tsConfigPaths: [
120
225
  (0, devkit_1.joinPathFragments)(options.projectRoot, 'tsconfig.app.json'),
121
226
  ],
122
- unitTestRunner: 'jest',
123
- skipFormat: true,
124
- setParserOptionsProject: false,
227
+ unitTestRunner: options.testRunner ?? 'jest',
228
+ enableTypedLinting: false,
125
229
  addPlugin: options.addPlugin,
126
230
  });
127
- return lintTask;
128
231
  }
129
232
  function updatePluginPackageJson(tree, options) {
130
233
  const { root } = (0, devkit_1.readProjectConfiguration)(tree, options.pluginName);
@@ -145,11 +248,19 @@ async function e2eProjectGeneratorInternal(host, schema) {
145
248
  const tasks = [];
146
249
  validatePlugin(host, schema.pluginName);
147
250
  const options = await normalizeOptions(host, schema);
251
+ // Default to jest if no testRunner is specified
252
+ options.testRunner = options.testRunner ?? 'jest';
148
253
  addFiles(host, options);
149
254
  tasks.push(await (0, js_1.setupVerdaccio)(host, {
150
255
  skipFormat: true,
151
256
  }));
152
- tasks.push(await addJest(host, options));
257
+ // Add test runner based on the testRunner option
258
+ if (options.testRunner === 'vitest') {
259
+ tasks.push(await addVitest(host, options));
260
+ }
261
+ else {
262
+ tasks.push(await addJest(host, options));
263
+ }
153
264
  updatePluginPackageJson(host, options);
154
265
  if (options.linter !== 'none') {
155
266
  tasks.push(await addLintingToApplication(host, {
@@ -5,17 +5,20 @@ import { mkdirSync, rmSync } from 'fs';
5
5
  describe('<%= pluginName %>', () => {
6
6
  let projectDirectory: string;
7
7
 
8
+ // This hook shells out synchronously twice, so its budget has to cover both
9
+ // installs on a cold package manager cache. Otherwise work that succeeded
10
+ // still fails on return.
8
11
  beforeAll(() => {
9
12
  projectDirectory = createTestProject();
10
13
 
11
- // The plugin has been built and published to a local registry in the jest globalSetup
14
+ // The plugin has been built and published to a local registry in the globalSetup
12
15
  // Install the plugin built with the latest source code into the test repo
13
16
  execSync(`<%= packageManagerCommands.addDev %> <%= pluginPackageName %>@e2e`, {
14
17
  cwd: projectDirectory,
15
18
  stdio: 'inherit',
16
19
  env: process.env,
17
20
  });
18
- });
21
+ }, 300_000);
19
22
 
20
23
  afterAll(() => {
21
24
  if (projectDirectory) {
@@ -1,4 +1,4 @@
1
- import type { Linter, LinterType } from '@nx/eslint';
1
+ import type { LinterType } from '@nx/js';
2
2
 
3
3
  export interface Schema {
4
4
  pluginName: string;
@@ -6,7 +6,8 @@ export interface Schema {
6
6
  projectDirectory?: string;
7
7
  pluginOutputPath?: string;
8
8
  jestConfig?: string;
9
- linter?: Linter | LinterType;
9
+ testRunner?: 'jest' | 'vitest';
10
+ linter?: LinterType;
10
11
  skipFormat?: boolean;
11
12
  rootProject?: boolean;
12
13
  useProjectJson?: boolean;
@@ -30,10 +30,16 @@
30
30
  "type": "string",
31
31
  "description": "Jest config file."
32
32
  },
33
+ "testRunner": {
34
+ "type": "string",
35
+ "enum": ["jest", "vitest"],
36
+ "description": "Test runner to use for the e2e tests.",
37
+ "default": "jest"
38
+ },
33
39
  "linter": {
34
- "description": "The tool to use for running lint checks.",
40
+ "description": "The tool to use for running lint checks. Defaults to the linter the workspace already uses.",
35
41
  "type": "string",
36
- "enum": ["none", "eslint"]
42
+ "enum": ["none", "eslint", "oxlint"]
37
43
  },
38
44
  "minimal": {
39
45
  "type": "boolean",
@@ -1,7 +1,7 @@
1
1
  import { ProjectConfiguration, TargetConfiguration, Tree } from '@nx/devkit';
2
2
  import type { Schema as EsLintExecutorOptions } from '@nx/eslint/internal';
3
3
  import { PluginLintChecksGeneratorSchema } from './schema';
4
- import { PackageJson } from 'nx/src/utils/package-json';
4
+ import { PackageJson } from '@nx/devkit/internal';
5
5
  export default function pluginLintCheckGenerator(host: Tree, options: PluginLintChecksGeneratorSchema): Promise<void>;
6
6
  export declare function addMigrationJsonChecks(host: Tree, options: PluginLintChecksGeneratorSchema, packageJson: PackageJson): void;
7
7
  export declare function getEsLintOptions(project: ProjectConfiguration): [target: string, configuration: TargetConfiguration<EsLintExecutorOptions>];
@@ -4,9 +4,8 @@ exports.default = pluginLintCheckGenerator;
4
4
  exports.addMigrationJsonChecks = addMigrationJsonChecks;
5
5
  exports.getEsLintOptions = getEsLintOptions;
6
6
  const devkit_1 = require("@nx/devkit");
7
- const logger_1 = require("nx/src/utils/logger");
8
- const package_json_1 = require("nx/src/utils/package-json");
9
7
  const internal_1 = require("@nx/eslint/internal");
8
+ const internal_2 = require("@nx/devkit/internal");
10
9
  async function pluginLintCheckGenerator(host, options) {
11
10
  const project = (0, devkit_1.readProjectConfiguration)(host, options.projectName);
12
11
  const packageJson = (0, devkit_1.readJson)(host, (0, devkit_1.joinPathFragments)(project.root, 'package.json'));
@@ -21,7 +20,7 @@ async function pluginLintCheckGenerator(host, options) {
21
20
  }
22
21
  }
23
22
  else {
24
- devkit_1.logger.error(`${logger_1.NX_PREFIX} plugin lint checks can only be added to plugins which use eslint for linting`);
23
+ devkit_1.logger.error(`${internal_2.NX_PREFIX} plugin lint checks can only be added to plugins which use eslint for linting`);
25
24
  }
26
25
  if (!options.skipFormat) {
27
26
  await (0, devkit_1.formatFiles)(host);
@@ -33,7 +32,7 @@ function addMigrationJsonChecks(host, options, packageJson) {
33
32
  return;
34
33
  }
35
34
  const [eslintTarget, eslintTargetConfiguration] = getEsLintOptions(projectConfiguration) ?? [];
36
- const relativeMigrationsJsonPath = (0, package_json_1.readNxMigrateConfig)(packageJson).migrations;
35
+ const relativeMigrationsJsonPath = (0, internal_2.readNxMigrateConfig)(packageJson).migrations;
37
36
  if (!relativeMigrationsJsonPath) {
38
37
  return;
39
38
  }
@@ -129,7 +128,7 @@ function updateProjectEslintConfig(host, options, packageJson) {
129
128
  packageJson.executors,
130
129
  packageJson.schematics,
131
130
  packageJson.builders,
132
- (0, package_json_1.readNxMigrateConfig)(packageJson).migrations,
131
+ (0, internal_2.readNxMigrateConfig)(packageJson).migrations,
133
132
  ].filter((f) => !!f);
134
133
  const parser = (0, internal_1.useFlatConfig)(host)
135
134
  ? { languageOptions: { parser: 'jsonc-eslint-parser' } }
@@ -195,7 +194,7 @@ function setupVsCodeLintingForJsonFiles(host) {
195
194
  existing = (0, devkit_1.readJson)(host, '.vscode/settings.json');
196
195
  }
197
196
  else {
198
- devkit_1.logger.info(`${logger_1.NX_PREFIX} We've updated the vscode settings for this repository to ensure that plugin lint checks show up inside your IDE. This created .vscode/settings.json. To read more about this file, check vscode's documentation. It is frequently not committed, so other developers may need to add similar settings if they'd like to see the lint checks in the IDE rather than only during linting.`);
197
+ devkit_1.logger.info(`${internal_2.NX_PREFIX} We've updated the vscode settings for this repository to ensure that plugin lint checks show up inside your IDE. This created .vscode/settings.json. To read more about this file, check vscode's documentation. It is frequently not committed, so other developers may need to add similar settings if they'd like to see the lint checks in the IDE rather than only during linting.`);
199
198
  }
200
199
  // setup eslint validation for json files
201
200
  const eslintValidate = existing['eslint.validate'] ?? [];
@@ -5,7 +5,6 @@ const internal_1 = require("@nx/devkit/internal");
5
5
  const devkit_1 = require("@nx/devkit");
6
6
  const internal_2 = require("@nx/js/internal");
7
7
  const node_path_1 = require("node:path");
8
- const package_json_1 = require("nx/src/utils/package-json");
9
8
  const paths_1 = require("../../utils/paths");
10
9
  const versions_1 = require("../../utils/versions");
11
10
  const generator_1 = require("../lint-checks/generator");
@@ -38,7 +37,7 @@ function addFiles(host, options) {
38
37
  });
39
38
  }
40
39
  function updateMigrationsJson(host, options) {
41
- const configuredMigrationPath = (0, package_json_1.readNxMigrateConfig)((0, devkit_1.readJson)(host, (0, devkit_1.joinPathFragments)(options.projectRoot, 'package.json'))).migrations;
40
+ const configuredMigrationPath = (0, internal_1.readNxMigrateConfig)((0, devkit_1.readJson)(host, (0, devkit_1.joinPathFragments)(options.projectRoot, 'package.json'))).migrations;
42
41
  const migrationsPath = (0, devkit_1.joinPathFragments)(options.projectRoot, configuredMigrationPath ?? 'migrations.json');
43
42
  const migrations = host.exists(migrationsPath)
44
43
  ? (0, devkit_1.readJson)(host, migrationsPath)
@@ -83,6 +83,11 @@ async function pluginGeneratorInternal(host, schema) {
83
83
  '@nx/devkit': nxVersion,
84
84
  }, {
85
85
  [options.unitTestRunner === 'vitest' ? '@nx/vitest' : '@nx/jest']: nxVersion,
86
+ ...(options.e2eTestRunner === 'vitest'
87
+ ? { '@nx/vitest': nxVersion }
88
+ : options.e2eTestRunner === 'jest'
89
+ ? { '@nx/jest': nxVersion }
90
+ : {}),
86
91
  '@nx/js': nxVersion,
87
92
  '@nx/plugin': nxVersion,
88
93
  }));
@@ -103,6 +108,7 @@ async function pluginGeneratorInternal(host, schema) {
103
108
  linter: options.linter,
104
109
  useProjectJson: options.useProjectJson,
105
110
  addPlugin: options.addPlugin,
111
+ testRunner: options.e2eTestRunner,
106
112
  }));
107
113
  }
108
114
  if (options.linter === 'eslint' && !options.skipLintChecks) {
@@ -1,4 +1,4 @@
1
- import type { Linter, LinterType } from '@nx/eslint';
1
+ import type { LinterType } from '@nx/js';
2
2
 
3
3
  export interface Schema {
4
4
  directory: string;
@@ -7,11 +7,15 @@ export interface Schema {
7
7
  skipTsConfig?: boolean; // default is false
8
8
  skipFormat?: boolean; // default is false
9
9
  skipLintChecks?: boolean; // default is false
10
- e2eTestRunner?: 'jest' | 'none';
10
+ e2eTestRunner?: 'jest' | 'vitest' | 'none';
11
11
  e2eProjectDirectory?: string;
12
12
  tags?: string;
13
13
  unitTestRunner?: 'jest' | 'vitest' | 'none';
14
- linter?: Linter | LinterType;
14
+ linter?: LinterType;
15
+ enableTypedLinting?: boolean;
16
+ /**
17
+ * @deprecated Use `enableTypedLinting` instead. This option will be removed in Nx v24.
18
+ */
15
19
  setParserOptionsProject?: boolean;
16
20
  compiler?: 'swc' | 'tsc';
17
21
  rootProject?: boolean;
@@ -32,9 +32,9 @@
32
32
  "x-priority": "important"
33
33
  },
34
34
  "linter": {
35
- "description": "The tool to use for running lint checks.",
35
+ "description": "The tool to use for running lint checks. Defaults to the linter the workspace already uses.",
36
36
  "type": "string",
37
- "enum": ["none", "eslint"],
37
+ "enum": ["none", "eslint", "oxlint"],
38
38
  "x-priority": "important"
39
39
  },
40
40
  "unitTestRunner": {
@@ -67,7 +67,7 @@
67
67
  },
68
68
  "e2eTestRunner": {
69
69
  "type": "string",
70
- "enum": ["jest", "none"],
70
+ "enum": ["jest", "vitest", "none"],
71
71
  "description": "Test runner to use for end to end (E2E) tests.",
72
72
  "default": "none"
73
73
  },
@@ -75,11 +75,17 @@
75
75
  "type": "string",
76
76
  "description": "A directory where the plugin E2E project is placed."
77
77
  },
78
- "setParserOptionsProject": {
78
+ "enableTypedLinting": {
79
79
  "type": "boolean",
80
- "description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
80
+ "description": "Whether to enable typed linting. For flat configs, this configures the recommended `parserOptions.projectService` and `tsconfigRootDir`. For legacy `.eslintrc` configs, this configures `parserOptions.project`. We do not enable this by default for lint performance reasons.",
81
81
  "default": false
82
82
  },
83
+ "setParserOptionsProject": {
84
+ "type": "boolean",
85
+ "description": "Deprecated alias for `enableTypedLinting`.",
86
+ "default": false,
87
+ "x-deprecated": "Use `enableTypedLinting` instead. This option will be removed in Nx v24."
88
+ },
83
89
  "compiler": {
84
90
  "type": "string",
85
91
  "enum": ["tsc", "swc"],
@@ -1,5 +1,5 @@
1
1
  import { type Tree } from '@nx/devkit';
2
- import type { LinterType } from '@nx/eslint';
2
+ import type { LinterType } from '@nx/js';
3
3
  import type { Schema } from '../schema';
4
4
  export interface NormalizedSchema extends Schema {
5
5
  projectName: string;
@@ -5,6 +5,7 @@ exports.presetGeneratorInternal = presetGeneratorInternal;
5
5
  const devkit_1 = require("@nx/devkit");
6
6
  const create_package_1 = require("../create-package/create-package");
7
7
  const plugin_1 = require("../plugin/plugin");
8
+ const internal_1 = require("@nx/js/internal");
8
9
  async function presetGenerator(tree, rawOptions) {
9
10
  return await presetGeneratorInternal(tree, {
10
11
  addPlugin: false,
@@ -14,10 +15,10 @@ async function presetGenerator(tree, rawOptions) {
14
15
  }
15
16
  async function presetGeneratorInternal(tree, rawOptions) {
16
17
  const tasks = [];
17
- const options = normalizeOptions(rawOptions);
18
+ const options = await normalizeOptions(tree, rawOptions);
18
19
  const pluginTask = await (0, plugin_1.pluginGenerator)(tree, {
19
20
  compiler: 'tsc',
20
- linter: 'eslint',
21
+ linter: options.linter,
21
22
  skipFormat: true,
22
23
  unitTestRunner: 'jest',
23
24
  importPath: options.pluginName,
@@ -42,7 +43,7 @@ async function presetGeneratorInternal(tree, rawOptions) {
42
43
  project: options.pluginName,
43
44
  skipFormat: true,
44
45
  unitTestRunner: 'jest',
45
- linter: 'eslint',
46
+ linter: options.linter,
46
47
  compiler: 'tsc',
47
48
  useProjectJson: options.useProjectJson,
48
49
  addPlugin: options.addPlugin,
@@ -62,7 +63,7 @@ function moveNxPluginToDevDeps(tree) {
62
63
  return json;
63
64
  });
64
65
  }
65
- function normalizeOptions(options) {
66
+ async function normalizeOptions(tree, options) {
66
67
  return {
67
68
  ...options,
68
69
  pluginName: (0, devkit_1.names)(options.pluginName.includes('/')
@@ -71,6 +72,9 @@ function normalizeOptions(options) {
71
72
  createPackageName: options.createPackageName === 'false' // for command line in e2e, it is passed as a string
72
73
  ? undefined
73
74
  : options.createPackageName,
75
+ // Resolved once here rather than left to the two child generators, which
76
+ // each prompt on their own and would ask the same question twice.
77
+ linter: await (0, internal_1.normalizeLinterOption)(tree, options.linter),
74
78
  };
75
79
  }
76
80
  exports.default = presetGenerator;
@@ -1,11 +1,14 @@
1
+ import type { LinterType } from '@nx/js';
2
+
1
3
  export interface PresetGeneratorSchema {
2
4
  pluginName: string;
3
5
  createPackageName?: string;
4
6
  useProjectJson?: boolean;
5
7
  addPlugin?: boolean;
8
+ linter?: LinterType;
6
9
  }
7
10
 
8
- export interface NormalizedPresetGeneratorOptions
9
- extends PresetGeneratorSchema {
11
+ export interface NormalizedPresetGeneratorOptions extends PresetGeneratorSchema {
10
12
  createPackageName: string;
13
+ linter: LinterType;
11
14
  }
@@ -25,6 +25,11 @@
25
25
  "type": "string",
26
26
  "description": "Name of package which creates a workspace"
27
27
  },
28
+ "linter": {
29
+ "description": "The tool to use for running lint checks. Defaults to the linter the workspace already uses.",
30
+ "type": "string",
31
+ "enum": ["none", "eslint", "oxlint"]
32
+ },
28
33
  "useProjectJson": {
29
34
  "type": "boolean",
30
35
  "description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
@@ -6,7 +6,6 @@ exports.runPackageManagerInstall = runPackageManagerInstall;
6
6
  exports.newNxProject = newNxProject;
7
7
  exports.ensureNxProject = ensureNxProject;
8
8
  const devkit_1 = require("@nx/devkit");
9
- const devkit_2 = require("@nx/devkit");
10
9
  const child_process_1 = require("child_process");
11
10
  const node_fs_1 = require("node:fs");
12
11
  const path_1 = require("path");
@@ -22,9 +21,9 @@ function runNxNewCommand(args, silent) {
22
21
  }
23
22
  function patchPackageJsonForPlugin(npmPackageName, distPath) {
24
23
  const path = (0, paths_1.tmpProjPath)('package.json');
25
- const json = (0, devkit_2.readJsonFile)(path);
24
+ const json = (0, devkit_1.readJsonFile)(path);
26
25
  json.devDependencies[npmPackageName] = `file:${devkit_1.workspaceRoot}/${distPath}`;
27
- (0, devkit_2.writeJsonFile)(path, json);
26
+ (0, devkit_1.writeJsonFile)(path, json);
28
27
  }
29
28
  /**
30
29
  * Generate a unique name for running CLI commands
@@ -41,7 +40,7 @@ function uniq(prefix) {
41
40
  */
42
41
  function runPackageManagerInstall(silent = true) {
43
42
  const cwd = (0, paths_1.tmpProjPath)();
44
- const pmc = (0, devkit_2.getPackageManagerCommand)((0, devkit_1.detectPackageManager)(cwd));
43
+ const pmc = (0, devkit_1.getPackageManagerCommand)((0, devkit_1.detectPackageManager)(cwd));
45
44
  const install = (0, child_process_1.execSync)(pmc.install, {
46
45
  cwd,
47
46
  ...(silent ? { stdio: ['ignore', 'ignore', 'ignore'] } : {}),
@@ -1,5 +1,5 @@
1
1
  import type { JsonParseOptions } from '@nx/devkit';
2
- import { directoryExists, fileExists } from 'nx/src/utils/fileutils';
2
+ import { directoryExists, fileExists } from '@nx/devkit/internal';
3
3
  export { directoryExists, fileExists };
4
4
  /**
5
5
  * Copies module folders from the working directory to the e2e directory
@@ -19,9 +19,9 @@ const node_fs_1 = require("node:fs");
19
19
  const path_1 = require("path");
20
20
  const paths_1 = require("./paths");
21
21
  const devkit_1 = require("@nx/devkit");
22
- const fileutils_1 = require("nx/src/utils/fileutils");
23
- Object.defineProperty(exports, "directoryExists", { enumerable: true, get: function () { return fileutils_1.directoryExists; } });
24
- Object.defineProperty(exports, "fileExists", { enumerable: true, get: function () { return fileutils_1.fileExists; } });
22
+ const internal_1 = require("@nx/devkit/internal");
23
+ Object.defineProperty(exports, "directoryExists", { enumerable: true, get: function () { return internal_1.directoryExists; } });
24
+ Object.defineProperty(exports, "fileExists", { enumerable: true, get: function () { return internal_1.fileExists; } });
25
25
  /**
26
26
  * Copies module folders from the working directory to the e2e directory
27
27
  * @param modules a list of module names or scopes to copy
@@ -136,7 +136,7 @@ function getCwd() {
136
136
  * @param path Path to file or directory
137
137
  */
138
138
  function exists(path) {
139
- return (0, fileutils_1.directoryExists)(path) || (0, fileutils_1.fileExists)(path);
139
+ return (0, internal_1.directoryExists)(path) || (0, internal_1.fileExists)(path);
140
140
  }
141
141
  /**
142
142
  * Get the size of a file on disk
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/plugin",
3
- "version": "23.2.0-beta.1",
3
+ "version": "23.2.0-beta.11",
4
4
  "private": false,
5
5
  "description": "This plugin is used to create Nx plugins! It contains generators for generating common plugin features like generators, executors, migrations and more.",
6
6
  "repository": {
@@ -36,13 +36,21 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "tslib": "^2.3.0",
39
- "@nx/devkit": "23.2.0-beta.1",
40
- "@nx/jest": "23.2.0-beta.1",
41
- "@nx/js": "23.2.0-beta.1",
42
- "@nx/eslint": "23.2.0-beta.1"
39
+ "@nx/devkit": "23.2.0-beta.11",
40
+ "@nx/jest": "23.2.0-beta.11",
41
+ "@nx/js": "23.2.0-beta.11",
42
+ "@nx/eslint": "23.2.0-beta.11"
43
43
  },
44
44
  "devDependencies": {
45
- "nx": "23.2.0-beta.1"
45
+ "nx": "23.2.0-beta.11"
46
+ },
47
+ "peerDependencies": {
48
+ "@nx/vitest": "23.2.0-beta.11"
49
+ },
50
+ "peerDependenciesMeta": {
51
+ "@nx/vitest": {
52
+ "optional": true
53
+ }
46
54
  },
47
55
  "publishConfig": {
48
56
  "access": "public"