nx 23.0.0-beta.21 → 23.0.0-beta.23

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 (82) hide show
  1. package/dist/plugins/package-json.js +1 -1
  2. package/dist/src/adapter/angular-json.d.ts +2 -2
  3. package/dist/src/adapter/angular-json.js +0 -1
  4. package/dist/src/adapter/compat.d.ts +1 -1
  5. package/dist/src/adapter/compat.js +1 -0
  6. package/dist/src/ai/set-up-ai-agents/set-up-ai-agents.js +2 -1
  7. package/dist/src/command-line/configure-ai-agents/configure-ai-agents.js +1 -1
  8. package/dist/src/command-line/examples.js +4 -4
  9. package/dist/src/command-line/graph/graph.js +1 -1
  10. package/dist/src/command-line/init/init-v2.js +1 -1
  11. package/dist/src/command-line/migrate/agentic/prompts/generic-validation.d.ts +5 -0
  12. package/dist/src/command-line/migrate/agentic/prompts/generic-validation.js +1 -0
  13. package/dist/src/command-line/migrate/agentic/prompts/hybrid-prompt-migration.d.ts +5 -0
  14. package/dist/src/command-line/migrate/agentic/prompts/hybrid-prompt-migration.js +1 -0
  15. package/dist/src/command-line/migrate/agentic/prompts/prompt-migration.d.ts +5 -0
  16. package/dist/src/command-line/migrate/agentic/prompts/prompt-migration.js +1 -0
  17. package/dist/src/command-line/migrate/agentic/prompts/shared-rendering.d.ts +1 -0
  18. package/dist/src/command-line/migrate/agentic/prompts/shared-rendering.js +15 -0
  19. package/dist/src/command-line/migrate/agentic/run-step.d.ts +7 -0
  20. package/dist/src/command-line/migrate/agentic/run-step.js +3 -1
  21. package/dist/src/command-line/migrate/agentic/select.js +120 -32
  22. package/dist/src/command-line/migrate/command-object.d.ts +42 -0
  23. package/dist/src/command-line/migrate/command-object.js +38 -8
  24. package/dist/src/command-line/migrate/migrate-config.d.ts +27 -0
  25. package/dist/src/command-line/migrate/migrate-config.js +103 -0
  26. package/dist/src/command-line/migrate/migrate.d.ts +39 -2
  27. package/dist/src/command-line/migrate/migrate.js +203 -41
  28. package/dist/src/command-line/migrate/multi-major.js +5 -2
  29. package/dist/src/command-line/release/changelog/version-plan-filtering.d.ts +3 -1
  30. package/dist/src/command-line/release/changelog/version-plan-filtering.js +7 -3
  31. package/dist/src/command-line/release/changelog.d.ts +7 -0
  32. package/dist/src/command-line/release/changelog.js +22 -9
  33. package/dist/src/command-line/release/release.js +65 -55
  34. package/dist/src/command-line/release/utils/git.d.ts +6 -0
  35. package/dist/src/command-line/release/utils/git.js +33 -0
  36. package/dist/src/command-line/release/version/derive-specifier-from-conventional-commits.js +3 -2
  37. package/dist/src/command-line/release/version.d.ts +3 -0
  38. package/dist/src/command-line/release/version.js +13 -3
  39. package/dist/src/config/misc-interfaces.d.ts +8 -0
  40. package/dist/src/config/nx-json.d.ts +49 -0
  41. package/dist/src/core/graph/main.js +1 -1
  42. package/dist/src/daemon/server/latest-nx.js +3 -1
  43. package/dist/src/devkit-exports.d.ts +11 -11
  44. package/dist/src/devkit-exports.js +7 -4
  45. package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
  46. package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
  47. package/dist/src/plugins/js/index.d.ts +2 -2
  48. package/dist/src/plugins/js/index.js +4 -4
  49. package/dist/src/plugins/js/lock-file/lock-file.d.ts +7 -2
  50. package/dist/src/plugins/js/lock-file/lock-file.js +35 -25
  51. package/dist/src/plugins/js/project-graph/affected/lock-file-changes.d.ts +2 -4
  52. package/dist/src/plugins/js/project-graph/affected/lock-file-changes.js +121 -43
  53. package/dist/src/plugins/js/utils/register.d.ts +52 -0
  54. package/dist/src/plugins/js/utils/register.js +195 -0
  55. package/dist/src/plugins/package-json/create-nodes.d.ts +2 -2
  56. package/dist/src/plugins/package-json/create-nodes.js +2 -2
  57. package/dist/src/plugins/project-json/build-nodes/project-json.d.ts +2 -2
  58. package/dist/src/plugins/project-json/build-nodes/project-json.js +1 -1
  59. package/dist/src/project-graph/error-types.d.ts +6 -6
  60. package/dist/src/project-graph/error-types.js +1 -1
  61. package/dist/src/project-graph/file-utils.d.ts +7 -0
  62. package/dist/src/project-graph/file-utils.js +78 -10
  63. package/dist/src/project-graph/plugins/isolation/isolated-plugin.d.ts +2 -2
  64. package/dist/src/project-graph/plugins/isolation/messaging.d.ts +2 -2
  65. package/dist/src/project-graph/plugins/loaded-nx-plugin.d.ts +3 -3
  66. package/dist/src/project-graph/plugins/loaded-nx-plugin.js +6 -4
  67. package/dist/src/project-graph/plugins/public-api.d.ts +31 -12
  68. package/dist/src/project-graph/plugins/transpiler.js +11 -0
  69. package/dist/src/project-graph/plugins/utils.d.ts +3 -3
  70. package/dist/src/project-graph/utils/project-configuration-utils.d.ts +1 -1
  71. package/dist/src/project-graph/utils/project-configuration-utils.js +6 -17
  72. package/dist/src/tasks-runner/init-tasks-runner.d.ts +2 -2
  73. package/dist/src/tasks-runner/init-tasks-runner.js +6 -6
  74. package/dist/src/tasks-runner/task-orchestrator.d.ts +2 -2
  75. package/dist/src/tasks-runner/task-orchestrator.js +6 -6
  76. package/dist/src/utils/package-json.d.ts +3 -3
  77. package/dist/src/utils/package-json.js +9 -11
  78. package/dist/src/utils/package-manager.d.ts +13 -0
  79. package/dist/src/utils/package-manager.js +27 -0
  80. package/migrations.json +18 -9
  81. package/package.json +11 -11
  82. package/schemas/nx-schema.json +41 -0
@@ -1,6 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NODENEXT_ESM_RESOLVER_SOURCE = void 0;
3
4
  exports.forceRegisterEsmLoader = forceRegisterEsmLoader;
5
+ exports.ensureNodeNextEsmResolverRegistered = ensureNodeNextEsmResolverRegistered;
6
+ exports.ensureCjsResolverPatched = ensureCjsResolverPatched;
4
7
  exports.isNativeStripPreferred = isNativeStripPreferred;
5
8
  exports.registerTsProject = registerTsProject;
6
9
  exports.getSwcTranspiler = getSwcTranspiler;
@@ -85,6 +88,195 @@ function ensureEsmLoaderRegistered(opts) {
85
88
  module.register(url.pathToFileURL(loaderPath));
86
89
  isTsEsmLoaderRegistered = true;
87
90
  }
91
+ /**
92
+ * Source of a minimal ESM resolution hook that rewrites TypeScript NodeNext
93
+ * `.js`/`.mjs`/`.cjs` relative specifiers to their `.ts`/`.mts`/`.cts` sources.
94
+ * Inlined as a string so it can be registered as a self-contained `data:`
95
+ * module - it relies only on Node's default resolver (no ts-node/swc-node) and
96
+ * defers loading to Node's native TypeScript stripping. The ESM counterpart to
97
+ * the CJS `ensureCjsResolverPatched`.
98
+ *
99
+ * Only rewrites when the default resolution fails with ERR_MODULE_NOT_FOUND,
100
+ * the importing module is itself TypeScript, and the specifier is relative, so
101
+ * it never hijacks resolution that would otherwise succeed.
102
+ *
103
+ * Exported so the hook can be exercised directly in unit tests.
104
+ */
105
+ exports.NODENEXT_ESM_RESOLVER_SOURCE = `
106
+ const EXT_FALLBACK = { '.js': ['.ts', '.tsx'], '.mjs': ['.mts'], '.cjs': ['.cts'] };
107
+ const TS_PARENT_RE = /\\.(?:ts|tsx|mts|cts)(?:$|\\?)/;
108
+ export async function resolve(specifier, context, nextResolve) {
109
+ try {
110
+ return await nextResolve(specifier, context);
111
+ } catch (err) {
112
+ if (err?.code !== 'ERR_MODULE_NOT_FOUND') throw err;
113
+ const parent = context.parentURL;
114
+ if (!parent || !TS_PARENT_RE.test(parent)) throw err;
115
+ if (!(specifier.startsWith('./') || specifier.startsWith('../') || specifier.startsWith('file:'))) throw err;
116
+ const m = specifier.match(/(\\.(?:js|mjs|cjs))($|\\?)/);
117
+ if (!m) throw err;
118
+ const fallbacks = EXT_FALLBACK[m[1]];
119
+ if (!fallbacks) throw err;
120
+ const base = specifier.slice(0, m.index);
121
+ const suffix = specifier.slice(m.index + m[1].length);
122
+ for (const ext of fallbacks) {
123
+ try { return await nextResolve(base + ext + suffix, context); } catch {}
124
+ }
125
+ throw err;
126
+ }
127
+ }
128
+ `;
129
+ let nodeNextEsmResolverRegistered = false;
130
+ /**
131
+ * Register a self-contained ESM resolution hook (via `Module.register`) that
132
+ * rewrites TypeScript NodeNext-style `.js`/`.mjs`/`.cjs` relative specifiers to
133
+ * their `.ts`/`.mts`/`.cts` sources. This is the ESM counterpart to
134
+ * `ensureCjsResolverPatched`: Node's native type stripping loads the `.ts`
135
+ * file, but neither native strip nor Node's ESM resolver rewrites the
136
+ * extension, so `import './foo.js'` from a `.ts` source where only `foo.ts`
137
+ * exists fails with ERR_MODULE_NOT_FOUND without it.
138
+ *
139
+ * The hook is inlined as a `data:` module (see `NODENEXT_ESM_RESOLVER_SOURCE`)
140
+ * and relies only on Node's default resolver, so it needs no ts-node/swc-node.
141
+ *
142
+ * Idempotent and best-effort: a no-op when `Module.register` is unavailable,
143
+ * when a TypeScript transpiler is already preloaded (see
144
+ * `isTsTranspilerPreloaded`), or if registration fails.
145
+ */
146
+ function ensureNodeNextEsmResolverRegistered() {
147
+ if (nodeNextEsmResolverRegistered)
148
+ return;
149
+ nodeNextEsmResolverRegistered = true;
150
+ const module = require('node:module');
151
+ if (typeof module.register !== 'function')
152
+ return;
153
+ // Skip when a transpiler was preloaded via `--require`/`--import` (e.g.
154
+ // `--require ts-node/register`, which Nx uses only when it runs from `.ts`
155
+ // source). `module.register()` spins up a loader-hook worker thread on which
156
+ // Node re-runs those preloads, resolved relative to the *current* working
157
+ // directory - and Nx plugin workers `chdir()` into the analyzed workspace
158
+ // first. If that workspace can't resolve the preloaded module, the loader
159
+ // worker throws and can leave module resolution in a bad state, so we must
160
+ // avoid the call entirely; catching it is not a clean recovery.
161
+ //
162
+ // Consequence: in that from-`.ts`-source invocation a `type: module` plugin
163
+ // using NodeNext `.js` specifiers won't get this resolver (a preloaded
164
+ // `ts-node` does NOT rewrite `.js` -> `.ts` for ESM). Published Nx is
165
+ // unaffected - its workers run compiled `.js` with no preload.
166
+ if (isTsTranspilerPreloaded())
167
+ return;
168
+ try {
169
+ module.register('data:text/javascript,' + encodeURIComponent(exports.NODENEXT_ESM_RESOLVER_SOURCE));
170
+ }
171
+ catch {
172
+ // Best-effort: leave Node's native handling in place for the
173
+ // dynamic-import path rather than failing the load.
174
+ }
175
+ }
176
+ /**
177
+ * Whether this process was started with a TypeScript transpiler preloaded via
178
+ * a `--require`/`--import`/`--loader` flag (e.g. `--require ts-node/register`),
179
+ * either directly in `process.execArgv` or through `NODE_OPTIONS`. Used to skip
180
+ * a redundant ESM loader registration that would otherwise crash a loader-hook
181
+ * worker re-running the preload from a `chdir()`'d cwd - see
182
+ * `ensureNodeNextEsmResolverRegistered`.
183
+ */
184
+ function isTsTranspilerPreloaded() {
185
+ const PRELOAD_FLAGS = [
186
+ '-r',
187
+ '--require',
188
+ '--import',
189
+ '--loader',
190
+ '--experimental-loader',
191
+ ];
192
+ const TRANSPILER_RE = /(?:ts-node|@?swc-node)/;
193
+ // Flags passed directly (e.g. spawn(..., ['--require', 'ts-node/register'])).
194
+ const execArgv = process.execArgv ?? [];
195
+ for (let i = 0; i < execArgv.length; i++) {
196
+ const arg = execArgv[i];
197
+ const eqIdx = arg.indexOf('=');
198
+ if (eqIdx !== -1) {
199
+ if (PRELOAD_FLAGS.includes(arg.slice(0, eqIdx)) &&
200
+ TRANSPILER_RE.test(arg.slice(eqIdx + 1))) {
201
+ return true;
202
+ }
203
+ }
204
+ else if (PRELOAD_FLAGS.includes(arg) &&
205
+ TRANSPILER_RE.test(execArgv[i + 1] ?? '')) {
206
+ return true;
207
+ }
208
+ }
209
+ // Preloads passed via NODE_OPTIONS don't surface in execArgv.
210
+ const nodeOptions = process.env.NODE_OPTIONS;
211
+ if (nodeOptions &&
212
+ TRANSPILER_RE.test(nodeOptions) &&
213
+ PRELOAD_FLAGS.some((flag) => nodeOptions.includes(flag))) {
214
+ return true;
215
+ }
216
+ return false;
217
+ }
218
+ let cjsResolverPatched = false;
219
+ /**
220
+ * Patches Node's CJS resolver to fall back from `.js`/`.mjs`/`.cjs` to the
221
+ * corresponding TypeScript source extension (`.ts`/`.tsx`, `.mts`, `.cts`)
222
+ * when the requesting file is itself a `.ts`/`.tsx`/`.mts`/`.cts` source.
223
+ *
224
+ * Required for TypeScript NodeNext-style relative imports: `import './foo.js'`
225
+ * inside a `.ts` file resolves to `./foo.ts` at compile time, but the `.js`
226
+ * specifier survives transpilation to CJS. Node's native CJS resolver doesn't
227
+ * rewrite extensions and there is no officially-supported Node API for this —
228
+ * Node's native strip-types deliberately doesn't either — so a resolver patch
229
+ * is the prevailing solution in the ecosystem (used by `tsx` and ts-node's
230
+ * `experimentalResolver`).
231
+ *
232
+ * Patches `Module._resolveFilename` (not `_findPath`, matching tsx's narrower
233
+ * surface). Gates on the requesting file being TS so vanilla `.js` code
234
+ * requesting missing `.js` files keeps failing — no silent hijack. Only fires
235
+ * the fallback on `MODULE_NOT_FOUND` so existing `.js` resolution is
236
+ * unaffected when both files exist. Idempotent on repeat calls.
237
+ */
238
+ function ensureCjsResolverPatched() {
239
+ if (cjsResolverPatched)
240
+ return;
241
+ cjsResolverPatched = true;
242
+ const Module = require('node:module');
243
+ const original = Module._resolveFilename;
244
+ if (typeof original !== 'function')
245
+ return;
246
+ const TS_PARENT_RE = /\.(?:ts|tsx|mts|cts)$/;
247
+ const EXT_FALLBACK = {
248
+ '.js': ['.ts', '.tsx'],
249
+ '.mjs': ['.mts'],
250
+ '.cjs': ['.cts'],
251
+ };
252
+ Module._resolveFilename = function (request, parent, ...rest) {
253
+ try {
254
+ return original.call(this, request, parent, ...rest);
255
+ }
256
+ catch (err) {
257
+ if (err?.code !== 'MODULE_NOT_FOUND')
258
+ throw err;
259
+ if (!parent?.filename || !TS_PARENT_RE.test(parent.filename))
260
+ throw err;
261
+ const match = request.match(/(\.(?:js|mjs|cjs))$/);
262
+ if (!match)
263
+ throw err;
264
+ const fallbacks = EXT_FALLBACK[match[1]];
265
+ if (!fallbacks)
266
+ throw err;
267
+ const base = request.slice(0, -match[1].length);
268
+ for (const ext of fallbacks) {
269
+ try {
270
+ return original.call(this, base + ext, parent, ...rest);
271
+ }
272
+ catch {
273
+ // try the next fallback
274
+ }
275
+ }
276
+ throw err;
277
+ }
278
+ };
279
+ }
88
280
  function tryResolveLoader(specifier) {
89
281
  try {
90
282
  return require.resolve(specifier);
@@ -194,6 +386,9 @@ function registerTsProject(tsConfigPath) {
194
386
  // files goes through a transpiler. No-op if no ESM loader package is
195
387
  // installed.
196
388
  ensureEsmLoaderRegistered({ required: false });
389
+ // CJS-side fallback so NodeNext `.js` specifiers in `.ts` sources resolve
390
+ // to the matching `.ts` file when require()'d.
391
+ ensureCjsResolverPatched();
197
392
  return () => {
198
393
  for (const fn of cleanupFunctions) {
199
394
  fn();
@@ -2,9 +2,9 @@ import { NxJsonConfiguration } from '../../config/nx-json';
2
2
  import type { ProjectConfiguration } from '../../config/workspace-json-project-json';
3
3
  import { PackageJson } from '../../utils/package-json';
4
4
  import { PackageManagerCommands } from '../../utils/package-manager';
5
- import { CreateNodesV2 } from '../../project-graph/plugins';
5
+ import { CreateNodes } from '../../project-graph/plugins';
6
6
  import { PackageJsonConfigurationCache } from '../../../plugins/package-json';
7
- export declare const createNodesV2: CreateNodesV2;
7
+ export declare const createNodes: CreateNodes;
8
8
  export declare function buildPackageJsonPatterns(workspaceRoot: string, readJson: (path: string) => any): PackageJsonPatterns;
9
9
  type PackageJsonPatterns = {
10
10
  positive: string[];
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createNodesV2 = void 0;
3
+ exports.createNodes = void 0;
4
4
  exports.buildPackageJsonPatterns = buildPackageJsonPatterns;
5
5
  exports.buildPackageJsonWorkspacesMatcher = buildPackageJsonWorkspacesMatcher;
6
6
  exports.createNodeFromPackageJson = createNodeFromPackageJson;
@@ -24,7 +24,7 @@ const path_2 = require("path");
24
24
  const file_hasher_1 = require("../../hasher/file-hasher");
25
25
  const package_json_2 = require("../../../plugins/package-json");
26
26
  const globPatterns = (0, globs_1.combineGlobPatterns)('package.json', '**/package.json', 'project.json', '**/project.json');
27
- exports.createNodesV2 = [
27
+ exports.createNodes = [
28
28
  globPatterns,
29
29
  (configFiles, _, context) => {
30
30
  const { packageJsons, projectJsonRoots } = splitConfigFiles(configFiles);
@@ -1,5 +1,5 @@
1
1
  import { ProjectConfiguration } from '../../../config/workspace-json-project-json';
2
- import { NxPluginV2 } from '../../../project-graph/plugins';
3
- export declare const ProjectJsonProjectsPlugin: NxPluginV2;
2
+ import { NxPlugin } from '../../../project-graph/plugins';
3
+ export declare const ProjectJsonProjectsPlugin: NxPlugin;
4
4
  export default ProjectJsonProjectsPlugin;
5
5
  export declare function buildProjectFromProjectJson(json: Partial<ProjectConfiguration>, path: string): ProjectConfiguration;
@@ -7,7 +7,7 @@ const fileutils_1 = require("../../../utils/fileutils");
7
7
  const plugins_1 = require("../../../project-graph/plugins");
8
8
  exports.ProjectJsonProjectsPlugin = {
9
9
  name: 'nx/core/project-json',
10
- createNodesV2: [
10
+ createNodes: [
11
11
  '{project.json,**/project.json}',
12
12
  (configFiles, _, context) => {
13
13
  return (0, plugins_1.createNodesFromFiles)((file) => {
@@ -1,8 +1,8 @@
1
+ import { ProjectGraph } from '../config/project-graph';
2
+ import { ProjectConfiguration } from '../config/workspace-json-project-json';
3
+ import { CreateNodesFunction } from './plugins/public-api';
1
4
  import { ConfigurationResult } from './utils/project-configuration-utils';
2
5
  import type { ConfigurationSourceMaps } from './utils/project-configuration/source-maps';
3
- import { ProjectConfiguration } from '../config/workspace-json-project-json';
4
- import { ProjectGraph } from '../config/project-graph';
5
- import { CreateNodesFunctionV2 } from './plugins/public-api';
6
6
  export type ProjectGraphErrorTypes = AggregateCreateNodesError | MergeNodesError | CreateMetadataError | ProjectsWithNoNameError | MultipleProjectsWithSameNameError | ProcessDependenciesError | WorkspaceValidityError;
7
7
  export declare class StaleProjectGraphCacheError extends Error {
8
8
  constructor();
@@ -18,7 +18,7 @@ export declare class ProjectGraphError extends Error {
18
18
  */
19
19
  static fromDaemonProjectGraphError(e: DaemonProjectGraphError): ProjectGraphError;
20
20
  /**
21
- * This gets the partial project graph despite the errors which occured.
21
+ * This gets the partial project graph despite the errors which occurred.
22
22
  * This partial project graph may be missing nodes, properties of nodes, or dependencies.
23
23
  * This is useful mostly for visualization/debugging. It should not be used for running tasks.
24
24
  */
@@ -61,7 +61,7 @@ export declare function isProjectConfigurationsError(e: unknown): e is ProjectCo
61
61
  */
62
62
  export declare class AggregateCreateNodesError extends Error {
63
63
  readonly errors: Array<[file: string | null, error: Error]>;
64
- readonly partialResults: Awaited<ReturnType<CreateNodesFunctionV2>>;
64
+ readonly partialResults: Awaited<ReturnType<CreateNodesFunction>>;
65
65
  pluginIndex: number | undefined;
66
66
  /**
67
67
  * Throwing this error from a `createNodesV2` function will allow Nx to continue processing and recieve partial results from your plugin.
@@ -88,7 +88,7 @@ export declare class AggregateCreateNodesError extends Error {
88
88
  * @param errors An array of tuples that represent errors encountered when processing a given file. An example entry might look like ['path/to/project.json', [Error: 'Invalid JSON. Unexpected token 'a' in JSON at position 0]]
89
89
  * @param partialResults The partial results of the `createNodesV2` function. This should be the results for each file that didn't encounter an issue.
90
90
  */
91
- constructor(errors: Array<[file: string | null, error: Error]>, partialResults: Awaited<ReturnType<CreateNodesFunctionV2>>);
91
+ constructor(errors: Array<[file: string | null, error: Error]>, partialResults: Awaited<ReturnType<CreateNodesFunction>>);
92
92
  }
93
93
  export declare function formatAggregateCreateNodesError(error: AggregateCreateNodesError, pluginName: string): void;
94
94
  export declare class MergeNodesError extends Error {
@@ -75,7 +75,7 @@ class ProjectGraphError extends Error {
75
75
  return new ProjectGraphError(e.errors, e.projectGraph, e.sourceMaps);
76
76
  }
77
77
  /**
78
- * This gets the partial project graph despite the errors which occured.
78
+ * This gets the partial project graph despite the errors which occurred.
79
79
  * This partial project graph may be missing nodes, properties of nodes, or dependencies.
80
80
  * This is useful mostly for visualization/debugging. It should not be used for running tasks.
81
81
  */
@@ -13,8 +13,15 @@ export declare class WholeFileChange implements Change {
13
13
  export declare class DeletedFileChange implements Change {
14
14
  type: string;
15
15
  }
16
+ export declare class LockFileChange implements Change {
17
+ baseContent: string;
18
+ headContent: string;
19
+ type: string;
20
+ constructor(baseContent: string, headContent: string);
21
+ }
16
22
  export declare function isWholeFileChange(change: Change): change is WholeFileChange;
17
23
  export declare function isDeletedFileChange(change: Change): change is DeletedFileChange;
24
+ export declare function isLockFileChange(change: Change): change is LockFileChange;
18
25
  export declare function calculateFileChanges(files: string[], nxArgs?: NxArgs, readFileAtRevision?: {
19
26
  (f: string, r: string | void): string;
20
27
  }, ignore?: ReturnType<typeof ignore>): FileChange[];
@@ -1,13 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TEN_MEGABYTES = exports.DeletedFileChange = exports.WholeFileChange = void 0;
3
+ exports.TEN_MEGABYTES = exports.LockFileChange = exports.DeletedFileChange = exports.WholeFileChange = void 0;
4
4
  exports.isWholeFileChange = isWholeFileChange;
5
5
  exports.isDeletedFileChange = isDeletedFileChange;
6
+ exports.isLockFileChange = isLockFileChange;
6
7
  exports.calculateFileChanges = calculateFileChanges;
7
8
  exports.defaultFileRead = defaultFileRead;
8
9
  exports.readPackageJson = readPackageJson;
9
10
  const child_process_1 = require("child_process");
10
11
  const fs_1 = require("fs");
12
+ const os_1 = require("os");
11
13
  const path_1 = require("path");
12
14
  const fileutils_1 = require("../utils/fileutils");
13
15
  const ignore_1 = require("../utils/ignore");
@@ -25,16 +27,36 @@ class DeletedFileChange {
25
27
  }
26
28
  }
27
29
  exports.DeletedFileChange = DeletedFileChange;
30
+ class LockFileChange {
31
+ constructor(baseContent, headContent) {
32
+ this.baseContent = baseContent;
33
+ this.headContent = headContent;
34
+ this.type = 'LockFileChange';
35
+ }
36
+ }
37
+ exports.LockFileChange = LockFileChange;
28
38
  function isWholeFileChange(change) {
29
39
  return change.type === 'WholeFileChange';
30
40
  }
31
41
  function isDeletedFileChange(change) {
32
42
  return change.type === 'WholeFileDeleted';
33
43
  }
44
+ function isLockFileChange(change) {
45
+ return change.type === 'LockFileChange';
46
+ }
47
+ const TEXT_LOCK_FILES = new Set([
48
+ 'yarn.lock',
49
+ 'package-lock.json',
50
+ 'pnpm-lock.yaml',
51
+ 'pnpm-lock.yml',
52
+ 'bun.lock',
53
+ ]);
54
+ const BINARY_LOCK_FILES = new Set(['bun.lockb']);
34
55
  function calculateFileChanges(files, nxArgs, readFileAtRevision = defaultReadFileAtRevision, ignore = (0, ignore_1.getIgnoreObject)()) {
35
56
  files = files.filter((f) => !ignore.ignores(f));
36
57
  return files.map((f) => {
37
58
  const ext = (0, path_1.extname)(f);
59
+ const basename = f.split('/').pop() ?? f;
38
60
  return {
39
61
  file: f,
40
62
  getChanges: () => {
@@ -47,6 +69,16 @@ function calculateFileChanges(files, nxArgs, readFileAtRevision = defaultReadFil
47
69
  if (nxArgs.files && nxArgs.files.includes(f)) {
48
70
  return [new WholeFileChange()];
49
71
  }
72
+ if (TEXT_LOCK_FILES.has(basename) || BINARY_LOCK_FILES.has(basename)) {
73
+ try {
74
+ const atBase = readLockFileAtRevision(f, basename, nxArgs.base, readFileAtRevision);
75
+ const atHead = readLockFileAtRevision(f, basename, nxArgs.head, readFileAtRevision);
76
+ return [new LockFileChange(atBase, atHead)];
77
+ }
78
+ catch {
79
+ return [new WholeFileChange()];
80
+ }
81
+ }
50
82
  switch (ext) {
51
83
  case '.json':
52
84
  try {
@@ -75,18 +107,17 @@ function calculateFileChanges(files, nxArgs, readFileAtRevision = defaultReadFil
75
107
  };
76
108
  });
77
109
  }
110
+ function readLockFileAtRevision(file, lockFileName, revision, readFileAtRevision) {
111
+ if (lockFileName === 'bun.lockb' &&
112
+ readFileAtRevision === defaultReadFileAtRevision) {
113
+ return defaultReadBunLockFileAtRevision(file, revision);
114
+ }
115
+ return readFileAtRevision(file, revision);
116
+ }
78
117
  exports.TEN_MEGABYTES = 1024 * 10000;
79
118
  function defaultReadFileAtRevision(file, revision) {
80
119
  try {
81
- const fileFullPath = `${workspace_root_1.workspaceRoot}${path_1.sep}${file}`;
82
- const gitRepositoryPath = (0, child_process_1.execSync)('git rev-parse --show-toplevel', {
83
- windowsHide: true,
84
- })
85
- .toString()
86
- .trim();
87
- const filePathInGitRepository = (0, path_1.relative)(gitRepositoryPath, fileFullPath)
88
- .split(path_1.sep)
89
- .join('/');
120
+ const filePathInGitRepository = getFilePathInGitRepository(file);
90
121
  return !revision
91
122
  ? (0, fs_1.readFileSync)(file, 'utf-8')
92
123
  : (0, child_process_1.execSync)(`git show ${revision}:${filePathInGitRepository}`, {
@@ -101,6 +132,43 @@ function defaultReadFileAtRevision(file, revision) {
101
132
  return '';
102
133
  }
103
134
  }
135
+ function defaultReadBunLockFileAtRevision(file, revision) {
136
+ if (!revision) {
137
+ return (0, child_process_1.execFileSync)('bun', [(0, path_1.join)(workspace_root_1.workspaceRoot, file)], {
138
+ encoding: 'utf-8',
139
+ maxBuffer: exports.TEN_MEGABYTES,
140
+ windowsHide: true,
141
+ }).trim();
142
+ }
143
+ const filePathInGitRepository = getFilePathInGitRepository(file);
144
+ const tempDirectory = (0, fs_1.mkdtempSync)((0, path_1.join)((0, os_1.tmpdir)(), 'nx-bun-lock-'));
145
+ const tempLockfilePath = (0, path_1.join)(tempDirectory, 'bun.lockb');
146
+ try {
147
+ const lockFileContents = (0, child_process_1.execFileSync)('git', ['show', `${revision}:${filePathInGitRepository}`], {
148
+ maxBuffer: exports.TEN_MEGABYTES,
149
+ stdio: ['pipe', 'pipe', 'ignore'],
150
+ windowsHide: true,
151
+ });
152
+ (0, fs_1.writeFileSync)(tempLockfilePath, lockFileContents);
153
+ return (0, child_process_1.execFileSync)('bun', [tempLockfilePath], {
154
+ encoding: 'utf-8',
155
+ maxBuffer: exports.TEN_MEGABYTES,
156
+ windowsHide: true,
157
+ }).trim();
158
+ }
159
+ finally {
160
+ (0, fs_1.rmSync)(tempDirectory, { force: true, recursive: true });
161
+ }
162
+ }
163
+ function getFilePathInGitRepository(file) {
164
+ const fileFullPath = `${workspace_root_1.workspaceRoot}${path_1.sep}${file}`;
165
+ const gitRepositoryPath = (0, child_process_1.execSync)('git rev-parse --show-toplevel', {
166
+ windowsHide: true,
167
+ })
168
+ .toString()
169
+ .trim();
170
+ return (0, path_1.relative)(gitRepositoryPath, fileFullPath).split(path_1.sep).join('/');
171
+ }
104
172
  function defaultFileRead(filePath) {
105
173
  return (0, fs_1.readFileSync)((0, path_1.join)(workspace_root_1.workspaceRoot, filePath), 'utf-8');
106
174
  }
@@ -2,7 +2,7 @@ import type { PluginConfiguration } from '../../../config/nx-json';
2
2
  import type { ProjectGraph } from '../../../config/project-graph';
3
3
  import type { RawProjectGraphDependency } from '../../project-graph-builder';
4
4
  import { LoadedNxPlugin } from '../loaded-nx-plugin';
5
- import type { CreateDependenciesContext, CreateMetadataContext, CreateNodesContextV2, CreateNodesResult, PostTasksExecutionContext, PreTasksExecutionContext, ProjectsMetadata } from '../public-api';
5
+ import type { CreateDependenciesContext, CreateMetadataContext, CreateNodesContext, CreateNodesResult, PostTasksExecutionContext, PreTasksExecutionContext, ProjectsMetadata } from '../public-api';
6
6
  import type { PluginWorkerLoadResult } from './messaging';
7
7
  import { Hook, Phase } from './plugin-lifecycle-manager';
8
8
  export type LoadResultPayload = Extract<PluginWorkerLoadResult['payload'], {
@@ -15,7 +15,7 @@ export declare class IsolatedPlugin implements LoadedNxPlugin {
15
15
  readonly exclude?: string[];
16
16
  readonly createNodes?: [
17
17
  filePattern: string,
18
- fn: (matchedFiles: string[], context: CreateNodesContextV2) => Promise<Array<readonly [plugin: string, file: string, result: CreateNodesResult]>>
18
+ fn: (matchedFiles: string[], context: CreateNodesContext) => Promise<Array<readonly [plugin: string, file: string, result: CreateNodesResult]>>
19
19
  ];
20
20
  readonly createDependencies?: (context: CreateDependenciesContext) => Promise<RawProjectGraphDependency[]>;
21
21
  readonly createMetadata?: (graph: ProjectGraph, context: CreateMetadataContext) => Promise<ProjectsMetadata>;
@@ -3,7 +3,7 @@ import type { Socket } from 'net';
3
3
  import type { PluginConfiguration } from '../../../config/nx-json';
4
4
  import type { ProjectGraph } from '../../../config/project-graph';
5
5
  import type { LoadedNxPlugin } from '../loaded-nx-plugin';
6
- import type { CreateDependenciesContext, CreateMetadataContext, CreateNodesContextV2, PostTasksExecutionContext, PreTasksExecutionContext } from '../public-api';
6
+ import type { CreateDependenciesContext, CreateMetadataContext, CreateNodesContext, PostTasksExecutionContext, PreTasksExecutionContext } from '../public-api';
7
7
  import type { AllMessages, AllResults, DefineMessages, Handlers, ResultOf, WithResult } from './message-types';
8
8
  /**
9
9
  * All plugin worker message definitions in one place.
@@ -39,7 +39,7 @@ type PluginMessageDefs = DefineMessages<{
39
39
  createNodes: {
40
40
  payload: {
41
41
  configFiles: string[];
42
- context: CreateNodesContextV2;
42
+ context: CreateNodesContext;
43
43
  };
44
44
  result: {
45
45
  success: true;
@@ -1,7 +1,7 @@
1
1
  import type { ProjectGraph } from '../../config/project-graph';
2
2
  import { type PluginConfiguration } from '../../config/nx-json';
3
3
  import type { RawProjectGraphDependency } from '../project-graph-builder';
4
- import type { CreateDependenciesContext, CreateMetadataContext, CreateNodesContextV2, CreateNodesResult, NxPluginV2, PostTasksExecutionContext, PreTasksExecutionContext, ProjectsMetadata } from './public-api';
4
+ import type { CreateDependenciesContext, CreateMetadataContext, CreateNodesContext, CreateNodesResult, NxPlugin, PostTasksExecutionContext, PreTasksExecutionContext, ProjectsMetadata } from './public-api';
5
5
  /**
6
6
  * NOTE: Avoid using `import type` with this class. It causes issues with
7
7
  * jest's module resolution when running tests in projects that import
@@ -12,7 +12,7 @@ export declare class LoadedNxPlugin {
12
12
  readonly name: string;
13
13
  readonly createNodes?: [
14
14
  filePattern: string,
15
- fn: (matchedFiles: string[], context: CreateNodesContextV2) => Promise<Array<readonly [plugin: string, file: string, result: CreateNodesResult]>>
15
+ fn: (matchedFiles: string[], context: CreateNodesContext) => Promise<Array<readonly [plugin: string, file: string, result: CreateNodesResult]>>
16
16
  ];
17
17
  readonly createDependencies?: (context: CreateDependenciesContext) => Promise<RawProjectGraphDependency[]>;
18
18
  readonly createMetadata?: (graph: ProjectGraph, context: CreateMetadataContext) => Promise<ProjectsMetadata>;
@@ -37,5 +37,5 @@ export declare class LoadedNxPlugin {
37
37
  * daemon's process.env automatically.
38
38
  */
39
39
  setWorkerEnv?(env: Record<string, string>): Promise<void>;
40
- constructor(plugin: NxPluginV2, pluginDefinition: PluginConfiguration, index?: number);
40
+ constructor(plugin: NxPlugin, pluginDefinition: PluginConfiguration, index?: number);
41
41
  }
@@ -19,12 +19,14 @@ class LoadedNxPlugin {
19
19
  this.include = pluginDefinition.include;
20
20
  this.exclude = pluginDefinition.exclude;
21
21
  }
22
- const createNodesV2Impl = plugin.createNodesV2 ?? plugin.createNodes;
23
- if (createNodesV2Impl) {
22
+ // Fall back to `createNodesV2` for plugins authored against the old name.
23
+ const createNodesImpl = plugin.createNodes ??
24
+ plugin.createNodesV2;
25
+ if (createNodesImpl) {
24
26
  this.createNodes = [
25
- createNodesV2Impl[0],
27
+ createNodesImpl[0],
26
28
  async (configFiles, context) => {
27
- const result = await createNodesV2Impl[1](configFiles, this.options, context);
29
+ const result = await createNodesImpl[1](configFiles, this.options, context);
28
30
  return result.map((r) => [this.name, r[0], r[1]]);
29
31
  },
30
32
  ];
@@ -1,14 +1,26 @@
1
1
  import type { FileMap, ProjectGraph, ProjectGraphExternalNode } from '../../config/project-graph';
2
2
  import type { ProjectConfiguration } from '../../config/workspace-json-project-json';
3
3
  import type { NxJsonConfiguration } from '../../config/nx-json';
4
- import type { RawProjectGraphDependency } from '../project-graph-builder';
5
4
  import type { TaskResults } from '../../tasks-runner/life-cycle';
6
- export interface CreateNodesContextV2 {
5
+ import type { RawProjectGraphDependency } from '../project-graph-builder';
6
+ export interface CreateNodesContext {
7
7
  readonly nxJsonConfiguration: NxJsonConfiguration;
8
8
  readonly workspaceRoot: string;
9
9
  }
10
- export type CreateNodesResultV2 = Array<readonly [configFileSource: string, result: CreateNodesResult]>;
11
- export type CreateNodesFunctionV2<T = unknown> = (projectConfigurationFiles: readonly string[], options: T | undefined, context: CreateNodesContextV2) => CreateNodesResultV2 | Promise<CreateNodesResultV2>;
10
+ /**
11
+ * @deprecated This will be removed in Nx 24. See {@link CreateNodesContext}
12
+ */
13
+ export type CreateNodesContextV2 = CreateNodesContext;
14
+ export type CreateNodesResultArray = Array<readonly [configFileSource: string, result: CreateNodesResult]>;
15
+ /**
16
+ * @deprecated This will be removed in Nx 24. See {@link CreateNodesResultArray}
17
+ */
18
+ export type CreateNodesResultV2 = CreateNodesResultArray;
19
+ export type CreateNodesFunction<T = unknown> = (projectConfigurationFiles: readonly string[], options: T | undefined, context: CreateNodesContext) => CreateNodesResultArray | Promise<CreateNodesResultArray>;
20
+ /**
21
+ * @deprecated see {@link CreateNodesFunction}
22
+ */
23
+ export type CreateNodesFunctionV2<T = unknown> = CreateNodesFunction<T>;
12
24
  export type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
13
25
  export interface CreateNodesResult {
14
26
  /**
@@ -21,13 +33,16 @@ export interface CreateNodesResult {
21
33
  externalNodes?: Record<string, ProjectGraphExternalNode>;
22
34
  }
23
35
  /**
24
- * A pair of file patterns and {@link CreateNodesFunctionV2}
25
- * In Nx 21 {@link CreateNodes} will be replaced with this type. In Nx 22, this type will be removed.
36
+ * A pair of file patterns and {@link CreateNodesFunction}
26
37
  */
27
- export type CreateNodesV2<T = unknown> = readonly [
38
+ export type CreateNodes<T = unknown> = readonly [
28
39
  projectFilePattern: string,
29
- createNodesFunction: CreateNodesFunctionV2<T>
40
+ createNodesFunction: CreateNodesFunction<T>
30
41
  ];
42
+ /**
43
+ * @deprecated - use {@link CreateNodes} instead
44
+ */
45
+ export type CreateNodesV2<T = unknown> = CreateNodes<T>;
31
46
  /**
32
47
  * Context for {@link CreateDependencies}
33
48
  */
@@ -68,18 +83,20 @@ export type CreateMetadata<T = unknown> = (graph: ProjectGraph, options: T | und
68
83
  /**
69
84
  * A plugin which enhances the behavior of Nx
70
85
  */
71
- export type NxPluginV2<TOptions = unknown> = {
86
+ export type NxPlugin<TOptions = unknown> = {
72
87
  name: string;
73
88
  /**
74
89
  * Provides a file pattern and function that retrieves configuration info from
75
90
  * those files. e.g. { '**\/*.csproj': buildProjectsFromCsProjFile }
76
91
  */
77
- createNodes?: CreateNodesV2<TOptions>;
92
+ createNodes?: CreateNodes<TOptions>;
78
93
  /**
79
94
  * Provides a file pattern and function that retrieves configuration info from
80
95
  * those files. e.g. { '**\/*.csproj': buildProjectsFromCsProjFiles }
96
+ *
97
+ * @deprecated Prefer `createNodes` for new plugins
81
98
  */
82
- createNodesV2?: CreateNodesV2<TOptions>;
99
+ createNodesV2?: CreateNodes<TOptions>;
83
100
  /**
84
101
  * Provides a function to analyze files to create dependencies for the {@link ProjectGraph}
85
102
  */
@@ -116,5 +133,7 @@ export type PreTasksExecution<TOptions = unknown> = (options: TOptions | undefin
116
133
  export type PostTasksExecution<TOptions = unknown> = (options: TOptions | undefined, context: PostTasksExecutionContext) => void | Promise<void>;
117
134
  /**
118
135
  * A plugin which enhances the behavior of Nx
136
+ *
137
+ * @deprecated See {@link NxPlugin}
119
138
  */
120
- export type NxPlugin<TOptions = unknown> = NxPluginV2<TOptions>;
139
+ export type NxPluginV2<TOptions = unknown> = NxPlugin<TOptions>;