nx 23.1.0 → 23.1.1
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/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 +8 -1
- 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 +1 -1
- 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/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 +1 -45
- package/dist/src/command-line/migrate/migrate.js +33 -376
- 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/utils/git.js +6 -2
- package/dist/src/command-line/release/utils/release-graph.d.ts +2 -2
- package/dist/src/command-line/release/utils/remote-release-clients/github.js +1 -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/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/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/daemon/client/client.d.ts +0 -2
- package/dist/src/daemon/client/client.js +17 -19
- package/dist/src/daemon/server/handle-tasks-execution-hooks.d.ts +1 -1
- package/dist/src/daemon/server/server.js +7 -4
- package/dist/src/devkit-internals.d.ts +3 -0
- package/dist/src/devkit-internals.js +10 -1
- 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/native/index.d.ts +21 -2
- package/dist/src/native/native-bindings.js +2 -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/plugins/js/lock-file/npm-parser.js +71 -27
- package/dist/src/plugins/js/lock-file/pnpm-parser.js +50 -17
- package/dist/src/plugins/js/lock-file/project-graph-pruning.js +1 -1
- 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/build-dependencies/target-project-locator.js +12 -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/build-project-graph.js +7 -1
- package/dist/src/project-graph/error-types.js +41 -1
- package/dist/src/project-graph/file-utils.js +6 -1
- package/dist/src/project-graph/plugins/isolation/isolated-plugin.js +4 -0
- 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 +3 -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 +11 -14
- 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 +16 -3
- 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 +26 -2
- package/dist/src/tasks-runner/task-orchestrator.d.ts +4 -1
- package/dist/src/tasks-runner/task-orchestrator.js +23 -10
- 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/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/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/min-release-age/behavior/pnpm.js +9 -7
- package/dist/src/utils/package-json.js +11 -7
- package/dist/src/utils/package-manager.d.ts +3 -1
- package/dist/src/utils/package-manager.js +28 -4
- package/dist/src/utils/provenance.js +12 -2
- package/dist/src/utils/workspace-id.d.ts +20 -0
- package/dist/src/utils/workspace-id.js +54 -0
- package/migrations.json +7 -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
|
@@ -4,6 +4,10 @@ exports.GitRepository = void 0;
|
|
|
4
4
|
exports.cloneFromUpstream = cloneFromUpstream;
|
|
5
5
|
exports.parseVcsRemoteUrl = parseVcsRemoteUrl;
|
|
6
6
|
exports.getVcsRemoteInfo = getVcsRemoteInfo;
|
|
7
|
+
exports.getGitRootPath = getGitRootPath;
|
|
8
|
+
exports.getGitRootRelativePath = getGitRootRelativePath;
|
|
9
|
+
exports.isShallowRepository = isShallowRepository;
|
|
10
|
+
exports.getFirstCommitSha = getFirstCommitSha;
|
|
7
11
|
exports.isGitRepository = isGitRepository;
|
|
8
12
|
exports.hasUncommittedChanges = hasUncommittedChanges;
|
|
9
13
|
exports.getUncommittedChangesSnapshot = getUncommittedChangesSnapshot;
|
|
@@ -16,9 +20,9 @@ const crypto = tslib_1.__importStar(require("crypto"));
|
|
|
16
20
|
const fs = tslib_1.__importStar(require("fs"));
|
|
17
21
|
const path_1 = require("path");
|
|
18
22
|
const logger_1 = require("./logger");
|
|
19
|
-
function
|
|
23
|
+
function execFileAsync(file, args, execOptions) {
|
|
20
24
|
return new Promise((res, rej) => {
|
|
21
|
-
(0, child_process_1.
|
|
25
|
+
(0, child_process_1.execFile)(file, args, { ...execOptions, windowsHide: true }, (err, stdout) => {
|
|
22
26
|
if (err) {
|
|
23
27
|
return rej(err);
|
|
24
28
|
}
|
|
@@ -29,7 +33,14 @@ function execAsync(command, execOptions) {
|
|
|
29
33
|
async function cloneFromUpstream(url, destination, { originName, depth } = {
|
|
30
34
|
originName: 'origin',
|
|
31
35
|
}) {
|
|
32
|
-
await
|
|
36
|
+
await execFileAsync('git', [
|
|
37
|
+
'clone',
|
|
38
|
+
url,
|
|
39
|
+
destination,
|
|
40
|
+
...(depth ? ['--depth', `${depth}`] : []),
|
|
41
|
+
'--origin',
|
|
42
|
+
originName,
|
|
43
|
+
], {
|
|
33
44
|
cwd: (0, path_1.dirname)(destination),
|
|
34
45
|
maxBuffer: 10 * 1024 * 1024,
|
|
35
46
|
});
|
|
@@ -41,25 +52,25 @@ class GitRepository {
|
|
|
41
52
|
this.root = this.getGitRootPath(this.directory);
|
|
42
53
|
}
|
|
43
54
|
getGitRootPath(cwd) {
|
|
44
|
-
return (
|
|
45
|
-
cwd,
|
|
46
|
-
windowsHide: true,
|
|
47
|
-
})
|
|
48
|
-
.toString()
|
|
49
|
-
.trim();
|
|
55
|
+
return getGitRootPath(cwd);
|
|
50
56
|
}
|
|
51
57
|
async hasUncommittedChanges() {
|
|
52
|
-
const data = await this.
|
|
58
|
+
const data = await this.execGit(['status', '--porcelain']);
|
|
53
59
|
return data.trim() !== '';
|
|
54
60
|
}
|
|
55
61
|
async addFetchRemote(remoteName, branch) {
|
|
56
|
-
return await this.
|
|
62
|
+
return await this.execGit([
|
|
63
|
+
'config',
|
|
64
|
+
'--add',
|
|
65
|
+
`remote.${remoteName}.fetch`,
|
|
66
|
+
`+refs/heads/${branch}:refs/remotes/${remoteName}/${branch}`,
|
|
67
|
+
]);
|
|
57
68
|
}
|
|
58
69
|
async showStat() {
|
|
59
|
-
return await this.
|
|
70
|
+
return await this.execGit(['show', '--stat']);
|
|
60
71
|
}
|
|
61
72
|
async listBranches() {
|
|
62
|
-
return (await this.
|
|
73
|
+
return (await this.execGit(['ls-remote', '--heads', '--quiet']))
|
|
63
74
|
.trim()
|
|
64
75
|
.split('\n')
|
|
65
76
|
.map((s) => s
|
|
@@ -70,45 +81,58 @@ class GitRepository {
|
|
|
70
81
|
async getGitFiles(path) {
|
|
71
82
|
// Use -z to return file names exactly as they are stored in git, separated by NULL (\x00) character.
|
|
72
83
|
// This avoids problems with special characters in file names.
|
|
73
|
-
return (await this.
|
|
84
|
+
return (await this.execGit(['ls-files', '-z', '--', path]))
|
|
74
85
|
.trim()
|
|
75
86
|
.split('\x00')
|
|
76
87
|
.map((s) => s.trim())
|
|
77
88
|
.filter(Boolean);
|
|
78
89
|
}
|
|
79
90
|
async reset(ref) {
|
|
80
|
-
return await this.
|
|
91
|
+
return await this.execGit(['reset', '--hard', ref]);
|
|
81
92
|
}
|
|
82
93
|
async mergeUnrelatedHistories(ref, message) {
|
|
83
|
-
return await this.
|
|
94
|
+
return await this.execGit([
|
|
95
|
+
'merge',
|
|
96
|
+
ref,
|
|
97
|
+
'-X',
|
|
98
|
+
'ours',
|
|
99
|
+
'--allow-unrelated-histories',
|
|
100
|
+
'-m',
|
|
101
|
+
message,
|
|
102
|
+
]);
|
|
84
103
|
}
|
|
85
104
|
async fetch(remote, ref) {
|
|
86
|
-
return await this.
|
|
105
|
+
return await this.execGit(['fetch', remote, ...(ref ? [ref] : [])]);
|
|
87
106
|
}
|
|
88
107
|
async checkout(branch, opts) {
|
|
89
|
-
return await this.
|
|
108
|
+
return await this.execGit([
|
|
109
|
+
'checkout',
|
|
110
|
+
...(opts.new ? ['-b'] : []),
|
|
111
|
+
branch,
|
|
112
|
+
...(opts.base ? [opts.base] : []),
|
|
113
|
+
]);
|
|
90
114
|
}
|
|
91
115
|
async move(path, destination) {
|
|
92
|
-
return await this.
|
|
116
|
+
return await this.execGit(['mv', '--', path, destination]);
|
|
93
117
|
}
|
|
94
118
|
async push(ref, remoteName) {
|
|
95
|
-
return await this.
|
|
119
|
+
return await this.execGit(['push', '-u', '-f', remoteName, ref]);
|
|
96
120
|
}
|
|
97
121
|
async commit(message) {
|
|
98
|
-
return await this.
|
|
122
|
+
return await this.execGit(['commit', '-am', message]);
|
|
99
123
|
}
|
|
100
124
|
async amendCommit() {
|
|
101
|
-
return await this.
|
|
125
|
+
return await this.execGit(['commit', '--amend', '-a', '--no-edit']);
|
|
102
126
|
}
|
|
103
127
|
async deleteGitRemote(name) {
|
|
104
|
-
return await this.
|
|
128
|
+
return await this.execGit(['remote', 'rm', name]);
|
|
105
129
|
}
|
|
106
130
|
async addGitRemote(name, url) {
|
|
107
|
-
return await this.
|
|
131
|
+
return await this.execGit(['remote', 'add', name, url]);
|
|
108
132
|
}
|
|
109
133
|
async hasFilterRepoInstalled() {
|
|
110
134
|
try {
|
|
111
|
-
await this.
|
|
135
|
+
await this.execGit(['filter-repo', '--help']);
|
|
112
136
|
return true;
|
|
113
137
|
}
|
|
114
138
|
catch {
|
|
@@ -121,35 +145,57 @@ class GitRepository {
|
|
|
121
145
|
// NOTE: filter-repo requires POSIX path to work
|
|
122
146
|
const sourcePosixPath = source.split(path_1.sep).join(path_1.posix.sep);
|
|
123
147
|
const destinationPosixPath = destination.split(path_1.sep).join(path_1.posix.sep);
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
148
|
+
const sourcePath = ensureTrailingSlash(sourcePosixPath);
|
|
149
|
+
const destinationPath = ensureTrailingSlash(destinationPosixPath);
|
|
150
|
+
await this.execGit([
|
|
151
|
+
'filter-repo',
|
|
152
|
+
'-f',
|
|
153
|
+
...(source !== '' ? ['--path', sourcePosixPath] : []),
|
|
154
|
+
...(source !== destination
|
|
155
|
+
? ['--path-rename', `${sourcePath}:${destinationPath}`]
|
|
156
|
+
: []),
|
|
157
|
+
]);
|
|
127
158
|
}
|
|
128
159
|
async filterBranch(source, destination, branchName) {
|
|
129
160
|
// We need non-ASCII file names to not be quoted, or else filter-branch will exclude them.
|
|
130
|
-
await this.
|
|
161
|
+
await this.execGit(['config', 'core.quotepath', 'false']);
|
|
131
162
|
// NOTE: filter-repo requires POSIX path to work
|
|
132
163
|
const sourcePosixPath = source.split(path_1.sep).join(path_1.posix.sep);
|
|
133
164
|
const destinationPosixPath = destination.split(path_1.sep).join(path_1.posix.sep);
|
|
134
165
|
// First, if the source is not a root project, then only include commits relevant to the subdirectory.
|
|
135
166
|
if (source !== '') {
|
|
136
|
-
const indexFilterCommand =
|
|
137
|
-
await this.
|
|
167
|
+
const indexFilterCommand = `node ${quoteForShell((0, path_1.join)(__dirname, 'git-utils.index-filter.js'))}`;
|
|
168
|
+
await this.execGit([
|
|
169
|
+
'filter-branch',
|
|
170
|
+
'-f',
|
|
171
|
+
'--index-filter',
|
|
172
|
+
indexFilterCommand,
|
|
173
|
+
'--prune-empty',
|
|
174
|
+
'--',
|
|
175
|
+
branchName,
|
|
176
|
+
], {
|
|
138
177
|
NX_IMPORT_SOURCE: sourcePosixPath,
|
|
139
178
|
NX_IMPORT_DESTINATION: destinationPosixPath,
|
|
140
179
|
});
|
|
141
180
|
}
|
|
142
181
|
// Then, move files to their new location if necessary.
|
|
143
182
|
if (source === '' || source !== destination) {
|
|
144
|
-
const treeFilterCommand =
|
|
145
|
-
await this.
|
|
183
|
+
const treeFilterCommand = `node ${quoteForShell((0, path_1.join)(__dirname, 'git-utils.tree-filter.js'))}`;
|
|
184
|
+
await this.execGit([
|
|
185
|
+
'filter-branch',
|
|
186
|
+
'-f',
|
|
187
|
+
'--tree-filter',
|
|
188
|
+
treeFilterCommand,
|
|
189
|
+
'--',
|
|
190
|
+
branchName,
|
|
191
|
+
], {
|
|
146
192
|
NX_IMPORT_SOURCE: sourcePosixPath,
|
|
147
193
|
NX_IMPORT_DESTINATION: destinationPosixPath,
|
|
148
194
|
});
|
|
149
195
|
}
|
|
150
196
|
}
|
|
151
|
-
|
|
152
|
-
return
|
|
197
|
+
execGit(args, env) {
|
|
198
|
+
return execFileAsync('git', args, {
|
|
153
199
|
cwd: this.root,
|
|
154
200
|
maxBuffer: 10 * 1024 * 1024,
|
|
155
201
|
env: {
|
|
@@ -158,25 +204,14 @@ class GitRepository {
|
|
|
158
204
|
},
|
|
159
205
|
});
|
|
160
206
|
}
|
|
161
|
-
quotePath(path, ensureTrailingSlash) {
|
|
162
|
-
return this.quoteArg(ensureTrailingSlash && path !== '' && !path.endsWith('/')
|
|
163
|
-
? `${path}/`
|
|
164
|
-
: path);
|
|
165
|
-
}
|
|
166
|
-
quoteArg(arg) {
|
|
167
|
-
return process.platform === 'win32'
|
|
168
|
-
? // Windows/CMD only understands double-quotes, single-quotes are treated as part of the file name
|
|
169
|
-
// Bash and other shells will substitute `$` in file names with a variable value.
|
|
170
|
-
`"${arg
|
|
171
|
-
// Need to keep two slashes for Windows or else the path will be invalid.
|
|
172
|
-
// e.g. 'C:\Users\bob\projects\repo' is invalid, but 'C:\\Users\\bob\\projects\\repo' is valid
|
|
173
|
-
.replaceAll('\\', '\\\\')}"`
|
|
174
|
-
: // e.g. `git mv "$$file.txt" "libs/a/$$file.txt"` will not work since `$$` is swapped with the PID of the last process.
|
|
175
|
-
// Using single-quotes prevents this substitution.
|
|
176
|
-
`'${arg}'`;
|
|
177
|
-
}
|
|
178
207
|
}
|
|
179
208
|
exports.GitRepository = GitRepository;
|
|
209
|
+
function ensureTrailingSlash(path) {
|
|
210
|
+
return path !== '' && !path.endsWith('/') ? `${path}/` : path;
|
|
211
|
+
}
|
|
212
|
+
function quoteForShell(arg) {
|
|
213
|
+
return `'${arg.replaceAll("'", "'\"'\"'")}'`;
|
|
214
|
+
}
|
|
180
215
|
function parseVcsRemoteUrl(url) {
|
|
181
216
|
// Remove whitespace and handle common URL formats
|
|
182
217
|
const cleanUrl = url.trim();
|
|
@@ -260,6 +295,65 @@ function getVcsRemoteInfo(directory) {
|
|
|
260
295
|
return null;
|
|
261
296
|
}
|
|
262
297
|
}
|
|
298
|
+
function getGitRootPath(cwd) {
|
|
299
|
+
return (0, child_process_1.execFileSync)('git', ['rev-parse', '--show-toplevel'], {
|
|
300
|
+
cwd,
|
|
301
|
+
windowsHide: true,
|
|
302
|
+
})
|
|
303
|
+
.toString()
|
|
304
|
+
.trim();
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Path of `directory` relative to its git root, posix-separated so it is
|
|
308
|
+
* identical on every OS, and '' when the directory is the git root itself.
|
|
309
|
+
* Null outside a git repository.
|
|
310
|
+
*/
|
|
311
|
+
function getGitRootRelativePath(directory) {
|
|
312
|
+
try {
|
|
313
|
+
return (0, path_1.relative)(getGitRootPath(directory), directory)
|
|
314
|
+
.split(path_1.sep)
|
|
315
|
+
.join(path_1.posix.sep);
|
|
316
|
+
}
|
|
317
|
+
catch {
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
/** A shallow clone's truncated history has no stable root commit. */
|
|
322
|
+
function isShallowRepository(directory) {
|
|
323
|
+
try {
|
|
324
|
+
return ((0, child_process_1.execFileSync)('git', ['rev-parse', '--is-shallow-repository'], {
|
|
325
|
+
encoding: 'utf8',
|
|
326
|
+
stdio: 'pipe',
|
|
327
|
+
cwd: directory,
|
|
328
|
+
windowsHide: true,
|
|
329
|
+
}).trim() === 'true');
|
|
330
|
+
}
|
|
331
|
+
catch {
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* SHA of the repository's first commit. Merged unrelated histories leave
|
|
337
|
+
* several root commits — the sorted-first one is picked so every clone
|
|
338
|
+
* agrees. Null when there are no commits, or outside a git repository.
|
|
339
|
+
*/
|
|
340
|
+
function getFirstCommitSha(directory) {
|
|
341
|
+
try {
|
|
342
|
+
const roots = (0, child_process_1.execFileSync)('git', ['rev-list', '--max-parents=0', 'HEAD'], {
|
|
343
|
+
encoding: 'utf8',
|
|
344
|
+
stdio: 'pipe',
|
|
345
|
+
cwd: directory,
|
|
346
|
+
windowsHide: true,
|
|
347
|
+
})
|
|
348
|
+
.trim()
|
|
349
|
+
.split(/\r?\n/)
|
|
350
|
+
.filter(Boolean);
|
|
351
|
+
return roots.sort()[0] ?? null;
|
|
352
|
+
}
|
|
353
|
+
catch {
|
|
354
|
+
return null;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
263
357
|
function isGitRepository(directory) {
|
|
264
358
|
try {
|
|
265
359
|
(0, child_process_1.execSync)('git rev-parse --is-inside-work-tree', {
|
|
@@ -88,15 +88,17 @@ function readPnpmConfigList(root) {
|
|
|
88
88
|
return null;
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
|
-
// Extracts the cooldown keys from pnpm's reported config. pnpm reports
|
|
92
|
-
//
|
|
93
|
-
//
|
|
91
|
+
// Extracts the cooldown keys from pnpm's reported config. pnpm 11 reports them
|
|
92
|
+
// camelCase; pnpm 10 reported them kebab-case, so read both forms. The exclude
|
|
93
|
+
// list comes back as a JSON array (set in a yaml surface) or a comma-joined
|
|
94
|
+
// string (set via .npmrc / env).
|
|
94
95
|
function parseCooldownConfig(config) {
|
|
96
|
+
const read = (camelKey, kebabKey) => config[camelKey] ?? config[kebabKey];
|
|
95
97
|
return {
|
|
96
|
-
windowMinutes: toNumber(
|
|
97
|
-
excludes: parseExcludeValue(
|
|
98
|
-
strictExplicit: toBoolean(
|
|
99
|
-
ignoreMissingTimeExplicit: toBoolean(
|
|
98
|
+
windowMinutes: toNumber(read('minimumReleaseAge', 'minimum-release-age')) ?? undefined,
|
|
99
|
+
excludes: parseExcludeValue(read('minimumReleaseAgeExclude', 'minimum-release-age-exclude')),
|
|
100
|
+
strictExplicit: toBoolean(read('minimumReleaseAgeStrict', 'minimum-release-age-strict')),
|
|
101
|
+
ignoreMissingTimeExplicit: toBoolean(read('minimumReleaseAgeIgnoreMissingTime', 'minimum-release-age-ignore-missing-time')),
|
|
100
102
|
};
|
|
101
103
|
}
|
|
102
104
|
function parseExcludeValue(value) {
|
|
@@ -225,19 +225,23 @@ function preparePackageInstallation(pkg, requiredVersion, packageManager) {
|
|
|
225
225
|
// it into the temp dir, so the `-w` here resolves to the temp dir.
|
|
226
226
|
const pmCommands = (0, package_manager_1.getPackageManagerCommand)(packageManager);
|
|
227
227
|
const preInstallCommand = pmCommands.preInstall;
|
|
228
|
-
//
|
|
228
|
+
// Keep peer dependencies out of the temp install. `ensurePackage` puts the
|
|
229
229
|
// workspace's `node_modules` on `NODE_PATH`, so a loaded package resolves its
|
|
230
230
|
// peers from the workspace instead of pulling its own (possibly incompatible)
|
|
231
231
|
// copies into the temp dir.
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
232
|
+
//
|
|
233
|
+
// npm needs `--legacy-peer-deps` rather than `--omit=peer`: npm marks a package
|
|
234
|
+
// as a peer if anything in the tree peer-depends on it, so `--omit=peer` also
|
|
235
|
+
// prunes packages that are real dependencies. Bun's `--omit=peer` does not.
|
|
236
|
+
const skipPeerDependenciesFlags = {
|
|
237
|
+
npm: '--legacy-peer-deps',
|
|
238
|
+
bun: '--omit=peer',
|
|
239
|
+
pnpm: '--config.auto-install-peers=false',
|
|
240
|
+
};
|
|
237
241
|
const installCommand = [
|
|
238
242
|
pmCommands.addDev,
|
|
239
243
|
`${pkg}@${requiredVersion}`,
|
|
240
|
-
|
|
244
|
+
skipPeerDependenciesFlags[packageManager],
|
|
241
245
|
pmCommands.ignoreScriptsFlag,
|
|
242
246
|
]
|
|
243
247
|
.filter(Boolean)
|
|
@@ -121,7 +121,9 @@ export declare function resolvePackageVersionUsingInstallation(packageName: stri
|
|
|
121
121
|
export declare function packageRegistryView(pkg: string, version: string, args: string, options?: {
|
|
122
122
|
forceNpm?: boolean;
|
|
123
123
|
}): Promise<string>;
|
|
124
|
-
export declare function packageRegistryPack(cwd: string, pkg: string, version: string
|
|
124
|
+
export declare function packageRegistryPack(cwd: string, pkg: string, version: string, options?: {
|
|
125
|
+
bypassMinReleaseAge?: boolean;
|
|
126
|
+
}): Promise<{
|
|
125
127
|
tarballPath: string;
|
|
126
128
|
}>;
|
|
127
129
|
/**
|
|
@@ -165,8 +165,12 @@ function getPackageManagerCommand(packageManager = detectPackageManager(), root
|
|
|
165
165
|
install: 'pnpm install --no-frozen-lockfile', // explicitly disable in case of CI
|
|
166
166
|
ciInstall: 'pnpm install --frozen-lockfile',
|
|
167
167
|
updateLockFile: 'pnpm install --lockfile-only',
|
|
168
|
-
add: isPnpmWorkspace
|
|
169
|
-
|
|
168
|
+
add: isPnpmWorkspace
|
|
169
|
+
? 'pnpm add -w --config.frozen-lockfile=false'
|
|
170
|
+
: 'pnpm add --config.frozen-lockfile=false',
|
|
171
|
+
addDev: isPnpmWorkspace
|
|
172
|
+
? 'pnpm add -Dw --config.frozen-lockfile=false'
|
|
173
|
+
: 'pnpm add -D --config.frozen-lockfile=false',
|
|
170
174
|
rm: 'pnpm rm',
|
|
171
175
|
exec: modernPnpm ? 'pnpm exec' : 'pnpx',
|
|
172
176
|
dlx: modernPnpm ? 'pnpm dlx' : 'pnpx',
|
|
@@ -345,6 +349,20 @@ function modifyPnpmWorkspaceYamlToFitNewDirectory(contents) {
|
|
|
345
349
|
doc.set('packages', ['.']);
|
|
346
350
|
// Relative patch paths don't resolve in the temp dir.
|
|
347
351
|
doc.delete('patchedDependencies');
|
|
352
|
+
// link:/file: overrides (e.g. written by `pnpm link`) point at paths that
|
|
353
|
+
// don't exist in the temp dir, and an override would hijack an exact-version
|
|
354
|
+
// add (`pnpm add pkg@x.y.z` would install the linked dir instead).
|
|
355
|
+
const overrides = doc.toJS()?.overrides;
|
|
356
|
+
if (overrides && typeof overrides === 'object') {
|
|
357
|
+
for (const [name, spec] of Object.entries(overrides)) {
|
|
358
|
+
if (typeof spec === 'string' && /^(link|file):/.test(spec)) {
|
|
359
|
+
doc.deleteIn(['overrides', name]);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
if (Object.keys(doc.toJS()?.overrides ?? {}).length === 0) {
|
|
363
|
+
doc.delete('overrides');
|
|
364
|
+
}
|
|
365
|
+
}
|
|
348
366
|
return doc.toString();
|
|
349
367
|
}
|
|
350
368
|
function copyPackageManagerConfigurationFiles(root, destination) {
|
|
@@ -515,7 +533,7 @@ options) {
|
|
|
515
533
|
});
|
|
516
534
|
return stdout.toString().trim();
|
|
517
535
|
}
|
|
518
|
-
async function packageRegistryPack(cwd, pkg, version) {
|
|
536
|
+
async function packageRegistryPack(cwd, pkg, version, options) {
|
|
519
537
|
/**
|
|
520
538
|
* Only `npm pack` supports downloading a tarball of a specified remote
|
|
521
539
|
* package. `yarn` packs the active workspace, `pnpm pack` only packs
|
|
@@ -529,7 +547,13 @@ async function packageRegistryPack(cwd, pkg, version) {
|
|
|
529
547
|
windowsHide: true,
|
|
530
548
|
// npm enforces `devEngines.packageManager` even on `pack`; force keeps the
|
|
531
549
|
// download working in workspaces that pin a non-npm manager (onFail: error).
|
|
532
|
-
env: {
|
|
550
|
+
env: {
|
|
551
|
+
...process.env,
|
|
552
|
+
npm_config_force: 'true',
|
|
553
|
+
...(options?.bypassMinReleaseAge
|
|
554
|
+
? { npm_config_min_release_age: '0' }
|
|
555
|
+
: {}),
|
|
556
|
+
},
|
|
533
557
|
});
|
|
534
558
|
const tarballPath = stdout.trim();
|
|
535
559
|
return { tarballPath };
|
|
@@ -22,8 +22,18 @@ async function ensurePackageHasProvenance(packageName, packageVersion) {
|
|
|
22
22
|
}
|
|
23
23
|
try {
|
|
24
24
|
const result = await (0, package_manager_1.packageRegistryView)(packageName, packageVersion, '--json --silent');
|
|
25
|
-
const
|
|
26
|
-
|
|
25
|
+
const parsed = JSON.parse(result);
|
|
26
|
+
// `npm view <pkg>@<spec> --json` returns a bare object on npm <= 11 but an
|
|
27
|
+
// array on npm 12 and pnpm, even for a single resolved version. A version
|
|
28
|
+
// range matches several versions and the registry lists all of them
|
|
29
|
+
// (including deprecated ones the installer skips), so we cannot tell which
|
|
30
|
+
// one will actually be installed; refuse rather than verify the wrong
|
|
31
|
+
// artifact.
|
|
32
|
+
if (Array.isArray(parsed) && parsed.length > 1) {
|
|
33
|
+
throw new ProvenanceError(packageName, packageVersion, 'Provenance can only be verified for a single version, but this version resolved to multiple candidates. Specify an exact version.');
|
|
34
|
+
}
|
|
35
|
+
const npmViewResult = Array.isArray(parsed) ? parsed[0] : parsed;
|
|
36
|
+
const attURL = npmViewResult?.dist?.attestations?.url;
|
|
27
37
|
if (!attURL)
|
|
28
38
|
throw new ProvenanceError(packageName, packageVersion, 'No attestation URL found');
|
|
29
39
|
const response = await fetch(attURL);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { NxJsonConfiguration } from '../config/nx-json';
|
|
2
|
+
/**
|
|
3
|
+
* The workspace's analytics identity: the Nx Cloud id when the workspace has
|
|
4
|
+
* one (most stable — it survives repo moves and renames), else the repo key.
|
|
5
|
+
* Null when neither is available, in which case nothing is reported.
|
|
6
|
+
*/
|
|
7
|
+
export declare function generateWorkspaceId(root: string, nxJson: NxJsonConfiguration | null): string | null;
|
|
8
|
+
/**
|
|
9
|
+
* Derive the stable, unsalted key identifying this workspace in the
|
|
10
|
+
* repoTelemetry registry: `sha256(<repo identity> + '#' + <workspace path
|
|
11
|
+
* relative to the git root>)`.
|
|
12
|
+
*
|
|
13
|
+
* The repo identity is the normalized `domain/slug` from the git remote
|
|
14
|
+
* (protocol-independent: ssh, https, and token-authenticated URLs of the
|
|
15
|
+
* same repo produce the same key), falling back to the first-commit SHA
|
|
16
|
+
* when no remote exists. Returns null when no identity is derivable — not
|
|
17
|
+
* a git repository, or a shallow clone without a remote.
|
|
18
|
+
*/
|
|
19
|
+
export declare function deriveRepoKey(directory: string): string | null;
|
|
20
|
+
export declare function computeRepoKey(identity: string, relativePath: string): string;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateWorkspaceId = generateWorkspaceId;
|
|
4
|
+
exports.deriveRepoKey = deriveRepoKey;
|
|
5
|
+
exports.computeRepoKey = computeRepoKey;
|
|
6
|
+
const crypto_1 = require("crypto");
|
|
7
|
+
const git_utils_1 = require("./git-utils");
|
|
8
|
+
/**
|
|
9
|
+
* The workspace's analytics identity: the Nx Cloud id when the workspace has
|
|
10
|
+
* one (most stable — it survives repo moves and renames), else the repo key.
|
|
11
|
+
* Null when neither is available, in which case nothing is reported.
|
|
12
|
+
*/
|
|
13
|
+
function generateWorkspaceId(root, nxJson) {
|
|
14
|
+
const nxCloudId = nxJson?.nxCloudId ?? nxJson?.nxCloudAccessToken;
|
|
15
|
+
if (nxCloudId) {
|
|
16
|
+
return nxCloudId;
|
|
17
|
+
}
|
|
18
|
+
return deriveRepoKey(root);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Derive the stable, unsalted key identifying this workspace in the
|
|
22
|
+
* repoTelemetry registry: `sha256(<repo identity> + '#' + <workspace path
|
|
23
|
+
* relative to the git root>)`.
|
|
24
|
+
*
|
|
25
|
+
* The repo identity is the normalized `domain/slug` from the git remote
|
|
26
|
+
* (protocol-independent: ssh, https, and token-authenticated URLs of the
|
|
27
|
+
* same repo produce the same key), falling back to the first-commit SHA
|
|
28
|
+
* when no remote exists. Returns null when no identity is derivable — not
|
|
29
|
+
* a git repository, or a shallow clone without a remote.
|
|
30
|
+
*/
|
|
31
|
+
function deriveRepoKey(directory) {
|
|
32
|
+
const identity = getRepoIdentity(directory);
|
|
33
|
+
if (!identity) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
return computeRepoKey(identity, (0, git_utils_1.getGitRootRelativePath)(directory) ?? '');
|
|
37
|
+
}
|
|
38
|
+
function computeRepoKey(identity, relativePath) {
|
|
39
|
+
return (0, crypto_1.createHash)('sha256')
|
|
40
|
+
.update(`${identity}#${relativePath}`)
|
|
41
|
+
.digest('hex');
|
|
42
|
+
}
|
|
43
|
+
function getRepoIdentity(directory) {
|
|
44
|
+
const remote = (0, git_utils_1.getVcsRemoteInfo)(directory);
|
|
45
|
+
if (remote) {
|
|
46
|
+
// Hosts route case-insensitively and hold one canonical casing, so a
|
|
47
|
+
// hand-typed remote must key the same as the canonical one the claim
|
|
48
|
+
// flow derives from the host's API.
|
|
49
|
+
return `${remote.domain}/${remote.slug}`.toLowerCase().replace(/\/+$/, '');
|
|
50
|
+
}
|
|
51
|
+
// Without a remote the first commit is the only stable identity, and a
|
|
52
|
+
// shallow clone doesn't have a real one.
|
|
53
|
+
return (0, git_utils_1.isShallowRepository)(directory) ? null : (0, git_utils_1.getFirstCommitSha)(directory);
|
|
54
|
+
}
|
package/migrations.json
CHANGED
|
@@ -160,7 +160,13 @@
|
|
|
160
160
|
"cli": "nx",
|
|
161
161
|
"version": "22.6.0-rc.0",
|
|
162
162
|
"description": "Adds .claude/settings.local.json to .gitignore",
|
|
163
|
-
"implementation": "./dist/src/migrations/update-
|
|
163
|
+
"implementation": "./dist/src/migrations/update-22-6-0/add-claude-settings-local-to-git-ignore"
|
|
164
|
+
},
|
|
165
|
+
"22-6-0-enable-analytics-prompt": {
|
|
166
|
+
"cli": "nx",
|
|
167
|
+
"version": "22.6.0-beta.11",
|
|
168
|
+
"description": "Prompts to enable usage analytics",
|
|
169
|
+
"implementation": "./dist/src/migrations/update-22-6-0/enable-analytics-prompt"
|
|
164
170
|
},
|
|
165
171
|
"22-7-0-add-self-healing-to-gitignore": {
|
|
166
172
|
"cli": "nx",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nx",
|
|
3
|
-
"version": "23.1.
|
|
3
|
+
"version": "23.1.1",
|
|
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.",
|
|
@@ -61,12 +61,13 @@
|
|
|
61
61
|
"ansi-styles": "4.3.0",
|
|
62
62
|
"argparse": "2.0.1",
|
|
63
63
|
"asynckit": "0.4.0",
|
|
64
|
-
"axios": "1.
|
|
64
|
+
"axios": "1.18.1",
|
|
65
65
|
"balanced-match": "4.0.3",
|
|
66
66
|
"base64-js": "1.5.1",
|
|
67
67
|
"bl": "4.1.0",
|
|
68
|
-
"brace-expansion": "5.0.
|
|
68
|
+
"brace-expansion": "5.0.8",
|
|
69
69
|
"buffer": "5.7.1",
|
|
70
|
+
"bundle-name": "4.1.0",
|
|
70
71
|
"call-bind-apply-helpers": "1.0.2",
|
|
71
72
|
"chalk": "4.1.2",
|
|
72
73
|
"cli-cursor": "3.1.0",
|
|
@@ -77,8 +78,10 @@
|
|
|
77
78
|
"color-name": "1.1.4",
|
|
78
79
|
"combined-stream": "1.0.8",
|
|
79
80
|
"debug": "4.4.3",
|
|
81
|
+
"default-browser": "5.2.1",
|
|
82
|
+
"default-browser-id": "5.0.0",
|
|
80
83
|
"defaults": "1.0.4",
|
|
81
|
-
"define-lazy-prop": "
|
|
84
|
+
"define-lazy-prop": "3.0.0",
|
|
82
85
|
"delayed-stream": "1.0.0",
|
|
83
86
|
"dotenv": "16.4.7",
|
|
84
87
|
"dotenv-expand": "12.0.3",
|
|
@@ -111,11 +114,12 @@
|
|
|
111
114
|
"ieee754": "1.2.1",
|
|
112
115
|
"ignore": "7.0.5",
|
|
113
116
|
"inherits": "2.0.4",
|
|
114
|
-
"is-docker": "
|
|
117
|
+
"is-docker": "3.0.0",
|
|
115
118
|
"is-fullwidth-code-point": "3.0.0",
|
|
119
|
+
"is-inside-container": "1.0.0",
|
|
116
120
|
"is-interactive": "1.0.0",
|
|
117
121
|
"is-unicode-supported": "0.1.0",
|
|
118
|
-
"is-wsl": "
|
|
122
|
+
"is-wsl": "3.1.0",
|
|
119
123
|
"isexe": "2.0.0",
|
|
120
124
|
"json5": "2.2.3",
|
|
121
125
|
"jsonc-parser": "3.3.1",
|
|
@@ -131,7 +135,7 @@
|
|
|
131
135
|
"npm-run-path": "4.0.1",
|
|
132
136
|
"once": "1.4.0",
|
|
133
137
|
"onetime": "5.1.2",
|
|
134
|
-
"open": "
|
|
138
|
+
"open": "10.1.0",
|
|
135
139
|
"ora": "5.4.1",
|
|
136
140
|
"path-key": "3.1.1",
|
|
137
141
|
"picocolors": "1.1.1",
|
|
@@ -140,6 +144,7 @@
|
|
|
140
144
|
"require-directory": "2.1.1",
|
|
141
145
|
"resolve.exports": "2.0.3",
|
|
142
146
|
"restore-cursor": "3.1.0",
|
|
147
|
+
"run-applescript": "7.0.0",
|
|
143
148
|
"safe-buffer": "5.2.1",
|
|
144
149
|
"semver": "7.8.4",
|
|
145
150
|
"signal-exit": "3.0.7",
|
|
@@ -176,16 +181,16 @@
|
|
|
176
181
|
}
|
|
177
182
|
},
|
|
178
183
|
"optionalDependencies": {
|
|
179
|
-
"@nx/nx-darwin-arm64": "23.1.
|
|
180
|
-
"@nx/nx-darwin-x64": "23.1.
|
|
181
|
-
"@nx/nx-freebsd-x64": "23.1.
|
|
182
|
-
"@nx/nx-linux-arm-gnueabihf": "23.1.
|
|
183
|
-
"@nx/nx-linux-arm64-gnu": "23.1.
|
|
184
|
-
"@nx/nx-linux-arm64-musl": "23.1.
|
|
185
|
-
"@nx/nx-linux-x64-gnu": "23.1.
|
|
186
|
-
"@nx/nx-linux-x64-musl": "23.1.
|
|
187
|
-
"@nx/nx-win32-arm64-msvc": "23.1.
|
|
188
|
-
"@nx/nx-win32-x64-msvc": "23.1.
|
|
184
|
+
"@nx/nx-darwin-arm64": "23.1.1",
|
|
185
|
+
"@nx/nx-darwin-x64": "23.1.1",
|
|
186
|
+
"@nx/nx-freebsd-x64": "23.1.1",
|
|
187
|
+
"@nx/nx-linux-arm-gnueabihf": "23.1.1",
|
|
188
|
+
"@nx/nx-linux-arm64-gnu": "23.1.1",
|
|
189
|
+
"@nx/nx-linux-arm64-musl": "23.1.1",
|
|
190
|
+
"@nx/nx-linux-x64-gnu": "23.1.1",
|
|
191
|
+
"@nx/nx-linux-x64-musl": "23.1.1",
|
|
192
|
+
"@nx/nx-win32-arm64-msvc": "23.1.1",
|
|
193
|
+
"@nx/nx-win32-x64-msvc": "23.1.1"
|
|
189
194
|
},
|
|
190
195
|
"nx-migrations": {
|
|
191
196
|
"migrations": "./migrations.json",
|