nx 23.1.0 → 23.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/nx.js +2 -1
- package/dist/release/changelog-renderer/index.js +4 -5
- package/dist/release/index.d.ts +1 -1
- package/dist/src/ai/configure-ai-agents-disclaimer.d.ts +5 -0
- package/dist/src/ai/configure-ai-agents-disclaimer.js +31 -0
- package/dist/src/analytics/analytics.d.ts +6 -0
- package/dist/src/analytics/analytics.js +16 -8
- package/dist/src/analytics/index.d.ts +1 -1
- package/dist/src/analytics/index.js +2 -1
- package/dist/src/command-line/add/add.js +13 -1
- package/dist/src/command-line/affected/affected.js +1 -0
- package/dist/src/command-line/configure-ai-agents/configure-ai-agents.js +2 -2
- package/dist/src/command-line/graph/graph.d.ts +1 -0
- package/dist/src/command-line/graph/graph.js +15 -6
- package/dist/src/command-line/import/import.js +2 -3
- package/dist/src/command-line/init/ai-agent-prompts.d.ts +1 -1
- package/dist/src/command-line/init/ai-agent-prompts.js +7 -6
- package/dist/src/command-line/init/command-object.js +10 -2
- package/dist/src/command-line/init/configure-plugins.js +3 -2
- package/dist/src/command-line/init/implementation/add-nx-to-monorepo.js +4 -2
- package/dist/src/command-line/init/implementation/add-nx-to-nest.js +4 -3
- package/dist/src/command-line/init/implementation/add-nx-to-npm-repo.js +4 -3
- package/dist/src/command-line/init/implementation/add-nx-to-turborepo.js +4 -3
- package/dist/src/command-line/init/implementation/angular/index.js +4 -2
- package/dist/src/command-line/init/implementation/angular/integrated-workspace.js +2 -5
- package/dist/src/command-line/init/implementation/angular/legacy-angular-versions.js +3 -0
- package/dist/src/command-line/init/implementation/dot-nx/add-nx-scripts.js +4 -1
- package/dist/src/command-line/init/implementation/utils.d.ts +3 -3
- package/dist/src/command-line/init/implementation/utils.js +22 -3
- package/dist/src/command-line/init/init-v2.js +4 -5
- package/dist/src/command-line/migrate/execute-migration.d.ts +72 -0
- package/dist/src/command-line/migrate/execute-migration.js +389 -0
- package/dist/src/command-line/migrate/migrate-ui-api.js +17 -12
- package/dist/src/command-line/migrate/migrate.d.ts +5 -45
- package/dist/src/command-line/migrate/migrate.js +122 -402
- package/dist/src/command-line/nx-cloud/connect/connect-to-nx-cloud.js +1 -1
- package/dist/src/command-line/nx-cloud/connect/view-logs.js +2 -0
- package/dist/src/command-line/release/changelog.js +5 -0
- package/dist/src/command-line/release/index.d.ts +1 -1
- package/dist/src/command-line/release/utils/git.js +7 -3
- package/dist/src/command-line/release/utils/release-graph.d.ts +19 -2
- package/dist/src/command-line/release/utils/release-graph.js +71 -19
- package/dist/src/command-line/release/utils/remote-release-clients/github.js +7 -1
- package/dist/src/command-line/release/utils/remote-release-clients/gitlab.js +1 -1
- package/dist/src/command-line/release/utils/shared.d.ts +2 -2
- package/dist/src/command-line/release/version/release-group-processor.d.ts +24 -0
- package/dist/src/command-line/release/version/release-group-processor.js +80 -6
- package/dist/src/command-line/release/version/version-actions.d.ts +27 -2
- package/dist/src/command-line/release/version/version-actions.js +9 -1
- package/dist/src/command-line/release/version.js +9 -5
- package/dist/src/command-line/reset/reset.js +6 -1
- package/dist/src/command-line/run/run-one.js +1 -0
- package/dist/src/command-line/run-many/run-many.js +1 -0
- package/dist/src/command-line/show/show-target/info.js +11 -2
- package/dist/src/command-line/show/show-target/inputs.js +50 -153
- package/dist/src/command-line/show/show-target/outputs.js +48 -173
- package/dist/src/command-line/show/show-target/utils.d.ts +28 -0
- package/dist/src/command-line/show/show-target/utils.js +83 -3
- package/dist/src/command-line/watch/watch.js +13 -0
- package/dist/src/command-line/yargs-utils/shared-options.d.ts +1 -1
- package/dist/src/commands-runner/create-command-graph.js +5 -0
- package/dist/src/config/nx-json.d.ts +5 -3
- package/dist/src/core/graph/main.js +1 -1
- package/dist/src/core/graph/styles.js +1 -1
- package/dist/src/daemon/client/client.d.ts +52 -3
- package/dist/src/daemon/client/client.js +177 -55
- package/dist/src/daemon/client/daemon-environment.d.ts +17 -0
- package/dist/src/daemon/client/daemon-environment.js +110 -2
- package/dist/src/daemon/client/daemon-socket-messenger.js +4 -0
- package/dist/src/daemon/message-types/daemon-message.d.ts +32 -0
- package/dist/src/daemon/message-types/daemon-message.js +25 -0
- package/dist/src/daemon/server/file-watching/file-watcher-sockets.d.ts +5 -0
- package/dist/src/daemon/server/file-watching/file-watcher-sockets.js +16 -0
- package/dist/src/daemon/server/handle-tasks-execution-hooks.d.ts +1 -1
- package/dist/src/daemon/server/latest-nx.js +5 -2
- package/dist/src/daemon/server/server.js +31 -4
- package/dist/src/daemon/server/shutdown-utils.d.ts +5 -0
- package/dist/src/daemon/server/shutdown-utils.js +11 -4
- package/dist/src/daemon/socket-utils.d.ts +1 -0
- package/dist/src/daemon/socket-utils.js +24 -3
- package/dist/src/daemon/tmp-dir.d.ts +43 -3
- package/dist/src/daemon/tmp-dir.js +437 -15
- package/dist/src/devkit-internals.d.ts +96 -3
- package/dist/src/devkit-internals.js +200 -4
- package/dist/src/generators/internal-utils/format-changed-files-with-prettier-if-available.d.ts +5 -0
- package/dist/src/generators/internal-utils/format-changed-files-with-prettier-if-available.js +9 -2
- package/dist/src/generators/tree.d.ts +4 -2
- package/dist/src/generators/utils/nx-json.js +13 -3
- package/dist/src/hasher/check-task-files.d.ts +86 -0
- package/dist/src/hasher/check-task-files.js +378 -0
- package/dist/src/migrations/update-23-2-0/set-cache-on-executor-target-defaults.d.ts +12 -0
- package/dist/src/migrations/update-23-2-0/set-cache-on-executor-target-defaults.js +250 -0
- package/dist/src/migrations/update-23-2-0/set-cache-on-executor-target-defaults.md +50 -0
- package/dist/src/native/index.d.ts +31 -2
- package/dist/src/native/index.js +71 -28
- package/dist/src/native/native-bindings.js +3 -0
- package/dist/src/native/native-file-cache-location.d.ts +17 -1
- package/dist/src/native/native-file-cache-location.js +86 -12
- package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
- package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
- package/dist/src/nx-cloud/utilities/get-cloud-options.js +5 -2
- package/dist/src/nx-cloud/utilities/onboarding.js +5 -2
- package/dist/src/plugins/js/lock-file/bun-parser.js +43 -10
- package/dist/src/plugins/js/lock-file/npm-parser.js +71 -27
- package/dist/src/plugins/js/lock-file/pnpm-parser.js +110 -17
- package/dist/src/plugins/js/lock-file/project-graph-pruning.js +15 -9
- package/dist/src/plugins/js/lock-file/utils/pnpm-normalizer.js +3 -0
- package/dist/src/plugins/js/lock-file/yarn-parser.js +32 -5
- package/dist/src/plugins/js/project-graph/affected/npm-packages.js +51 -20
- package/dist/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +14 -4
- package/dist/src/plugins/js/utils/register.d.ts +18 -0
- package/dist/src/plugins/js/utils/register.js +81 -0
- package/dist/src/plugins/js/utils/typescript.d.ts +9 -0
- package/dist/src/plugins/js/utils/typescript.js +15 -0
- package/dist/src/project-graph/affected/affected-project-graph-models.d.ts +1 -1
- package/dist/src/project-graph/affected/affected-project-graph.d.ts +1 -1
- package/dist/src/project-graph/affected/affected-project-graph.js +2 -2
- package/dist/src/project-graph/affected/locators/project-glob-changes.js +5 -2
- package/dist/src/project-graph/build-project-graph.js +7 -1
- package/dist/src/project-graph/error-types.d.ts +12 -1
- package/dist/src/project-graph/error-types.js +68 -3
- package/dist/src/project-graph/file-utils.js +6 -1
- package/dist/src/project-graph/plugins/isolation/isolated-plugin.d.ts +1 -0
- package/dist/src/project-graph/plugins/isolation/isolated-plugin.js +22 -1
- package/dist/src/project-graph/plugins/isolation/messaging.d.ts +16 -3
- package/dist/src/project-graph/plugins/isolation/messaging.js +3 -0
- package/dist/src/project-graph/plugins/isolation/plugin-worker.js +58 -8
- package/dist/src/project-graph/plugins/loaded-nx-plugin.js +1 -0
- package/dist/src/project-graph/plugins/transpiler.js +4 -0
- package/dist/src/project-graph/project-graph.js +23 -0
- package/dist/src/project-graph/utils/project-configuration/name-substitution-manager.d.ts +10 -12
- package/dist/src/project-graph/utils/project-configuration/name-substitution-manager.js +93 -63
- package/dist/src/project-graph/utils/project-configuration/project-nodes-manager.d.ts +5 -8
- package/dist/src/project-graph/utils/project-configuration/project-nodes-manager.js +16 -15
- package/dist/src/project-graph/utils/project-configuration/source-maps.d.ts +12 -5
- package/dist/src/project-graph/utils/project-configuration/source-maps.js +21 -7
- package/dist/src/project-graph/utils/project-configuration/target-defaults.d.ts +1 -1
- package/dist/src/project-graph/utils/project-configuration/target-defaults.js +26 -27
- package/dist/src/project-graph/utils/project-configuration/target-merging.js +50 -8
- package/dist/src/project-graph/utils/project-configuration/target-normalization.js +149 -6
- package/dist/src/project-graph/utils/project-configuration/utils.d.ts +15 -0
- package/dist/src/project-graph/utils/project-configuration/utils.js +42 -6
- package/dist/src/project-graph/utils/project-configuration-utils.d.ts +15 -12
- package/dist/src/project-graph/utils/project-configuration-utils.js +79 -101
- package/dist/src/tasks-runner/life-cycles/performance-analysis.d.ts +11 -4
- package/dist/src/tasks-runner/life-cycles/performance-analysis.js +15 -6
- package/dist/src/tasks-runner/life-cycles/performance-life-cycle.js +5 -4
- package/dist/src/tasks-runner/life-cycles/performance-report.d.ts +18 -8
- package/dist/src/tasks-runner/life-cycles/performance-report.js +66 -29
- package/dist/src/tasks-runner/run-command.js +4 -2
- package/dist/src/tasks-runner/task-env.d.ts +9 -0
- package/dist/src/tasks-runner/task-env.js +31 -4
- package/dist/src/tasks-runner/task-orchestrator.d.ts +4 -1
- package/dist/src/tasks-runner/task-orchestrator.js +23 -10
- package/dist/src/tasks-runner/utils.js +2 -6
- package/dist/src/utils/acknowledge-build-scripts.d.ts +13 -0
- package/dist/src/utils/acknowledge-build-scripts.js +102 -0
- package/dist/src/utils/analytics-prompt.d.ts +0 -6
- package/dist/src/utils/analytics-prompt.js +0 -51
- package/dist/src/utils/assert-workspace-validity.js +7 -2
- package/dist/src/utils/catalog/manager-utils.d.ts +1 -2
- package/dist/src/utils/catalog/manager-utils.js +22 -5
- package/dist/src/utils/catalog/pnpm-manager.d.ts +1 -0
- package/dist/src/utils/catalog/pnpm-manager.js +3 -15
- package/dist/src/utils/catalog/yarn-manager.d.ts +1 -0
- package/dist/src/utils/catalog/yarn-manager.js +3 -15
- package/dist/src/utils/command-line-utils.js +30 -20
- package/dist/src/utils/fileutils.d.ts +5 -0
- package/dist/src/utils/fileutils.js +7 -2
- package/dist/src/utils/git-revision.d.ts +12 -0
- package/dist/src/utils/git-revision.js +25 -0
- package/dist/src/utils/git-utils.d.ts +16 -3
- package/dist/src/utils/git-utils.js +146 -52
- package/dist/src/utils/git-worktrees.d.ts +30 -0
- package/dist/src/utils/git-worktrees.js +212 -0
- package/dist/src/utils/ignore.d.ts +128 -1
- package/dist/src/utils/ignore.js +182 -12
- package/dist/src/utils/long-running-target.d.ts +10 -0
- package/dist/src/utils/long-running-target.js +19 -0
- package/dist/src/utils/min-release-age/behavior/bun.js +7 -11
- package/dist/src/utils/min-release-age/behavior/npm.js +5 -2
- package/dist/src/utils/min-release-age/behavior/pnpm.js +9 -7
- package/dist/src/utils/min-release-age/packument.js +1 -1
- package/dist/src/utils/nx-tmp-dir.d.ts +18 -0
- package/dist/src/utils/nx-tmp-dir.js +40 -0
- package/dist/src/utils/owned-private-dir.d.ts +132 -0
- package/dist/src/utils/owned-private-dir.js +323 -0
- package/dist/src/utils/package-json.js +11 -7
- package/dist/src/utils/package-manager-config/bunfig.d.ts +14 -0
- package/dist/src/utils/package-manager-config/bunfig.js +49 -0
- package/dist/src/utils/package-manager-config/npmrc.d.ts +23 -0
- package/dist/src/utils/package-manager-config/npmrc.js +124 -0
- package/dist/src/utils/package-manager-config/pnpm-config.d.ts +17 -0
- package/dist/src/utils/package-manager-config/pnpm-config.js +60 -0
- package/dist/src/utils/package-manager.d.ts +23 -2
- package/dist/src/utils/package-manager.js +264 -43
- package/dist/src/utils/provenance.js +18 -16
- package/dist/src/utils/registry-config/bun.d.ts +2 -0
- package/dist/src/utils/registry-config/bun.js +257 -0
- package/dist/src/utils/registry-config/index.d.ts +13 -0
- package/dist/src/utils/registry-config/index.js +102 -0
- package/dist/src/utils/registry-config/pnpm.d.ts +2 -0
- package/dist/src/utils/registry-config/pnpm.js +1551 -0
- package/dist/src/utils/registry-config/utils.d.ts +195 -0
- package/dist/src/utils/registry-config/utils.js +496 -0
- package/dist/src/utils/registry-config/yarn-berry.d.ts +2 -0
- package/dist/src/utils/registry-config/yarn-berry.js +612 -0
- package/dist/src/utils/registry-config/yarn-classic.d.ts +2 -0
- package/dist/src/utils/registry-config/yarn-classic.js +1001 -0
- package/dist/src/utils/safe-spawn.d.ts +24 -0
- package/dist/src/utils/safe-spawn.js +104 -0
- package/dist/src/utils/shell-quoting.d.ts +15 -0
- package/dist/src/utils/shell-quoting.js +35 -0
- package/dist/src/utils/wait-for-socket-connection.d.ts +11 -0
- package/dist/src/utils/wait-for-socket-connection.js +14 -8
- package/dist/src/utils/workspace-id.d.ts +20 -0
- package/dist/src/utils/workspace-id.js +54 -0
- package/migrations.json +13 -1
- package/package.json +22 -17
- package/dist/src/migrations/update-17-3-0/nx-release-path.d.ts +0 -3
- package/dist/src/migrations/update-17-3-0/nx-release-path.js +0 -47
- package/dist/src/utils/min-release-age/npmrc.d.ts +0 -15
- package/dist/src/utils/min-release-age/npmrc.js +0 -45
|
@@ -21,7 +21,7 @@ const utils_1 = require("./utils");
|
|
|
21
21
|
* fly. That's all the matcher needs; the full target merge happens
|
|
22
22
|
* downstream in the real merge.
|
|
23
23
|
*/
|
|
24
|
-
function createTargetDefaultsResults(specifiedPluginRootMap, defaultPluginRootMap, nxJsonConfiguration, specifiedSourceMaps
|
|
24
|
+
function createTargetDefaultsResults(specifiedPluginRootMap, defaultPluginRootMap, nxJsonConfiguration, specifiedSourceMaps) {
|
|
25
25
|
const targetDefaultsConfig = nxJsonConfiguration.targetDefaults;
|
|
26
26
|
if (!targetDefaultsConfig) {
|
|
27
27
|
return [];
|
|
@@ -65,7 +65,7 @@ function createTargetDefaultsResults(specifiedPluginRootMap, defaultPluginRootMa
|
|
|
65
65
|
if (!effective)
|
|
66
66
|
continue;
|
|
67
67
|
const sourcePlugin = needsSourcePlugin
|
|
68
|
-
? resolveSourcePlugin(root, targetName,
|
|
68
|
+
? resolveSourcePlugin(root, targetName, defaultTargets[targetName], specifiedSourceMaps)
|
|
69
69
|
: undefined;
|
|
70
70
|
const syntheticTargets = buildSyntheticTargetsForRoot(targetName, root, effective, targetDefaults, projectName, projectNode, sourcePlugin);
|
|
71
71
|
for (const { key, index, target } of syntheticTargets) {
|
|
@@ -372,34 +372,33 @@ function normalizeTargetDefaultValue(value) {
|
|
|
372
372
|
// A bare config object is functionally a one-element array.
|
|
373
373
|
return [value ?? {}];
|
|
374
374
|
}
|
|
375
|
-
function resolveSourcePlugin(root, targetName,
|
|
376
|
-
//
|
|
377
|
-
//
|
|
378
|
-
//
|
|
379
|
-
//
|
|
380
|
-
//
|
|
381
|
-
//
|
|
382
|
-
//
|
|
383
|
-
//
|
|
384
|
-
//
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
375
|
+
function resolveSourcePlugin(root, targetName, defaultTarget, specifiedSourceMaps) {
|
|
376
|
+
// `filter.plugin` ("targets originated by X") can only name a plugin from
|
|
377
|
+
// nx.json's `plugins` — the specified set. When the default layer authors
|
|
378
|
+
// the target's identity (its merged config carries an executor or command,
|
|
379
|
+
// which the merge lets win), the originator is a default plugin and the
|
|
380
|
+
// target has no matchable source plugin; no source maps are needed to see
|
|
381
|
+
// that. Otherwise the specified layer's executor/command attribution names
|
|
382
|
+
// the originator. The top-level `targets.<name>` node key is deliberately
|
|
383
|
+
// NOT used as a fallback: it tracks ownership, so a later plugin augmenting
|
|
384
|
+
// the target would mis-attribute it. The trade-off is that a target with
|
|
385
|
+
// neither an executor nor a command (a rare, non-runnable shape) resolves to
|
|
386
|
+
// no source plugin and won't match a `filter.plugin` default — accepted,
|
|
387
|
+
// since every runnable target carries one of these keys.
|
|
388
|
+
if (defaultTarget &&
|
|
389
|
+
(defaultTarget.executor !== undefined ||
|
|
390
|
+
defaultTarget.command !== undefined)) {
|
|
391
|
+
return undefined;
|
|
392
|
+
}
|
|
393
|
+
const sourceMap = specifiedSourceMaps?.[root];
|
|
394
|
+
for (const identityKey of ['executor', 'command']) {
|
|
395
|
+
const plugin = sourceMap?.[`${(0, source_maps_1.targetSourceMapKey)(targetName)}.${identityKey}`]?.[1];
|
|
396
|
+
if (plugin && plugin !== source_maps_1.TARGET_DEFAULTS_PLUGIN_NAME) {
|
|
397
|
+
return plugin;
|
|
398
|
+
}
|
|
396
399
|
}
|
|
397
400
|
return undefined;
|
|
398
401
|
}
|
|
399
|
-
function pluginFromSourceMap(maps, root, key) {
|
|
400
|
-
const entry = maps?.[root]?.[key];
|
|
401
|
-
return entry?.[1];
|
|
402
|
-
}
|
|
403
402
|
// Builds a name → MatcherProjectNode view for `findMatchingProjects` to
|
|
404
403
|
// consult, across both layered rootMaps. Tags are unioned across layers. A
|
|
405
404
|
// full `mergeProjectConfigurationIntoRootMap` would be overkill — the matcher
|
|
@@ -170,6 +170,11 @@ function mergeConfigurations(newConfigurations, baseConfigurations, projectConfi
|
|
|
170
170
|
// Before '...': base wins for shared names. Keep base's source-map
|
|
171
171
|
// entries when it owns the config.
|
|
172
172
|
if (baseHasConfig) {
|
|
173
|
+
// Base wins, so the incoming config is dropped without reaching
|
|
174
|
+
// `mergeConfigurationValue`. Validate its nested spread here so an
|
|
175
|
+
// integer-like-key ambiguity throws regardless of which side owns
|
|
176
|
+
// the config name (mirrors the base-independent target-level check).
|
|
177
|
+
(0, utils_1.assertNoIntegerLikeSpreadKey)(newConfigurations?.[configName], configIdentifier ? `Object at "${configIdentifier}"` : 'Object');
|
|
173
178
|
mergedConfigurations[configName] = baseConfigurations[configName];
|
|
174
179
|
}
|
|
175
180
|
else {
|
|
@@ -282,8 +287,11 @@ function mergeTargetConfigurations(target, baseTarget, projectConfigSourceMap, s
|
|
|
282
287
|
? new Set(targetKeys.slice(0, spreadPosInTarget))
|
|
283
288
|
: new Set();
|
|
284
289
|
// Integer-like keys get hoisted to targetKeys[0], making their position
|
|
285
|
-
// relative to '...' unrecoverable.
|
|
286
|
-
|
|
290
|
+
// relative to '...' unrecoverable. This is a property of the authored
|
|
291
|
+
// config, not of the base, so it throws regardless of compatibility —
|
|
292
|
+
// which also keeps the error identical between the target-defaults staging
|
|
293
|
+
// merge and the real merge, whose bases differ.
|
|
294
|
+
if (spreadPosInTarget >= 0 &&
|
|
287
295
|
targetKeys[0] &&
|
|
288
296
|
utils_1.INTEGER_LIKE_KEY_PATTERN.test(targetKeys[0])) {
|
|
289
297
|
throw new utils_1.IntegerLikeSpreadKeyError(targetKeys[0], targetIdentifier ? `Target at "${targetIdentifier}"` : 'Target');
|
|
@@ -304,6 +312,13 @@ function mergeTargetConfigurations(target, baseTarget, projectConfigSourceMap, s
|
|
|
304
312
|
return;
|
|
305
313
|
if (hasSpread && keysBeforeSpread.has(key)) {
|
|
306
314
|
// Before '...': base wins; fall through to target only if base lacks it.
|
|
315
|
+
// When base wins, the incoming `target[key]` is dropped without ever
|
|
316
|
+
// reaching `getMergeValueResult`, so validate its nested spread here —
|
|
317
|
+
// the integer-like-key ambiguity is a property of the authored value,
|
|
318
|
+
// not of which side owns the key, and must throw either way.
|
|
319
|
+
(0, utils_1.assertNoIntegerLikeSpreadKey)(target[key], projectConfigSourceMap
|
|
320
|
+
? `Object at "${targetIdentifier}.${key}"`
|
|
321
|
+
: 'Object');
|
|
307
322
|
result[key] =
|
|
308
323
|
key in mergeBase
|
|
309
324
|
? mergeBase[key]
|
|
@@ -381,13 +396,20 @@ function mergeTargetConfigurations(target, baseTarget, projectConfigSourceMap, s
|
|
|
381
396
|
processKey(key);
|
|
382
397
|
}
|
|
383
398
|
}
|
|
384
|
-
// Update
|
|
385
|
-
//
|
|
386
|
-
//
|
|
387
|
-
//
|
|
388
|
-
//
|
|
399
|
+
// Update the node key once after the loop. Ownership follows identity: this
|
|
400
|
+
// merge claims `targets.<name>` only when it changed the target's identity
|
|
401
|
+
// (a new/different executor or command, or an incompatible replace — whose
|
|
402
|
+
// key purge above empties the slot anyway). A plugin that only layers fields
|
|
403
|
+
// onto an existing target leaves the node with its creator; weak
|
|
404
|
+
// target-defaults stamps are always reclaimable.
|
|
389
405
|
if (projectConfigSourceMap) {
|
|
390
|
-
|
|
406
|
+
const identityChanged = !isCompatible ||
|
|
407
|
+
(target.executor !== undefined &&
|
|
408
|
+
target.executor !== baseTarget?.executor) ||
|
|
409
|
+
(target.command !== undefined &&
|
|
410
|
+
target.command !== baseTarget?.command) ||
|
|
411
|
+
suppliesNewOptionsIdentity(baseTarget, target);
|
|
412
|
+
(0, source_maps_1.recordTargetIdentitySourceMapInfo)(projectConfigSourceMap, targetIdentifier, sourceInformation, identityChanged);
|
|
391
413
|
}
|
|
392
414
|
// merge options if there are any
|
|
393
415
|
// if the targets aren't compatible, we simply discard the old options during the merge
|
|
@@ -443,6 +465,26 @@ function isCompatibleTarget(a, b) {
|
|
|
443
465
|
}
|
|
444
466
|
return true;
|
|
445
467
|
}
|
|
468
|
+
/**
|
|
469
|
+
* Run-commands and run-script targets carry their runnable identity in
|
|
470
|
+
* `options` (see {@link isCompatibleTarget}). A layer that supplies that
|
|
471
|
+
* identity where the base had none changed what the target runs — the same
|
|
472
|
+
* identity change as setting an executor on a target that had none.
|
|
473
|
+
*/
|
|
474
|
+
function suppliesNewOptionsIdentity(baseTarget, target) {
|
|
475
|
+
const executor = target.executor ?? baseTarget?.executor;
|
|
476
|
+
if (executor === 'nx:run-commands') {
|
|
477
|
+
const baseCommand = baseTarget?.options?.command ??
|
|
478
|
+
baseTarget?.options?.commands?.join(' && ');
|
|
479
|
+
const targetCommand = target.options?.command ?? target.options?.commands?.join(' && ');
|
|
480
|
+
return !!targetCommand && targetCommand !== baseCommand;
|
|
481
|
+
}
|
|
482
|
+
if (executor === 'nx:run-script') {
|
|
483
|
+
const targetScript = target.options?.script;
|
|
484
|
+
return !!targetScript && targetScript !== baseTarget?.options?.script;
|
|
485
|
+
}
|
|
486
|
+
return false;
|
|
487
|
+
}
|
|
446
488
|
function resolveNxTokensInOptions(object, project, key) {
|
|
447
489
|
const result = Array.isArray(object) ? [...object] : { ...object };
|
|
448
490
|
for (let [opt, value] of Object.entries(object ?? {})) {
|
|
@@ -5,10 +5,13 @@ exports.normalizeTarget = normalizeTarget;
|
|
|
5
5
|
exports.validateAndNormalizeProjectRootMap = validateAndNormalizeProjectRootMap;
|
|
6
6
|
const executor_utils_1 = require("../../../command-line/run/executor-utils");
|
|
7
7
|
const fileutils_1 = require("../../../utils/fileutils");
|
|
8
|
+
const long_running_target_1 = require("../../../utils/long-running-target");
|
|
9
|
+
const output_1 = require("../../../utils/output");
|
|
8
10
|
const to_project_name_1 = require("../../../config/to-project-name");
|
|
9
11
|
const error_types_1 = require("../../error-types");
|
|
10
12
|
const target_merging_1 = require("./target-merging");
|
|
11
13
|
const node_fs_1 = require("node:fs");
|
|
14
|
+
const git_worktrees_1 = require("../../../utils/git-worktrees");
|
|
12
15
|
const path_1 = require("path");
|
|
13
16
|
function validateProject(project,
|
|
14
17
|
// name -> project
|
|
@@ -65,15 +68,137 @@ function normalizeTarget(target, project, workspaceRoot, projectsMap, errorMsgKe
|
|
|
65
68
|
}
|
|
66
69
|
return target;
|
|
67
70
|
}
|
|
71
|
+
// TODO(v24): remove the legacy target-name cache fallback and its warning.
|
|
72
|
+
// Removal needs a second mechanism for plugin-inferred targets, which the
|
|
73
|
+
// accompanying migration cannot reach.
|
|
74
|
+
/**
|
|
75
|
+
* Whether `target` is cacheable only by way of the legacy name-based fallback:
|
|
76
|
+
* the exact target-name key of `targetDefaults` declares `cache: true`, but an
|
|
77
|
+
* executor key won target-default resolution instead, so the merged target never
|
|
78
|
+
* received it.
|
|
79
|
+
*
|
|
80
|
+
* A `true` result means the user's `cache: true` silently lost, so this doubles
|
|
81
|
+
* as the condition for warning them that the name key is being shadowed.
|
|
82
|
+
*/
|
|
83
|
+
function isLegacyCachedTarget(targetName, targetDefaults, target) {
|
|
84
|
+
// Resolution already decided `cache`, so the name key isn't shadowed.
|
|
85
|
+
if (target.cache !== undefined) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
if (isLongRunningTarget(targetName, target)) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
// Restricted to shadowing, which is narrower than what pre-23 restored: that
|
|
92
|
+
// derivation matched on target name alone, so a name key dropped as
|
|
93
|
+
// incompatible (its entry declared a foreign executor) was cacheable too.
|
|
94
|
+
// Restoring that as well would mean writing `cache` with no key to name in
|
|
95
|
+
// the warning, and no migration able to retire it. Deliberately not covered.
|
|
96
|
+
if (!findShadowingTargetDefaultKey(targetDefaults, target)) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
return declaresCacheTrue(targetDefaults?.[targetName]);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Whether the name key declares `cache: true` on an entry that always applies.
|
|
103
|
+
*
|
|
104
|
+
* Filters are deliberately not evaluated. They cannot express a pre-23 config
|
|
105
|
+
* (the filtered array shape postdates the behavior being restored), and a
|
|
106
|
+
* filtered entry declaring `cache` may or may not apply to this project — so
|
|
107
|
+
* rather than guess, a filtered `cache` declares the value unknowable and
|
|
108
|
+
* nothing is restored. Among unfiltered entries the last wins, matching the
|
|
109
|
+
* in-key merge order.
|
|
110
|
+
*/
|
|
111
|
+
function declaresCacheTrue(value) {
|
|
112
|
+
if (!value) {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
const entries = Array.isArray(value) ? value : [value];
|
|
116
|
+
let declared;
|
|
117
|
+
for (const entry of entries) {
|
|
118
|
+
// `nx.json` is hand-edited; a null or scalar entry would throw here.
|
|
119
|
+
if (!entry || typeof entry !== 'object')
|
|
120
|
+
continue;
|
|
121
|
+
if (entry.cache === undefined)
|
|
122
|
+
continue;
|
|
123
|
+
if (entry.filter)
|
|
124
|
+
return false;
|
|
125
|
+
declared = entry.cache;
|
|
126
|
+
}
|
|
127
|
+
return declared === true;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* The normalization-time half of the pre-23 `longRunningTask` guard, which kept
|
|
131
|
+
* `cacheableOperations` from ever making these cacheable. Its remaining clause
|
|
132
|
+
* — `task.overrides['watch']` — is a runtime invocation override with no target
|
|
133
|
+
* equivalent, so it has no counterpart here.
|
|
134
|
+
*/
|
|
135
|
+
function isLongRunningTarget(targetName, target) {
|
|
136
|
+
return !!target.continuous || (0, long_running_target_1.isLongRunningTargetName)(targetName);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* The `targetDefaults` key that beat the target-name key for `target`. Only an
|
|
140
|
+
* executor key can: key precedence puts the exact target name ahead of every
|
|
141
|
+
* glob, so nothing else outranks it. Undefined when the name key lost for
|
|
142
|
+
* another reason (e.g. its entry declared a foreign executor and was dropped as
|
|
143
|
+
* incompatible) — see {@link isLegacyCachedTarget} for why that case is left
|
|
144
|
+
* alone even though pre-23 restored it.
|
|
145
|
+
*
|
|
146
|
+
* `hasOwnProperty` rather than a lookup: an executor named `__proto__` resolves
|
|
147
|
+
* through the prototype chain to a truthy object, which would report a key the
|
|
148
|
+
* user never wrote.
|
|
149
|
+
*/
|
|
150
|
+
function findShadowingTargetDefaultKey(targetDefaults, target) {
|
|
151
|
+
return target.executor &&
|
|
152
|
+
targetDefaults &&
|
|
153
|
+
Object.prototype.hasOwnProperty.call(targetDefaults, target.executor)
|
|
154
|
+
? target.executor
|
|
155
|
+
: undefined;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Emits a single grouped warning for every (shadowing key, target-name key)
|
|
159
|
+
* pair that relied on the deprecated fallback. Grouping matters because the
|
|
160
|
+
* same pair recurs in every affected project — a per-target warning would
|
|
161
|
+
* print hundreds of identical lines in a large workspace.
|
|
162
|
+
*/
|
|
163
|
+
function warnAboutLegacyCachedTargets(legacyCacheReads) {
|
|
164
|
+
if (legacyCacheReads.size === 0) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const bodyLines = [];
|
|
168
|
+
for (const [shadowingKey, targetKeys] of legacyCacheReads) {
|
|
169
|
+
for (const targetKey of targetKeys) {
|
|
170
|
+
bodyLines.push(` - "${shadowingKey}" does not set "cache", so it was read from "${targetKey}"`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
bodyLines.push('', 'An executor key applies to every target that resolves through it, so exclude any continuous target before setting "cache" on one — a target that is both cacheable and continuous is rejected.', 'Target defaults resolve to a single key rather than merging, so an executor key hides the target name key entirely.', 'Set "cache" on the executor key to keep these targets cacheable — reading it from the target name key is deprecated and will be removed in Nx 24.');
|
|
174
|
+
output_1.output.warn({
|
|
175
|
+
title: 'Some targets are only cacheable through a deprecated fallback.',
|
|
176
|
+
bodyLines,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
68
179
|
function normalizeTargets(project, sourceMaps, nxJsonConfiguration, workspaceRoot,
|
|
69
180
|
/**
|
|
70
181
|
* Project configurations keyed by project name
|
|
71
182
|
*/
|
|
72
|
-
projects
|
|
183
|
+
projects,
|
|
184
|
+
/**
|
|
185
|
+
* Shadowing `targetDefaults` key -> target name keys its `cache` was read
|
|
186
|
+
* from. Accumulated across projects so the deprecation warns once per pair.
|
|
187
|
+
*/
|
|
188
|
+
legacyCacheReads) {
|
|
73
189
|
const targetErrorMessage = [];
|
|
74
190
|
for (const targetName in project.targets) {
|
|
75
191
|
project.targets[targetName] = normalizeTarget(project.targets[targetName], project, workspaceRoot, projects, [project.root, targetName].join(':'));
|
|
76
192
|
const target = project.targets[targetName];
|
|
193
|
+
const targetDefaults = nxJsonConfiguration.targetDefaults;
|
|
194
|
+
if (isLegacyCachedTarget(targetName, targetDefaults, target)) {
|
|
195
|
+
target.cache = true;
|
|
196
|
+
// Always defined: `isLegacyCachedTarget` returns false without it.
|
|
197
|
+
const shadowingKey = findShadowingTargetDefaultKey(targetDefaults, target);
|
|
198
|
+
const targetKeys = legacyCacheReads.get(shadowingKey) ?? new Set();
|
|
199
|
+
targetKeys.add(targetName);
|
|
200
|
+
legacyCacheReads.set(shadowingKey, targetKeys);
|
|
201
|
+
}
|
|
77
202
|
if (
|
|
78
203
|
// If the target has no executor or command, it doesn't do anything
|
|
79
204
|
!target.executor &&
|
|
@@ -106,6 +231,7 @@ function validateAndNormalizeProjectRootMap(workspaceRoot, projectRootMap, nxJso
|
|
|
106
231
|
const conflicts = new Map();
|
|
107
232
|
const projectRootsWithNoName = [];
|
|
108
233
|
const validityErrors = [];
|
|
234
|
+
const legacyCacheReads = new Map();
|
|
109
235
|
for (const root in projectRootMap) {
|
|
110
236
|
const project = projectRootMap[root];
|
|
111
237
|
// We're setting `// targets` as a comment `targets` is empty due to Project Crystal.
|
|
@@ -115,9 +241,22 @@ function validateAndNormalizeProjectRootMap(workspaceRoot, projectRootMap, nxJso
|
|
|
115
241
|
// We initially did this in the project.json plugin, but
|
|
116
242
|
// that resulted in project.json files without names causing
|
|
117
243
|
// the resulting project to change names from earlier plugins...
|
|
118
|
-
if (!project.name
|
|
119
|
-
|
|
120
|
-
|
|
244
|
+
if (!project.name) {
|
|
245
|
+
const projectJsonPath = (0, path_1.join)(workspaceRoot, project.root, 'project.json');
|
|
246
|
+
if ((0, node_fs_1.existsSync)(projectJsonPath)) {
|
|
247
|
+
// The project.json plugin may not have run (e.g. when a single
|
|
248
|
+
// plugin is run in isolation via `addPlugin` from a generator), so
|
|
249
|
+
// prefer the name declared in project.json before deriving one from
|
|
250
|
+
// the directory name.
|
|
251
|
+
let nameFromProjectJson;
|
|
252
|
+
try {
|
|
253
|
+
nameFromProjectJson =
|
|
254
|
+
(0, fileutils_1.readJsonFile)(projectJsonPath).name;
|
|
255
|
+
}
|
|
256
|
+
catch { }
|
|
257
|
+
project.name =
|
|
258
|
+
nameFromProjectJson ?? (0, to_project_name_1.toProjectName)((0, path_1.join)(root, 'project.json'));
|
|
259
|
+
}
|
|
121
260
|
}
|
|
122
261
|
try {
|
|
123
262
|
validateProject(project, projects);
|
|
@@ -142,7 +281,7 @@ function validateAndNormalizeProjectRootMap(workspaceRoot, projectRootMap, nxJso
|
|
|
142
281
|
for (const root in projectRootMap) {
|
|
143
282
|
const project = projectRootMap[root];
|
|
144
283
|
try {
|
|
145
|
-
normalizeTargets(project, sourceMaps, nxJsonConfiguration, workspaceRoot, projects);
|
|
284
|
+
normalizeTargets(project, sourceMaps, nxJsonConfiguration, workspaceRoot, projects, legacyCacheReads);
|
|
146
285
|
}
|
|
147
286
|
catch (e) {
|
|
148
287
|
if (e instanceof error_types_1.WorkspaceValidityError) {
|
|
@@ -153,9 +292,13 @@ function validateAndNormalizeProjectRootMap(workspaceRoot, projectRootMap, nxJso
|
|
|
153
292
|
}
|
|
154
293
|
}
|
|
155
294
|
}
|
|
295
|
+
warnAboutLegacyCachedTargets(legacyCacheReads);
|
|
156
296
|
const errors = [];
|
|
157
297
|
if (conflicts.size > 0) {
|
|
158
|
-
|
|
298
|
+
// Only on the way to throwing, so a workspace without duplicates never
|
|
299
|
+
// pays for reading git's worktree registry.
|
|
300
|
+
const worktreeAdvice = (0, git_worktrees_1.analyzeWorktreeConflicts)(workspaceRoot, conflicts);
|
|
301
|
+
errors.push(new error_types_1.MultipleProjectsWithSameNameError(conflicts, projects, worktreeAdvice ?? undefined));
|
|
159
302
|
}
|
|
160
303
|
if (projectRootsWithNoName.length > 0) {
|
|
161
304
|
errors.push(new error_types_1.ProjectsWithNoNameError(projectRootsWithNoName, projects));
|
|
@@ -8,6 +8,21 @@ export declare const INTEGER_LIKE_KEY_PATTERN: RegExp;
|
|
|
8
8
|
export declare class IntegerLikeSpreadKeyError extends Error {
|
|
9
9
|
constructor(key: string, context: string);
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Throws `IntegerLikeSpreadKeyError` when `value` is a `'...'` spread object
|
|
13
|
+
* whose enumeration hoists an integer-like key ahead of the spread, making its
|
|
14
|
+
* authored position ambiguous.
|
|
15
|
+
*
|
|
16
|
+
* The ambiguity is a property of the authored value alone, not of any merge
|
|
17
|
+
* base. `mergeObjectWithSpread` runs this the moment it merges such a value —
|
|
18
|
+
* but a merge layer that lets the base win a key drops the incoming value
|
|
19
|
+
* without merging it, so the check must also be run eagerly at those
|
|
20
|
+
* base-owns-key shortcuts. Otherwise the error would surface or vanish
|
|
21
|
+
* depending on which side owns the key (e.g. it fires in the target-defaults
|
|
22
|
+
* staging merge but not the real merge), which is exactly the divergence that
|
|
23
|
+
* makes discarding staging errors unsafe.
|
|
24
|
+
*/
|
|
25
|
+
export declare function assertNoIntegerLikeSpreadKey(value: unknown, errorContext: string): void;
|
|
11
26
|
type SourceMapContext = {
|
|
12
27
|
sourceMap: Record<string, SourceInformation>;
|
|
13
28
|
key: string;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.IntegerLikeSpreadKeyError = exports.INTEGER_LIKE_KEY_PATTERN = exports.NX_SPREAD_TOKEN = void 0;
|
|
4
4
|
exports.uniqueKeysInObjects = uniqueKeysInObjects;
|
|
5
|
+
exports.assertNoIntegerLikeSpreadKey = assertNoIntegerLikeSpreadKey;
|
|
5
6
|
exports.getMergeValueResult = getMergeValueResult;
|
|
6
7
|
const source_maps_1 = require("./source-maps");
|
|
7
8
|
exports.NX_SPREAD_TOKEN = '...';
|
|
@@ -30,6 +31,29 @@ class IntegerLikeSpreadKeyError extends Error {
|
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
33
|
exports.IntegerLikeSpreadKeyError = IntegerLikeSpreadKeyError;
|
|
34
|
+
/**
|
|
35
|
+
* Throws `IntegerLikeSpreadKeyError` when `value` is a `'...'` spread object
|
|
36
|
+
* whose enumeration hoists an integer-like key ahead of the spread, making its
|
|
37
|
+
* authored position ambiguous.
|
|
38
|
+
*
|
|
39
|
+
* The ambiguity is a property of the authored value alone, not of any merge
|
|
40
|
+
* base. `mergeObjectWithSpread` runs this the moment it merges such a value —
|
|
41
|
+
* but a merge layer that lets the base win a key drops the incoming value
|
|
42
|
+
* without merging it, so the check must also be run eagerly at those
|
|
43
|
+
* base-owns-key shortcuts. Otherwise the error would surface or vanish
|
|
44
|
+
* depending on which side owns the key (e.g. it fires in the target-defaults
|
|
45
|
+
* staging merge but not the real merge), which is exactly the divergence that
|
|
46
|
+
* makes discarding staging errors unsafe.
|
|
47
|
+
*/
|
|
48
|
+
function assertNoIntegerLikeSpreadKey(value, errorContext) {
|
|
49
|
+
if (!isObject(value) || value[exports.NX_SPREAD_TOKEN] !== true) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const keys = Object.keys(value);
|
|
53
|
+
if (keys[0] && exports.INTEGER_LIKE_KEY_PATTERN.test(keys[0])) {
|
|
54
|
+
throw new IntegerLikeSpreadKeyError(keys[0], errorContext);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
33
57
|
/**
|
|
34
58
|
* `"..."` in `newValue` (as an array element or a key set to `true`)
|
|
35
59
|
* expands the base at that position; otherwise `newValue` replaces
|
|
@@ -52,11 +76,25 @@ function getMergeValueResult(baseValue, newValue, sourceMapContext, deferSpreads
|
|
|
52
76
|
// plugin already set, purely as a merge guard — must not steal provenance
|
|
53
77
|
// from the layer that introduced the value. A genuinely new value (no base,
|
|
54
78
|
// or a different one) still attributes to the new layer.
|
|
55
|
-
|
|
79
|
+
//
|
|
80
|
+
// The exception cuts the other way too: when the *existing* attribution is a
|
|
81
|
+
// target-defaults stamp (TD merges before the plugin whose value it
|
|
82
|
+
// predicted, so its stamp lands first), a real plugin re-stating that value
|
|
83
|
+
// is the genuine author and reclaims the key.
|
|
84
|
+
if (!isUnchangedPrimitive(newValue, baseValue) ||
|
|
85
|
+
isReclaimableTargetDefaultsStamp(sourceMapContext)) {
|
|
56
86
|
writeTopLevelSourceMap(sourceMapContext);
|
|
57
87
|
}
|
|
58
88
|
return newValue;
|
|
59
89
|
}
|
|
90
|
+
// Whether the key's current attribution is a weak target-defaults stamp that
|
|
91
|
+
// the (non-target-defaults) writer should reclaim despite the value being
|
|
92
|
+
// unchanged.
|
|
93
|
+
function isReclaimableTargetDefaultsStamp(ctx) {
|
|
94
|
+
return (!!ctx &&
|
|
95
|
+
ctx.sourceMap[ctx.key]?.[1] === source_maps_1.TARGET_DEFAULTS_PLUGIN_NAME &&
|
|
96
|
+
ctx.sourceInformation[1] !== source_maps_1.TARGET_DEFAULTS_PLUGIN_NAME);
|
|
97
|
+
}
|
|
60
98
|
// Whether `newValue` leaves a defined primitive base untouched. Objects fall
|
|
61
99
|
// through (always re-attributed) to preserve the existing replace semantics —
|
|
62
100
|
// the regression this guards is scalar executor/command re-stamping.
|
|
@@ -120,12 +158,10 @@ function mergeObjectWithSpread(baseValue, newValue, sourceMapContext, deferSprea
|
|
|
120
158
|
const errorContext = sourceMapContext?.key
|
|
121
159
|
? `Object at "${sourceMapContext.key}"`
|
|
122
160
|
: 'Object';
|
|
161
|
+
// Integer-like keys are hoisted to the front of enumeration, so one
|
|
162
|
+
// alongside `'...'` makes its authored position ambiguous.
|
|
163
|
+
assertNoIntegerLikeSpreadKey(newValue, errorContext);
|
|
123
164
|
const newKeys = Object.keys(newValue);
|
|
124
|
-
// Integer-like keys are hoisted to the front of enumeration, so if one
|
|
125
|
-
// exists alongside `'...'` it must be newKeys[0].
|
|
126
|
-
if (newKeys[0] && exports.INTEGER_LIKE_KEY_PATTERN.test(newKeys[0])) {
|
|
127
|
-
throw new IntegerLikeSpreadKeyError(newKeys[0], errorContext);
|
|
128
|
-
}
|
|
129
165
|
// Base per-key sources captured lazily — only for shared keys the new
|
|
130
166
|
// object overwrites before `'...'`, since writing their new source
|
|
131
167
|
// clobbers the base entry the spread will need to restore.
|
|
@@ -60,19 +60,22 @@ export type MergeError = AggregateCreateNodesError | MergeNodesError | ProjectsW
|
|
|
60
60
|
/**
|
|
61
61
|
* Merges create nodes results into a single rootMap.
|
|
62
62
|
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* `'...'` spreads deferred) so that synthesis can read each layer's
|
|
66
|
-
* contribution without re-running the merge. The synthetic result from
|
|
67
|
-
* `createTargetDefaultsResults` is then merged into the manager, and
|
|
68
|
-
* the staged intermediate is replayed on top — that replay is where
|
|
69
|
-
* deferred spreads expand against the final (specified + synth) base.
|
|
63
|
+
* Every layer merges into the manager through the same source-map-aware
|
|
64
|
+
* merge, in precedence order:
|
|
70
65
|
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
66
|
+
* specified plugins → synthetic target defaults → default plugins
|
|
67
|
+
*
|
|
68
|
+
* so field-level provenance is decided by the merge itself for all three
|
|
69
|
+
* layers — whichever layer a field's final value came from owns its
|
|
70
|
+
* attribution, and `'...'` spreads in default-plugin configs resolve against
|
|
71
|
+
* the accumulated specified + target-defaults base.
|
|
72
|
+
*
|
|
73
|
+
* Target-default synthesis needs the *merged* shape of the default layer
|
|
74
|
+
* (to predict each target's eventual executor/command) before that layer
|
|
75
|
+
* merges into the manager. To get it, default results are first staged into
|
|
76
|
+
* a throwaway intermediate rootMap with unresolvable `'...'` spreads
|
|
77
|
+
* deferred. The staging output feeds only `createTargetDefaultsResults`; the
|
|
78
|
+
* default plugins then merge into the manager from their original results.
|
|
76
79
|
*/
|
|
77
80
|
export declare function mergeCreateNodesResults(specifiedResults: CreateNodesResultEntry[][], defaultResults: CreateNodesResultEntry[][], nxJsonConfiguration: NxJsonConfiguration, workspaceRoot: string, errors: MergeError[]): {
|
|
78
81
|
projectRootMap: Record<string, ProjectConfiguration>;
|