@nx/devkit 21.0.0-beta.0 → 21.0.0-beta.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/devkit",
3
- "version": "21.0.0-beta.0",
3
+ "version": "21.0.0-beta.10",
4
4
  "private": false,
5
5
  "description": "The Nx Devkit is used to customize Nx for different technologies and use cases. It contains many utility functions for reading and writing files, updating configuration, working with Abstract Syntax Trees(ASTs), and more. Learn more about [extending Nx by leveraging the Nx Devkit](https://nx.dev/extending-nx/intro/getting-started) on our docs.",
6
6
  "repository": {
@@ -17,7 +17,7 @@ function readTargetOptions({ project, target, configuration }, context) {
17
17
  if (!targetConfiguration) {
18
18
  throw new Error(`Unable to find target ${target} for project ${project}`);
19
19
  }
20
- const [nodeModule, executorName] = targetConfiguration.executor.split(':');
20
+ const [nodeModule, executorName] = (0, devkit_internals_1.parseExecutor)(targetConfiguration.executor);
21
21
  const { schema } = (0, devkit_internals_1.getExecutorInformation)(nodeModule, executorName, context.root, context.projectsConfigurations?.projects);
22
22
  const defaultProject = (0, devkit_internals_1.calculateDefaultProjectName)(context.cwd, context.root, { version: 2, projects: context.projectsConfigurations.projects }, context.nxJsonConfiguration);
23
23
  return (0, devkit_internals_1.combineOptionsForExecutor)({}, configuration ?? targetConfiguration.defaultConfiguration ?? '', targetConfiguration, schema, defaultProject, (0, path_1.relative)(context.root, context.cwd));
@@ -18,6 +18,13 @@ async function formatFiles(tree, options = {
18
18
  let prettier;
19
19
  try {
20
20
  prettier = await Promise.resolve().then(() => require('prettier'));
21
+ /**
22
+ * Even after we discovered prettier in node_modules, we need to be sure that the user is intentionally using prettier
23
+ * before proceeding to format with it.
24
+ */
25
+ if (!(0, devkit_internals_1.isUsingPrettierInTree)(tree)) {
26
+ return;
27
+ }
21
28
  }
22
29
  catch { }
23
30
  if (options.sortRootTsconfigPaths) {
@@ -31,8 +31,11 @@ export type ProjectNameAndRootOptions = {
31
31
  /**
32
32
  * Normalized import path for the project.
33
33
  */
34
- importPath?: string;
34
+ importPath: string;
35
35
  };
36
36
  export declare function determineProjectNameAndRootOptions(tree: Tree, options: ProjectGenerationOptions): Promise<ProjectNameAndRootOptions>;
37
37
  export declare function resolveImportPath(tree: Tree, projectName: string, projectRoot: string): string;
38
- export declare function ensureProjectName(tree: Tree, options: Omit<ProjectGenerationOptions, 'projectType'>, projectType: 'application' | 'library'): Promise<void>;
38
+ export declare function ensureRootProjectName(options: {
39
+ directory: string;
40
+ name?: string;
41
+ }, projectType: 'application' | 'library'): Promise<void>;
@@ -2,16 +2,20 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.determineProjectNameAndRootOptions = determineProjectNameAndRootOptions;
4
4
  exports.resolveImportPath = resolveImportPath;
5
- exports.ensureProjectName = ensureProjectName;
5
+ exports.ensureRootProjectName = ensureRootProjectName;
6
6
  const enquirer_1 = require("enquirer");
7
7
  const devkit_exports_1 = require("nx/src/devkit-exports");
8
8
  const path_1 = require("path");
9
9
  async function determineProjectNameAndRootOptions(tree, options) {
10
- validateOptions(options);
10
+ // root projects must provide name option
11
+ if (options.directory === '.' && !options.name) {
12
+ throw new Error(`When generating a root project, you must also specify the name option.`);
13
+ }
11
14
  const directory = (0, devkit_exports_1.normalizePath)(options.directory);
12
15
  const name = options.name ??
13
16
  directory.match(/(@[^@/]+(\/[^@/]+)+)/)?.[1] ??
14
17
  directory.substring(directory.lastIndexOf('/') + 1);
18
+ validateOptions(options.name, name, options.directory);
15
19
  let projectSimpleName;
16
20
  let projectFileName;
17
21
  if (name.startsWith('@')) {
@@ -44,11 +48,10 @@ async function determineProjectNameAndRootOptions(tree, options) {
44
48
  projectRoot = (0, devkit_exports_1.joinPathFragments)(relativeCwd, name);
45
49
  }
46
50
  }
47
- let importPath = undefined;
48
- if (options.projectType === 'library') {
49
- importPath =
50
- options.importPath ?? resolveImportPath(tree, name, projectRoot);
51
+ if (projectRoot.startsWith('..')) {
52
+ throw new Error(`The resolved project root "${projectRoot}" is outside of the workspace root "${devkit_exports_1.workspaceRoot}".`);
51
53
  }
54
+ const importPath = options.importPath ?? resolveImportPath(tree, name, projectRoot);
52
55
  return {
53
56
  projectName: name,
54
57
  names: {
@@ -74,50 +77,36 @@ function resolveImportPath(tree, projectName, projectRoot) {
74
77
  }
75
78
  return importPath;
76
79
  }
77
- async function ensureProjectName(tree, options, projectType) {
78
- if (!options.name) {
79
- if (options.directory === '.' && getRelativeCwd() === '') {
80
- const result = await (0, enquirer_1.prompt)({
81
- type: 'input',
82
- name: 'name',
83
- message: `What do you want to name the ${projectType}?`,
84
- }).then(({ name }) => (options.name = name));
85
- }
86
- const { projectName } = await determineProjectNameAndRootOptions(tree, {
87
- ...options,
88
- projectType,
80
+ async function ensureRootProjectName(options, projectType) {
81
+ if (!options.name && options.directory === '.' && getRelativeCwd() === '') {
82
+ const result = await (0, enquirer_1.prompt)({
83
+ type: 'input',
84
+ name: 'name',
85
+ message: `What do you want to name the ${projectType}?`,
89
86
  });
90
- options.name = projectName;
87
+ options.name = result.name;
91
88
  }
92
89
  }
93
- function validateOptions(options) {
94
- if (options.directory === '.') {
95
- /**
96
- * Root projects must provide name option
97
- */
98
- if (!options.name) {
99
- throw new Error(`Root projects must also specify name option.`);
90
+ function validateOptions(providedName, derivedName, directory) {
91
+ /**
92
+ * The provided name and the derived name from the provided directory must match one of two cases:
93
+ *
94
+ * 1. Valid npm package names (e.g., '@scope/name' or 'name').
95
+ * 2. Names starting with a letter and can contain any character except whitespace and ':'.
96
+ *
97
+ * The second case is to support the legacy behavior (^[a-zA-Z].*$) with the difference
98
+ * that it doesn't allow the ":" character. It was wrong to allow it because it would
99
+ * conflict with the notation for tasks.
100
+ */
101
+ const pattern = '(?:^@[a-zA-Z0-9-*~][a-zA-Z0-9-*._~]*\\/[a-zA-Z0-9-~][a-zA-Z0-9-._~]*|^[a-zA-Z][^:]*)$';
102
+ const validationRegex = new RegExp(pattern);
103
+ if (providedName) {
104
+ if (!validationRegex.test(providedName)) {
105
+ throw new Error(`The name should match the pattern "${pattern}". The provided value "${providedName}" does not match.`);
100
106
  }
101
107
  }
102
- else {
103
- /**
104
- * Both directory and name (if present) must match one of two cases:
105
- *
106
- * 1. Valid npm package names (e.g., '@scope/name' or 'name').
107
- * 2. Names starting with a letter and can contain any character except whitespace and ':'.
108
- *
109
- * The second case is to support the legacy behavior (^[a-zA-Z].*$) with the difference
110
- * that it doesn't allow the ":" character. It was wrong to allow it because it would
111
- * conflict with the notation for tasks.
112
- */
113
- const pattern = '(?:^@[a-zA-Z0-9-*~][a-zA-Z0-9-*._~]*\\/[a-zA-Z0-9-~][a-zA-Z0-9-._~]*|^[a-zA-Z][^:]*)$';
114
- const validationRegex = new RegExp(pattern);
115
- if (options.name && !validationRegex.test(options.name)) {
116
- throw new Error(`The name should match the pattern "${pattern}". The provided value "${options.name}" does not match.`);
117
- }
118
- if (!validationRegex.test(options.directory)) {
119
- throw new Error(`The directory should match the pattern "${pattern}". The provided value "${options.directory}" does not match.`);
120
- }
108
+ else if (!validationRegex.test(derivedName)) {
109
+ throw new Error(`The derived name from the provided directory should match the pattern "${pattern}". The derived name "${derivedName}" from the provided value "${directory}" does not match.`);
121
110
  }
122
111
  }
123
112
  function getImportPath(npmScope, name) {
@@ -46,7 +46,7 @@ async function addE2eCiTargetDefaults(tree, e2ePlugin, buildTarget, pathToE2ECon
46
46
  const ciTargetName = typeof foundPluginForApplication === 'string'
47
47
  ? 'e2e-ci'
48
48
  : foundPluginForApplication.options?.ciTargetName ?? 'e2e-ci';
49
- const ciTargetNameGlob = `${ciTargetName}--**/*`;
49
+ const ciTargetNameGlob = `${ciTargetName}--**/**`;
50
50
  nxJson.targetDefaults ??= {};
51
51
  const e2eCiTargetDefaults = nxJson.targetDefaults[ciTargetNameGlob];
52
52
  if (!e2eCiTargetDefaults) {
@@ -26,9 +26,9 @@ function updateTsConfigsToJs(tree, options) {
26
26
  }
27
27
  if (updateConfigPath) {
28
28
  (0, devkit_exports_1.updateJson)(tree, updateConfigPath, (json) => {
29
- json.include = uniq([...json.include, 'src/**/*.js']);
29
+ json.include = uniq([...(json.include ?? []), 'src/**/*.js']);
30
30
  json.exclude = uniq([
31
- ...json.exclude,
31
+ ...(json.exclude ?? []),
32
32
  'src/**/*.spec.js',
33
33
  'src/**/*.test.js',
34
34
  ]);
@@ -1,2 +1,3 @@
1
1
  import { CreateNodesContext, CreateNodesContextV2 } from 'nx/src/devkit-exports';
2
2
  export declare function calculateHashForCreateNodes(projectRoot: string, options: object, context: CreateNodesContext | CreateNodesContextV2, additionalGlobs?: string[]): Promise<string>;
3
+ export declare function calculateHashesForCreateNodes(projectRoots: string[], options: object, context: CreateNodesContext | CreateNodesContextV2, additionalGlobs?: string[][]): Promise<string[]>;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.calculateHashForCreateNodes = calculateHashForCreateNodes;
4
+ exports.calculateHashesForCreateNodes = calculateHashesForCreateNodes;
4
5
  const path_1 = require("path");
5
6
  const devkit_exports_1 = require("nx/src/devkit-exports");
6
7
  const devkit_internals_1 = require("nx/src/devkit-internals");
@@ -13,3 +14,15 @@ async function calculateHashForCreateNodes(projectRoot, options, context, additi
13
14
  (0, devkit_internals_1.hashObject)(options),
14
15
  ]);
15
16
  }
17
+ async function calculateHashesForCreateNodes(projectRoots, options, context, additionalGlobs = []) {
18
+ if (additionalGlobs.length &&
19
+ additionalGlobs.length !== projectRoots.length) {
20
+ throw new Error('If additionalGlobs is provided, it must be the same length as projectRoots');
21
+ }
22
+ return (0, devkit_internals_1.hashMultiGlobWithWorkspaceContext)(context.workspaceRoot, projectRoots.map((projectRoot, idx) => [
23
+ (0, path_1.join)(projectRoot, '**/*'),
24
+ ...(additionalGlobs.length ? additionalGlobs[idx] : []),
25
+ ])).then((hashes) => {
26
+ return hashes.map((hash) => (0, devkit_exports_1.hashArray)([hash, (0, devkit_internals_1.hashObject)(options)]));
27
+ });
28
+ }
@@ -176,14 +176,18 @@ function removeDependenciesFromPackageJson(tree, dependencies, devDependencies,
176
176
  const currentPackageJson = (0, devkit_exports_1.readJson)(tree, packageJsonPath);
177
177
  if (requiresRemovingOfPackages(currentPackageJson, dependencies, devDependencies)) {
178
178
  (0, devkit_exports_1.updateJson)(tree, packageJsonPath, (json) => {
179
- for (const dep of dependencies) {
180
- delete json.dependencies[dep];
179
+ if (json.dependencies) {
180
+ for (const dep of dependencies) {
181
+ delete json.dependencies[dep];
182
+ }
183
+ json.dependencies = sortObjectByKeys(json.dependencies);
181
184
  }
182
- for (const devDep of devDependencies) {
183
- delete json.devDependencies[devDep];
185
+ if (json.devDependencies) {
186
+ for (const devDep of devDependencies) {
187
+ delete json.devDependencies[devDep];
188
+ }
189
+ json.devDependencies = sortObjectByKeys(json.devDependencies);
184
190
  }
185
- json.dependencies = sortObjectByKeys(json.dependencies);
186
- json.devDependencies = sortObjectByKeys(json.devDependencies);
187
191
  return json;
188
192
  });
189
193
  }
@@ -102,6 +102,7 @@ function replaceMentions(tree, oldPackageName, newPackageName) {
102
102
  'package-lock.json',
103
103
  'pnpm-lock.yaml',
104
104
  'bun.lockb',
105
+ 'bun.lock',
105
106
  'CHANGELOG.md',
106
107
  ];
107
108
  if (ignoredFiles.includes((0, path_1.basename)(path))) {