nx 23.3.0 → 24.0.0-beta.0
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/README.md +3 -6
- package/dist/src/adapter/ngcli-adapter.js +1 -0
- package/dist/src/command-line/configure-ai-agents/configure-ai-agents.js +0 -12
- package/dist/src/command-line/graph/graph.js +3 -5
- package/dist/src/command-line/init/command-object.js +0 -12
- package/dist/src/command-line/init/init-v2.js +0 -2
- package/dist/src/command-line/nx-cloud/connect/connect-to-nx-cloud.js +17 -12
- package/dist/src/command-line/release/utils/remote-release-clients/github.js +5 -6
- package/dist/src/command-line/release/utils/remote-release-clients/gitlab.js +5 -6
- package/dist/src/command-line/run/executor-utils.js +1 -0
- package/dist/src/command-line/run/run-one.d.ts +20 -1
- package/dist/src/command-line/run/run-one.js +153 -5
- package/dist/src/command-line/show/show-target/utils.js +1 -0
- package/dist/src/command-line/watch/command-object.js +3 -22
- package/dist/src/command-line/watch/watch.d.ts +0 -7
- package/dist/src/command-line/watch/watch.js +1 -1
- package/dist/src/config/misc-interfaces.d.ts +12 -0
- package/dist/src/config/workspace-json-project-json.d.ts +5 -0
- package/dist/src/daemon/client/client.d.ts +9 -0
- package/dist/src/daemon/client/client.js +89 -37
- package/dist/src/daemon/server/shutdown-utils.js +0 -3
- package/dist/src/daemon/socket-utils.d.ts +9 -4
- package/dist/src/daemon/socket-utils.js +12 -49
- package/dist/src/daemon/tmp-dir.d.ts +19 -14
- package/dist/src/daemon/tmp-dir.js +142 -354
- package/dist/src/devkit-internals.d.ts +1 -1
- package/dist/src/devkit-internals.js +1 -0
- package/dist/src/hasher/file-hasher.js +9 -7
- package/dist/src/hasher/hash-task.js +4 -0
- package/dist/src/hasher/native-task-hasher-impl.js +1 -1
- package/dist/src/migrations/update-24-0-0/find-custom-hashers.d.ts +3 -0
- package/dist/src/migrations/update-24-0-0/find-custom-hashers.js +100 -0
- package/dist/src/migrations/update-24-0-0/find-custom-hashers.md +63 -0
- package/dist/src/migrations/update-24-0-0/move-custom-hashers-to-inputs.md +145 -0
- package/dist/src/native/index.d.ts +127 -8
- package/dist/src/native/native-bindings.js +5 -0
- package/dist/src/native/nx.wasi-browser.js +1 -0
- package/dist/src/native/nx.wasi.cjs +1 -0
- 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/update-manager.d.ts +7 -0
- package/dist/src/nx-cloud/update-manager.js +237 -50
- package/dist/src/project-graph/affected/affected-tasks.js +1 -0
- package/dist/src/project-graph/plugins/isolation/isolated-plugin.js +7 -0
- package/dist/src/tasks-runner/create-task-graph.d.ts +10 -0
- package/dist/src/tasks-runner/create-task-graph.js +37 -2
- package/dist/src/tasks-runner/task-env.d.ts +10 -0
- package/dist/src/tasks-runner/task-env.js +26 -5
- package/dist/src/tasks-runner/task-orchestrator.d.ts +10 -4
- package/dist/src/tasks-runner/task-orchestrator.js +87 -53
- package/dist/src/tasks-runner/utils.d.ts +20 -5
- package/dist/src/tasks-runner/utils.js +80 -29
- package/dist/src/ultracache/overrides.js +4 -0
- package/dist/src/utils/owned-private-dir.d.ts +1 -17
- package/dist/src/utils/owned-private-dir.js +10 -62
- package/dist/src/utils/perf-hooks.d.ts +1 -0
- package/dist/src/utils/plugins/core-plugins.js +1 -1
- package/dist/src/utils/string-similarity.d.ts +38 -0
- package/dist/src/utils/string-similarity.js +108 -0
- package/migrations.json +7 -0
- package/package.json +11 -20
- package/readme-template.md +3 -3
- package/schemas/nx-schema.json +5 -0
- package/schemas/project-schema.json +5 -0
- package/dist/src/tasks-runner/legacy-depends-on-warning.d.ts +0 -18
- package/dist/src/tasks-runner/legacy-depends-on-warning.js +0 -109
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.levenshteinDistance = levenshteinDistance;
|
|
4
|
+
exports.rankByDistance = rankByDistance;
|
|
5
|
+
exports.isWithinSuggestionThreshold = isWithinSuggestionThreshold;
|
|
6
|
+
exports.rankSuggestions = rankSuggestions;
|
|
7
|
+
exports.findClosestMatches = findClosestMatches;
|
|
8
|
+
/**
|
|
9
|
+
* Computes the Levenshtein edit distance between two strings, i.e. the minimum
|
|
10
|
+
* number of single-character insertions, deletions, or substitutions required
|
|
11
|
+
* to turn `a` into `b`.
|
|
12
|
+
*/
|
|
13
|
+
function levenshteinDistance(a, b) {
|
|
14
|
+
if (a === b) {
|
|
15
|
+
return 0;
|
|
16
|
+
}
|
|
17
|
+
if (a.length === 0) {
|
|
18
|
+
return b.length;
|
|
19
|
+
}
|
|
20
|
+
if (b.length === 0) {
|
|
21
|
+
return a.length;
|
|
22
|
+
}
|
|
23
|
+
let previousRow = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
24
|
+
let currentRow = new Array(b.length + 1);
|
|
25
|
+
for (let i = 0; i < a.length; i++) {
|
|
26
|
+
currentRow[0] = i + 1;
|
|
27
|
+
for (let j = 0; j < b.length; j++) {
|
|
28
|
+
const cost = a[i] === b[j] ? 0 : 1;
|
|
29
|
+
currentRow[j + 1] = Math.min(currentRow[j] + 1, // insertion
|
|
30
|
+
previousRow[j + 1] + 1, // deletion
|
|
31
|
+
previousRow[j] + cost // substitution
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
[previousRow, currentRow] = [currentRow, previousRow];
|
|
35
|
+
}
|
|
36
|
+
return previousRow[b.length];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Ranks every candidate by how closely it resembles `input`, from closest to
|
|
40
|
+
* furthest, tie-broken alphabetically so the order is deterministic. Each entry
|
|
41
|
+
* keeps its computed distance so callers can reuse it (e.g. to both pick the
|
|
42
|
+
* closest match and order a list) without recomputing.
|
|
43
|
+
*/
|
|
44
|
+
function rankByDistance(input, candidates) {
|
|
45
|
+
return candidates
|
|
46
|
+
.map((candidate) => ({
|
|
47
|
+
candidate,
|
|
48
|
+
distance: levenshteinDistance(input, candidate),
|
|
49
|
+
}))
|
|
50
|
+
.sort((a, b) => a.distance - b.distance || a.candidate.localeCompare(b.candidate));
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The number of edits tolerated before `candidate` stops being a useful
|
|
54
|
+
* suggestion for `input`.
|
|
55
|
+
*
|
|
56
|
+
* The tolerance scales with length so longer words allow for more typos, but it
|
|
57
|
+
* scales with the length of the part that actually *differs* — the shared
|
|
58
|
+
* prefix and suffix are stripped first. Scaling on the raw length lets text the
|
|
59
|
+
* user typed correctly buy a bigger budget for the part they got wrong, which
|
|
60
|
+
* matters because these inputs are joined `project:target[:configuration]`
|
|
61
|
+
* specifiers: `zzz:build` and `api:build` are 3 edits apart, but the shared
|
|
62
|
+
* `:build` inflates the raw-length budget to 4 and a project name with no
|
|
63
|
+
* character in common gets suggested.
|
|
64
|
+
*
|
|
65
|
+
* Stripping a common prefix and suffix does not change the Levenshtein
|
|
66
|
+
* distance, so a caller's precomputed `distance` remains directly comparable.
|
|
67
|
+
*/
|
|
68
|
+
function suggestionThreshold(input, candidate) {
|
|
69
|
+
const shortest = Math.min(input.length, candidate.length);
|
|
70
|
+
let prefix = 0;
|
|
71
|
+
while (prefix < shortest && input[prefix] === candidate[prefix]) {
|
|
72
|
+
prefix++;
|
|
73
|
+
}
|
|
74
|
+
let suffix = 0;
|
|
75
|
+
while (suffix < shortest - prefix &&
|
|
76
|
+
input[input.length - 1 - suffix] ===
|
|
77
|
+
candidate[candidate.length - 1 - suffix]) {
|
|
78
|
+
suffix++;
|
|
79
|
+
}
|
|
80
|
+
return Math.max(2, Math.ceil((input.length - prefix - suffix) * 0.4));
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Whether a candidate at edit `distance` from `input` is close enough to be a
|
|
84
|
+
* useful suggestion. Exposed so callers that already have a distance (e.g. from
|
|
85
|
+
* `rankByDistance`) can gate on it without recomputing.
|
|
86
|
+
*/
|
|
87
|
+
function isWithinSuggestionThreshold(input, candidate, distance) {
|
|
88
|
+
return distance <= suggestionThreshold(input, candidate);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Ranks the candidates that are similar enough to `input` to be worth
|
|
92
|
+
* suggesting, closest first (ties broken alphabetically). Each entry keeps its
|
|
93
|
+
* distance so callers can compare suggestions found for different forms of the
|
|
94
|
+
* same input without recomputing.
|
|
95
|
+
*/
|
|
96
|
+
function rankSuggestions(input, candidates) {
|
|
97
|
+
return rankByDistance(input, candidates).filter(({ candidate, distance }) => isWithinSuggestionThreshold(input, candidate, distance));
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Returns up to `limit` candidates that most closely resemble `input`, sorted
|
|
101
|
+
* from closest to furthest. Candidates that are not similar enough to be a
|
|
102
|
+
* useful suggestion are excluded.
|
|
103
|
+
*/
|
|
104
|
+
function findClosestMatches(input, candidates, limit = 3) {
|
|
105
|
+
return rankSuggestions(input, candidates)
|
|
106
|
+
.slice(0, limit)
|
|
107
|
+
.map(({ candidate }) => candidate);
|
|
108
|
+
}
|
package/migrations.json
CHANGED
|
@@ -190,6 +190,13 @@
|
|
|
190
190
|
"description": "Sets \"cache\" on some executor-based target defaults whose caching was previously enabled by a target name default, maintaining compatibility with how cacheability resolved before Nx 23. Keys the migration cannot decide are left alone and keep working through a deprecated runtime fallback.",
|
|
191
191
|
"implementation": "./dist/src/migrations/update-23-2-0/set-cache-on-executor-target-defaults",
|
|
192
192
|
"documentation": "./dist/src/migrations/update-23-2-0/set-cache-on-executor-target-defaults.md"
|
|
193
|
+
},
|
|
194
|
+
"24-0-0-move-custom-hashers-to-inputs": {
|
|
195
|
+
"version": "24.0.0-beta.0",
|
|
196
|
+
"description": "Finds local executors that declare a custom hasher, which is deprecated and will be removed in Nx 25. Rewriting a hasher as target inputs means reading what its code hashes, so the rewrite is driven by an AI prompt; the generator only reports each hasher.",
|
|
197
|
+
"implementation": "./dist/src/migrations/update-24-0-0/find-custom-hashers",
|
|
198
|
+
"prompt": "./dist/src/migrations/update-24-0-0/move-custom-hashers-to-inputs.md",
|
|
199
|
+
"documentation": "./dist/src/migrations/update-24-0-0/find-custom-hashers.md"
|
|
193
200
|
}
|
|
194
201
|
}
|
|
195
202
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nx",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "24.0.0-beta.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
|
|
@@ -66,7 +66,6 @@
|
|
|
66
66
|
"bl": "4.1.0",
|
|
67
67
|
"brace-expansion": "5.0.12",
|
|
68
68
|
"buffer": "5.7.1",
|
|
69
|
-
"bundle-name": "4.1.0",
|
|
70
69
|
"chalk": "4.1.2",
|
|
71
70
|
"cli-cursor": "3.1.0",
|
|
72
71
|
"cli-spinners": "2.6.1",
|
|
@@ -74,10 +73,7 @@
|
|
|
74
73
|
"clone": "1.0.4",
|
|
75
74
|
"color-convert": "2.0.1",
|
|
76
75
|
"color-name": "1.1.4",
|
|
77
|
-
"default-browser": "5.2.1",
|
|
78
|
-
"default-browser-id": "5.0.0",
|
|
79
76
|
"defaults": "1.0.4",
|
|
80
|
-
"define-lazy-prop": "3.0.0",
|
|
81
77
|
"dotenv": "16.4.7",
|
|
82
78
|
"dotenv-expand": "12.0.3",
|
|
83
79
|
"ejs": "5.0.1",
|
|
@@ -95,12 +91,9 @@
|
|
|
95
91
|
"ieee754": "1.2.1",
|
|
96
92
|
"ignore": "7.0.6",
|
|
97
93
|
"inherits": "2.0.4",
|
|
98
|
-
"is-docker": "3.0.0",
|
|
99
94
|
"is-fullwidth-code-point": "3.0.0",
|
|
100
|
-
"is-inside-container": "1.0.0",
|
|
101
95
|
"is-interactive": "1.0.0",
|
|
102
96
|
"is-unicode-supported": "0.1.0",
|
|
103
|
-
"is-wsl": "3.1.0",
|
|
104
97
|
"isexe": "2.0.0",
|
|
105
98
|
"json5": "2.2.3",
|
|
106
99
|
"jsonc-parser": "3.3.1",
|
|
@@ -112,7 +105,6 @@
|
|
|
112
105
|
"npm-run-path": "4.0.1",
|
|
113
106
|
"once": "1.4.0",
|
|
114
107
|
"onetime": "5.1.2",
|
|
115
|
-
"open": "10.1.0",
|
|
116
108
|
"ora": "5.4.1",
|
|
117
109
|
"path-key": "3.1.1",
|
|
118
110
|
"picocolors": "1.1.1",
|
|
@@ -120,7 +112,6 @@
|
|
|
120
112
|
"require-directory": "2.1.1",
|
|
121
113
|
"resolve.exports": "2.0.3",
|
|
122
114
|
"restore-cursor": "3.1.0",
|
|
123
|
-
"run-applescript": "7.0.0",
|
|
124
115
|
"safe-buffer": "5.2.1",
|
|
125
116
|
"semver": "7.8.5",
|
|
126
117
|
"signal-exit": "3.0.7",
|
|
@@ -159,16 +150,16 @@
|
|
|
159
150
|
}
|
|
160
151
|
},
|
|
161
152
|
"optionalDependencies": {
|
|
162
|
-
"@nx/nx-darwin-arm64": "
|
|
163
|
-
"@nx/nx-darwin-x64": "
|
|
164
|
-
"@nx/nx-freebsd-x64": "
|
|
165
|
-
"@nx/nx-linux-arm-gnueabihf": "
|
|
166
|
-
"@nx/nx-linux-arm64-gnu": "
|
|
167
|
-
"@nx/nx-linux-arm64-musl": "
|
|
168
|
-
"@nx/nx-linux-x64-gnu": "
|
|
169
|
-
"@nx/nx-linux-x64-musl": "
|
|
170
|
-
"@nx/nx-win32-arm64-msvc": "
|
|
171
|
-
"@nx/nx-win32-x64-msvc": "
|
|
153
|
+
"@nx/nx-darwin-arm64": "24.0.0-beta.0",
|
|
154
|
+
"@nx/nx-darwin-x64": "24.0.0-beta.0",
|
|
155
|
+
"@nx/nx-freebsd-x64": "24.0.0-beta.0",
|
|
156
|
+
"@nx/nx-linux-arm-gnueabihf": "24.0.0-beta.0",
|
|
157
|
+
"@nx/nx-linux-arm64-gnu": "24.0.0-beta.0",
|
|
158
|
+
"@nx/nx-linux-arm64-musl": "24.0.0-beta.0",
|
|
159
|
+
"@nx/nx-linux-x64-gnu": "24.0.0-beta.0",
|
|
160
|
+
"@nx/nx-linux-x64-musl": "24.0.0-beta.0",
|
|
161
|
+
"@nx/nx-win32-arm64-msvc": "24.0.0-beta.0",
|
|
162
|
+
"@nx/nx-win32-x64-msvc": "24.0.0-beta.0"
|
|
172
163
|
},
|
|
173
164
|
"nx-migrations": {
|
|
174
165
|
"migrations": "./migrations.json",
|
package/readme-template.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
<p
|
|
1
|
+
<p align="center">
|
|
2
2
|
<picture>
|
|
3
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-
|
|
4
|
-
<img alt="Nx
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo-light.svg">
|
|
4
|
+
<img alt="Nx Logo" src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo.svg" width="140">
|
|
5
5
|
</picture>
|
|
6
6
|
</p>
|
|
7
7
|
|
package/schemas/nx-schema.json
CHANGED
|
@@ -1021,6 +1021,11 @@
|
|
|
1021
1021
|
"description": "Configuration for params handling.",
|
|
1022
1022
|
"enum": ["ignore", "forward"],
|
|
1023
1023
|
"default": "ignore"
|
|
1024
|
+
},
|
|
1025
|
+
"inputs": {
|
|
1026
|
+
"type": "boolean",
|
|
1027
|
+
"description": "Set to false to keep a continuous dependency's inputs out of this target's hash and affected calculation. Has no effect on dependencies that are not continuous.",
|
|
1028
|
+
"default": true
|
|
1024
1029
|
}
|
|
1025
1030
|
},
|
|
1026
1031
|
"oneOf": [
|
|
@@ -102,6 +102,11 @@
|
|
|
102
102
|
"description": "Configuration for params handling.",
|
|
103
103
|
"enum": ["ignore", "forward"],
|
|
104
104
|
"default": "ignore"
|
|
105
|
+
},
|
|
106
|
+
"inputs": {
|
|
107
|
+
"type": "boolean",
|
|
108
|
+
"description": "Set to false to keep a continuous dependency's inputs out of this target's hash and affected calculation. Has no effect on dependencies that are not continuous.",
|
|
109
|
+
"default": true
|
|
105
110
|
}
|
|
106
111
|
},
|
|
107
112
|
"oneOf": [
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { TargetDependencyConfig } from '../config/workspace-json-project-json';
|
|
2
|
-
type LegacyValue = 'self' | 'dependencies';
|
|
3
|
-
type LegacyEntry = TargetDependencyConfig & {
|
|
4
|
-
projects: LegacyValue;
|
|
5
|
-
};
|
|
6
|
-
export interface LegacyDependsOnViolation {
|
|
7
|
-
index: number;
|
|
8
|
-
originalEntry: LegacyEntry;
|
|
9
|
-
}
|
|
10
|
-
export interface LegacyDependsOnLocation {
|
|
11
|
-
ownerTarget?: string;
|
|
12
|
-
index?: number;
|
|
13
|
-
legacyViolations?: LegacyDependsOnViolation[];
|
|
14
|
-
}
|
|
15
|
-
export declare function warnLegacyDependsOnMagicString(currentProject: string | undefined, dependencyConfig: TargetDependencyConfig, location: LegacyDependsOnLocation | undefined): void;
|
|
16
|
-
export declare function flushLegacyDependsOnViolations(project: string, ownerTarget: string, violations: LegacyDependsOnViolation[], projectRoot: string | undefined): void;
|
|
17
|
-
export declare function __resetForTests(): void;
|
|
18
|
-
export {};
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.warnLegacyDependsOnMagicString = warnLegacyDependsOnMagicString;
|
|
4
|
-
exports.flushLegacyDependsOnViolations = flushLegacyDependsOnViolations;
|
|
5
|
-
exports.__resetForTests = __resetForTests;
|
|
6
|
-
const nx_deps_cache_1 = require("../project-graph/nx-deps-cache");
|
|
7
|
-
const source_maps_1 = require("../project-graph/utils/project-configuration/source-maps");
|
|
8
|
-
const output_1 = require("../utils/output");
|
|
9
|
-
const warned = new Set();
|
|
10
|
-
const isInternal = (p) => !p || p.startsWith('nx/');
|
|
11
|
-
// Callers gate this on `dependencyConfig.projects` already being a legacy value;
|
|
12
|
-
// the inner cast snapshots that runtime guarantee into the type system.
|
|
13
|
-
function warnLegacyDependsOnMagicString(currentProject, dependencyConfig, location) {
|
|
14
|
-
const violation = {
|
|
15
|
-
index: location?.index ?? -1,
|
|
16
|
-
originalEntry: { ...dependencyConfig },
|
|
17
|
-
};
|
|
18
|
-
// Collector-aware caller (`getDependencyConfigs`) batches violations so the
|
|
19
|
-
// warning can group all offending entries for a single target. External
|
|
20
|
-
// callers fall through to an immediate per-entry warning.
|
|
21
|
-
if (location?.legacyViolations)
|
|
22
|
-
return void location.legacyViolations.push(violation);
|
|
23
|
-
flushLegacyDependsOnViolations(currentProject ?? '<unknown>', location?.ownerTarget ?? '<unknown>', [violation], undefined);
|
|
24
|
-
}
|
|
25
|
-
function flushLegacyDependsOnViolations(project, ownerTarget, violations, projectRoot) {
|
|
26
|
-
if (violations.length === 0)
|
|
27
|
-
return;
|
|
28
|
-
// Read source maps fresh each flush so daemon-cached maps don't go stale;
|
|
29
|
-
// only runs when violations exist, which is rare.
|
|
30
|
-
let sourceMaps = null;
|
|
31
|
-
try {
|
|
32
|
-
sourceMaps = (0, nx_deps_cache_1.readSourceMapsCache)();
|
|
33
|
-
}
|
|
34
|
-
catch { } // best-effort context
|
|
35
|
-
const map = projectRoot && sourceMaps ? sourceMaps[projectRoot] : undefined;
|
|
36
|
-
const arrayKey = `targets.${ownerTarget}.dependsOn`;
|
|
37
|
-
const items = violations.map((v) => {
|
|
38
|
-
const info = map
|
|
39
|
-
? (0, source_maps_1.readArrayItemSourceInfo)(map, arrayKey, v.index)
|
|
40
|
-
: undefined;
|
|
41
|
-
return {
|
|
42
|
-
...v,
|
|
43
|
-
value: v.originalEntry.projects,
|
|
44
|
-
plugin: info?.[1],
|
|
45
|
-
file: info?.[0] ?? undefined,
|
|
46
|
-
};
|
|
47
|
-
});
|
|
48
|
-
const shared = (key) => items.every((i) => i[key] === items[0][key]) ? items[0][key] : null;
|
|
49
|
-
const value = shared('value');
|
|
50
|
-
const plugin = shared('plugin');
|
|
51
|
-
const file = shared('file');
|
|
52
|
-
// External-plugin warnings are workspace-wide (the plugin's behavior, not a
|
|
53
|
-
// specific config): dedupe per (plugin, value) so the user sees one warning
|
|
54
|
-
// per offending plugin, not one per affected target.
|
|
55
|
-
const dedupeKey = plugin && !isInternal(plugin) && value
|
|
56
|
-
? `plugin::${plugin}::${value}`
|
|
57
|
-
: `target::${project}::${ownerTarget}`;
|
|
58
|
-
if (warned.has(dedupeKey))
|
|
59
|
-
return;
|
|
60
|
-
warned.add(dedupeKey);
|
|
61
|
-
const n = items.length;
|
|
62
|
-
const word = n === 1 ? 'entry' : 'entries';
|
|
63
|
-
const deprecation = 'This is deprecated and will be removed in Nx v24 —';
|
|
64
|
-
let phrase;
|
|
65
|
-
if (value) {
|
|
66
|
-
phrase = `projects: '${value}'`;
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
const self = items.filter((i) => i.value === 'self').length;
|
|
70
|
-
phrase = `legacy projects values (${self} 'self', ${n - self} 'dependencies')`;
|
|
71
|
-
}
|
|
72
|
-
let title;
|
|
73
|
-
let suppressBody = false;
|
|
74
|
-
if (plugin && !isInternal(plugin)) {
|
|
75
|
-
// Single external plugin: same plugin emits the same value across projects.
|
|
76
|
-
title = `The ${plugin} plugin infers dependsOn entries using ${phrase}. ${deprecation} please upgrade ${plugin} to a version that doesn't emit this.`;
|
|
77
|
-
suppressBody = true;
|
|
78
|
-
}
|
|
79
|
-
else if (plugin && isInternal(plugin) && file) {
|
|
80
|
-
// Single hand-authored config file — lead with the file path.
|
|
81
|
-
title = `${file} defines ${project}:${ownerTarget} with ${n} dependsOn ${word} using ${phrase}. ${deprecation} run 'nx repair' to fix this.`;
|
|
82
|
-
}
|
|
83
|
-
else {
|
|
84
|
-
// Mixed sources or no source-map info — tailor advice to what's offending.
|
|
85
|
-
const offending = Array.from(new Set(items
|
|
86
|
-
.filter((i) => i.plugin && !isInternal(i.plugin))
|
|
87
|
-
.map((i) => i.plugin)));
|
|
88
|
-
const origin = plugin
|
|
89
|
-
? ` (set by ${plugin}${file ? ` in ${file}` : ''})`
|
|
90
|
-
: '';
|
|
91
|
-
const advice = offending.length
|
|
92
|
-
? `run 'nx repair' for hand-authored entries and upgrade ${offending.join(', ')} for plugin-inferred entries`
|
|
93
|
-
: `run 'nx repair' to fix`;
|
|
94
|
-
title = `${project}:${ownerTarget} has ${n} dependsOn ${word} using ${phrase}${origin}. ${deprecation} ${advice}.`;
|
|
95
|
-
}
|
|
96
|
-
const bodyLines = suppressBody
|
|
97
|
-
? []
|
|
98
|
-
: items.map((i) => {
|
|
99
|
-
const src = i.plugin && !plugin
|
|
100
|
-
? ` from ${i.plugin}${i.file ? ` in ${i.file}` : ''}`
|
|
101
|
-
: '';
|
|
102
|
-
return ` - ${JSON.stringify(i.originalEntry)} (${i.index}${src})`;
|
|
103
|
-
});
|
|
104
|
-
output_1.output.warn({ title, bodyLines });
|
|
105
|
-
}
|
|
106
|
-
// Test-only: clears the process-wide dedupe set.
|
|
107
|
-
function __resetForTests() {
|
|
108
|
-
warned.clear();
|
|
109
|
-
}
|