nx 23.1.0 → 23.2.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/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/command-line/add/add.js +8 -1
- package/dist/src/command-line/import/import.js +1 -1
- 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/utils.d.ts +3 -3
- package/dist/src/command-line/init/implementation/utils.js +22 -3
- package/dist/src/command-line/migrate/migrate.d.ts +13 -0
- package/dist/src/command-line/migrate/migrate.js +45 -0
- package/dist/src/command-line/release/utils/git.js +6 -2
- package/dist/src/command-line/show/show-target/info.js +11 -2
- package/dist/src/daemon/client/client.d.ts +0 -2
- package/dist/src/daemon/client/client.js +17 -19
- package/dist/src/devkit-internals.d.ts +2 -0
- package/dist/src/devkit-internals.js +7 -1
- package/dist/src/native/index.d.ts +1 -1
- 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 +46 -15
- package/dist/src/plugins/js/lock-file/project-graph-pruning.js +1 -1
- package/dist/src/plugins/js/lock-file/yarn-parser.js +32 -5
- 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/error-types.js +41 -1
- package/dist/src/project-graph/plugins/isolation/isolated-plugin.js +4 -0
- package/dist/src/project-graph/plugins/transpiler.js +4 -0
- package/dist/src/project-graph/utils/project-configuration/name-substitution-manager.d.ts +9 -12
- package/dist/src/project-graph/utils/project-configuration/name-substitution-manager.js +77 -61
- package/dist/src/project-graph/utils/project-configuration/project-nodes-manager.d.ts +1 -1
- package/dist/src/project-graph/utils/project-configuration/project-nodes-manager.js +1 -1
- package/dist/src/project-graph/utils/project-configuration-utils.js +4 -6
- package/dist/src/tasks-runner/life-cycles/performance-analysis.d.ts +2 -0
- package/dist/src/tasks-runner/life-cycles/performance-analysis.js +15 -6
- package/dist/src/tasks-runner/life-cycles/performance-report.d.ts +2 -0
- package/dist/src/tasks-runner/life-cycles/performance-report.js +11 -2
- package/dist/src/tasks-runner/run-command.js +5 -3
- package/dist/src/utils/acknowledge-build-scripts.d.ts +13 -0
- package/dist/src/utils/acknowledge-build-scripts.js +100 -0
- 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/git-utils.d.ts +2 -3
- package/dist/src/utils/git-utils.js +101 -47
- package/dist/src/utils/min-release-age/behavior/pnpm.js +9 -7
- package/dist/src/utils/provenance.js +12 -2
- package/migrations.json +7 -1
- package/package.json +11 -11
- 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
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.readCatalogConfigFromTree = readCatalogConfigFromTree;
|
|
3
|
+
exports.readCatalogDefinitions = readCatalogDefinitions;
|
|
5
4
|
exports.updateCatalogVersionsInFile = updateCatalogVersionsInFile;
|
|
6
|
-
// Keep in sync with packages/devkit/src/utils/catalog/manager-utils.ts; the body
|
|
7
|
-
// below the imports is duplicated because @nx/devkit supports a range of nx majors
|
|
8
|
-
// and this logic isn't part of the nx surface it can import across that range.
|
|
9
5
|
const js_yaml_1 = require("@zkochan/js-yaml");
|
|
10
6
|
const node_fs_1 = require("node:fs");
|
|
11
7
|
const node_path_1 = require("node:path");
|
|
@@ -119,6 +115,27 @@ function readCatalogConfigFromTree(filename, tree) {
|
|
|
119
115
|
return null;
|
|
120
116
|
}
|
|
121
117
|
}
|
|
118
|
+
// Managers are created per operation (getCatalogManager news one up), so the
|
|
119
|
+
// fs (string-root) branch is cached to read the file once per pass instead of
|
|
120
|
+
// once per catalog reference. The Tree branch stays live since the tree is
|
|
121
|
+
// mutable within a generator.
|
|
122
|
+
function readCatalogDefinitions(filename, treeOrRoot, cache) {
|
|
123
|
+
if (typeof treeOrRoot === 'string') {
|
|
124
|
+
if (cache.has(treeOrRoot)) {
|
|
125
|
+
return cache.get(treeOrRoot);
|
|
126
|
+
}
|
|
127
|
+
const configPath = (0, node_path_1.join)(treeOrRoot, filename);
|
|
128
|
+
const defs = (0, node_fs_1.existsSync)(configPath)
|
|
129
|
+
? readCatalogConfigFromFs(filename, configPath)
|
|
130
|
+
: null;
|
|
131
|
+
cache.set(treeOrRoot, defs);
|
|
132
|
+
return defs;
|
|
133
|
+
}
|
|
134
|
+
if (!treeOrRoot.exists(filename)) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
return readCatalogConfigFromTree(filename, treeOrRoot);
|
|
138
|
+
}
|
|
122
139
|
function updateCatalogVersionsInFile(filename, treeOrRoot, updates) {
|
|
123
140
|
let checkExists;
|
|
124
141
|
let readYaml;
|
|
@@ -7,6 +7,7 @@ import type { CatalogDefinitions, CatalogReference } from './types';
|
|
|
7
7
|
export declare class PnpmCatalogManager implements CatalogManager {
|
|
8
8
|
readonly name = "pnpm";
|
|
9
9
|
readonly catalogProtocol = "catalog:";
|
|
10
|
+
private definitionsByRoot;
|
|
10
11
|
isCatalogReference(version: string): boolean;
|
|
11
12
|
parseCatalogReference(version: string): CatalogReference | null;
|
|
12
13
|
getCatalogDefinitionFilePaths(): string[];
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PnpmCatalogManager = void 0;
|
|
4
|
-
const node_fs_1 = require("node:fs");
|
|
5
|
-
const node_path_1 = require("node:path");
|
|
6
4
|
const manager_1 = require("./manager");
|
|
7
5
|
const manager_utils_1 = require("./manager-utils");
|
|
8
6
|
const PNPM_WORKSPACE_FILENAME = 'pnpm-workspace.yaml';
|
|
@@ -13,6 +11,8 @@ class PnpmCatalogManager {
|
|
|
13
11
|
constructor() {
|
|
14
12
|
this.name = 'pnpm';
|
|
15
13
|
this.catalogProtocol = 'catalog:';
|
|
14
|
+
// Parsed fs-root definitions, cached per pass. See readCatalogDefinitions.
|
|
15
|
+
this.definitionsByRoot = new Map();
|
|
16
16
|
}
|
|
17
17
|
isCatalogReference(version) {
|
|
18
18
|
return version.startsWith(this.catalogProtocol);
|
|
@@ -33,19 +33,7 @@ class PnpmCatalogManager {
|
|
|
33
33
|
return [PNPM_WORKSPACE_FILENAME];
|
|
34
34
|
}
|
|
35
35
|
getCatalogDefinitions(treeOrRoot) {
|
|
36
|
-
|
|
37
|
-
const configPath = (0, node_path_1.join)(treeOrRoot, PNPM_WORKSPACE_FILENAME);
|
|
38
|
-
if (!(0, node_fs_1.existsSync)(configPath)) {
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
return (0, manager_utils_1.readCatalogConfigFromFs)(PNPM_WORKSPACE_FILENAME, configPath);
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
if (!treeOrRoot.exists(PNPM_WORKSPACE_FILENAME)) {
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
return (0, manager_utils_1.readCatalogConfigFromTree)(PNPM_WORKSPACE_FILENAME, treeOrRoot);
|
|
48
|
-
}
|
|
36
|
+
return (0, manager_utils_1.readCatalogDefinitions)(PNPM_WORKSPACE_FILENAME, treeOrRoot, this.definitionsByRoot);
|
|
49
37
|
}
|
|
50
38
|
resolveCatalogReference(treeOrRoot, packageName, version) {
|
|
51
39
|
const catalogRef = this.parseCatalogReference(version);
|
|
@@ -7,6 +7,7 @@ import type { CatalogDefinitions, CatalogReference } from './types';
|
|
|
7
7
|
export declare class YarnCatalogManager implements CatalogManager {
|
|
8
8
|
readonly name = "yarn";
|
|
9
9
|
readonly catalogProtocol = "catalog:";
|
|
10
|
+
private definitionsByRoot;
|
|
10
11
|
isCatalogReference(version: string): boolean;
|
|
11
12
|
parseCatalogReference(version: string): CatalogReference | null;
|
|
12
13
|
getCatalogDefinitionFilePaths(): string[];
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.YarnCatalogManager = void 0;
|
|
4
|
-
const node_fs_1 = require("node:fs");
|
|
5
|
-
const node_path_1 = require("node:path");
|
|
6
4
|
const manager_1 = require("./manager");
|
|
7
5
|
const manager_utils_1 = require("./manager-utils");
|
|
8
6
|
const YARNRC_FILENAME = '.yarnrc.yml';
|
|
@@ -13,6 +11,8 @@ class YarnCatalogManager {
|
|
|
13
11
|
constructor() {
|
|
14
12
|
this.name = 'yarn';
|
|
15
13
|
this.catalogProtocol = 'catalog:';
|
|
14
|
+
// Parsed fs-root definitions, cached per pass. See readCatalogDefinitions.
|
|
15
|
+
this.definitionsByRoot = new Map();
|
|
16
16
|
}
|
|
17
17
|
isCatalogReference(version) {
|
|
18
18
|
return version.startsWith(this.catalogProtocol);
|
|
@@ -33,19 +33,7 @@ class YarnCatalogManager {
|
|
|
33
33
|
return [YARNRC_FILENAME];
|
|
34
34
|
}
|
|
35
35
|
getCatalogDefinitions(treeOrRoot) {
|
|
36
|
-
|
|
37
|
-
const configPath = (0, node_path_1.join)(treeOrRoot, YARNRC_FILENAME);
|
|
38
|
-
if (!(0, node_fs_1.existsSync)(configPath)) {
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
return (0, manager_utils_1.readCatalogConfigFromFs)(YARNRC_FILENAME, configPath);
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
if (!treeOrRoot.exists(YARNRC_FILENAME)) {
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
return (0, manager_utils_1.readCatalogConfigFromTree)(YARNRC_FILENAME, treeOrRoot);
|
|
48
|
-
}
|
|
36
|
+
return (0, manager_utils_1.readCatalogDefinitions)(YARNRC_FILENAME, treeOrRoot, this.definitionsByRoot);
|
|
49
37
|
}
|
|
50
38
|
resolveCatalogReference(treeOrRoot, packageName, version) {
|
|
51
39
|
const catalogRef = this.parseCatalogReference(version);
|
|
@@ -28,9 +28,7 @@ export declare class GitRepository {
|
|
|
28
28
|
hasFilterRepoInstalled(): Promise<boolean>;
|
|
29
29
|
filterRepo(source: string, destination: string): Promise<void>;
|
|
30
30
|
filterBranch(source: string, destination: string, branchName: string): Promise<void>;
|
|
31
|
-
private
|
|
32
|
-
private quotePath;
|
|
33
|
-
private quoteArg;
|
|
31
|
+
private execGit;
|
|
34
32
|
}
|
|
35
33
|
export interface VcsRemoteInfo {
|
|
36
34
|
domain: string;
|
|
@@ -39,6 +37,7 @@ export interface VcsRemoteInfo {
|
|
|
39
37
|
export declare function parseVcsRemoteUrl(url: string): VcsRemoteInfo | null;
|
|
40
38
|
export declare function getVcsRemoteInfo(directory?: string): VcsRemoteInfo | null;
|
|
41
39
|
export declare function isGitRepository(directory?: string): boolean;
|
|
40
|
+
export declare function getGitCurrentBranch(directory?: string): string | null;
|
|
42
41
|
export declare function hasUncommittedChanges(directory?: string): boolean;
|
|
43
42
|
export declare function getUncommittedChangesSnapshot(directory?: string): string;
|
|
44
43
|
export declare function commitChanges(commitMessage: string, directory?: string): string | null;
|
|
@@ -5,6 +5,7 @@ exports.cloneFromUpstream = cloneFromUpstream;
|
|
|
5
5
|
exports.parseVcsRemoteUrl = parseVcsRemoteUrl;
|
|
6
6
|
exports.getVcsRemoteInfo = getVcsRemoteInfo;
|
|
7
7
|
exports.isGitRepository = isGitRepository;
|
|
8
|
+
exports.getGitCurrentBranch = getGitCurrentBranch;
|
|
8
9
|
exports.hasUncommittedChanges = hasUncommittedChanges;
|
|
9
10
|
exports.getUncommittedChangesSnapshot = getUncommittedChangesSnapshot;
|
|
10
11
|
exports.commitChanges = commitChanges;
|
|
@@ -16,9 +17,9 @@ const crypto = tslib_1.__importStar(require("crypto"));
|
|
|
16
17
|
const fs = tslib_1.__importStar(require("fs"));
|
|
17
18
|
const path_1 = require("path");
|
|
18
19
|
const logger_1 = require("./logger");
|
|
19
|
-
function
|
|
20
|
+
function execFileAsync(file, args, execOptions) {
|
|
20
21
|
return new Promise((res, rej) => {
|
|
21
|
-
(0, child_process_1.
|
|
22
|
+
(0, child_process_1.execFile)(file, args, { ...execOptions, windowsHide: true }, (err, stdout) => {
|
|
22
23
|
if (err) {
|
|
23
24
|
return rej(err);
|
|
24
25
|
}
|
|
@@ -29,7 +30,14 @@ function execAsync(command, execOptions) {
|
|
|
29
30
|
async function cloneFromUpstream(url, destination, { originName, depth } = {
|
|
30
31
|
originName: 'origin',
|
|
31
32
|
}) {
|
|
32
|
-
await
|
|
33
|
+
await execFileAsync('git', [
|
|
34
|
+
'clone',
|
|
35
|
+
url,
|
|
36
|
+
destination,
|
|
37
|
+
...(depth ? ['--depth', `${depth}`] : []),
|
|
38
|
+
'--origin',
|
|
39
|
+
originName,
|
|
40
|
+
], {
|
|
33
41
|
cwd: (0, path_1.dirname)(destination),
|
|
34
42
|
maxBuffer: 10 * 1024 * 1024,
|
|
35
43
|
});
|
|
@@ -41,7 +49,7 @@ class GitRepository {
|
|
|
41
49
|
this.root = this.getGitRootPath(this.directory);
|
|
42
50
|
}
|
|
43
51
|
getGitRootPath(cwd) {
|
|
44
|
-
return (0, child_process_1.
|
|
52
|
+
return (0, child_process_1.execFileSync)('git', ['rev-parse', '--show-toplevel'], {
|
|
45
53
|
cwd,
|
|
46
54
|
windowsHide: true,
|
|
47
55
|
})
|
|
@@ -49,17 +57,22 @@ class GitRepository {
|
|
|
49
57
|
.trim();
|
|
50
58
|
}
|
|
51
59
|
async hasUncommittedChanges() {
|
|
52
|
-
const data = await this.
|
|
60
|
+
const data = await this.execGit(['status', '--porcelain']);
|
|
53
61
|
return data.trim() !== '';
|
|
54
62
|
}
|
|
55
63
|
async addFetchRemote(remoteName, branch) {
|
|
56
|
-
return await this.
|
|
64
|
+
return await this.execGit([
|
|
65
|
+
'config',
|
|
66
|
+
'--add',
|
|
67
|
+
`remote.${remoteName}.fetch`,
|
|
68
|
+
`+refs/heads/${branch}:refs/remotes/${remoteName}/${branch}`,
|
|
69
|
+
]);
|
|
57
70
|
}
|
|
58
71
|
async showStat() {
|
|
59
|
-
return await this.
|
|
72
|
+
return await this.execGit(['show', '--stat']);
|
|
60
73
|
}
|
|
61
74
|
async listBranches() {
|
|
62
|
-
return (await this.
|
|
75
|
+
return (await this.execGit(['ls-remote', '--heads', '--quiet']))
|
|
63
76
|
.trim()
|
|
64
77
|
.split('\n')
|
|
65
78
|
.map((s) => s
|
|
@@ -70,45 +83,58 @@ class GitRepository {
|
|
|
70
83
|
async getGitFiles(path) {
|
|
71
84
|
// Use -z to return file names exactly as they are stored in git, separated by NULL (\x00) character.
|
|
72
85
|
// This avoids problems with special characters in file names.
|
|
73
|
-
return (await this.
|
|
86
|
+
return (await this.execGit(['ls-files', '-z', '--', path]))
|
|
74
87
|
.trim()
|
|
75
88
|
.split('\x00')
|
|
76
89
|
.map((s) => s.trim())
|
|
77
90
|
.filter(Boolean);
|
|
78
91
|
}
|
|
79
92
|
async reset(ref) {
|
|
80
|
-
return await this.
|
|
93
|
+
return await this.execGit(['reset', '--hard', ref]);
|
|
81
94
|
}
|
|
82
95
|
async mergeUnrelatedHistories(ref, message) {
|
|
83
|
-
return await this.
|
|
96
|
+
return await this.execGit([
|
|
97
|
+
'merge',
|
|
98
|
+
ref,
|
|
99
|
+
'-X',
|
|
100
|
+
'ours',
|
|
101
|
+
'--allow-unrelated-histories',
|
|
102
|
+
'-m',
|
|
103
|
+
message,
|
|
104
|
+
]);
|
|
84
105
|
}
|
|
85
106
|
async fetch(remote, ref) {
|
|
86
|
-
return await this.
|
|
107
|
+
return await this.execGit(['fetch', remote, ...(ref ? [ref] : [])]);
|
|
87
108
|
}
|
|
88
109
|
async checkout(branch, opts) {
|
|
89
|
-
return await this.
|
|
110
|
+
return await this.execGit([
|
|
111
|
+
'checkout',
|
|
112
|
+
...(opts.new ? ['-b'] : []),
|
|
113
|
+
branch,
|
|
114
|
+
...(opts.base ? [opts.base] : []),
|
|
115
|
+
]);
|
|
90
116
|
}
|
|
91
117
|
async move(path, destination) {
|
|
92
|
-
return await this.
|
|
118
|
+
return await this.execGit(['mv', '--', path, destination]);
|
|
93
119
|
}
|
|
94
120
|
async push(ref, remoteName) {
|
|
95
|
-
return await this.
|
|
121
|
+
return await this.execGit(['push', '-u', '-f', remoteName, ref]);
|
|
96
122
|
}
|
|
97
123
|
async commit(message) {
|
|
98
|
-
return await this.
|
|
124
|
+
return await this.execGit(['commit', '-am', message]);
|
|
99
125
|
}
|
|
100
126
|
async amendCommit() {
|
|
101
|
-
return await this.
|
|
127
|
+
return await this.execGit(['commit', '--amend', '-a', '--no-edit']);
|
|
102
128
|
}
|
|
103
129
|
async deleteGitRemote(name) {
|
|
104
|
-
return await this.
|
|
130
|
+
return await this.execGit(['remote', 'rm', name]);
|
|
105
131
|
}
|
|
106
132
|
async addGitRemote(name, url) {
|
|
107
|
-
return await this.
|
|
133
|
+
return await this.execGit(['remote', 'add', name, url]);
|
|
108
134
|
}
|
|
109
135
|
async hasFilterRepoInstalled() {
|
|
110
136
|
try {
|
|
111
|
-
await this.
|
|
137
|
+
await this.execGit(['filter-repo', '--help']);
|
|
112
138
|
return true;
|
|
113
139
|
}
|
|
114
140
|
catch {
|
|
@@ -121,35 +147,57 @@ class GitRepository {
|
|
|
121
147
|
// NOTE: filter-repo requires POSIX path to work
|
|
122
148
|
const sourcePosixPath = source.split(path_1.sep).join(path_1.posix.sep);
|
|
123
149
|
const destinationPosixPath = destination.split(path_1.sep).join(path_1.posix.sep);
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
150
|
+
const sourcePath = ensureTrailingSlash(sourcePosixPath);
|
|
151
|
+
const destinationPath = ensureTrailingSlash(destinationPosixPath);
|
|
152
|
+
await this.execGit([
|
|
153
|
+
'filter-repo',
|
|
154
|
+
'-f',
|
|
155
|
+
...(source !== '' ? ['--path', sourcePosixPath] : []),
|
|
156
|
+
...(source !== destination
|
|
157
|
+
? ['--path-rename', `${sourcePath}:${destinationPath}`]
|
|
158
|
+
: []),
|
|
159
|
+
]);
|
|
127
160
|
}
|
|
128
161
|
async filterBranch(source, destination, branchName) {
|
|
129
162
|
// We need non-ASCII file names to not be quoted, or else filter-branch will exclude them.
|
|
130
|
-
await this.
|
|
163
|
+
await this.execGit(['config', 'core.quotepath', 'false']);
|
|
131
164
|
// NOTE: filter-repo requires POSIX path to work
|
|
132
165
|
const sourcePosixPath = source.split(path_1.sep).join(path_1.posix.sep);
|
|
133
166
|
const destinationPosixPath = destination.split(path_1.sep).join(path_1.posix.sep);
|
|
134
167
|
// First, if the source is not a root project, then only include commits relevant to the subdirectory.
|
|
135
168
|
if (source !== '') {
|
|
136
|
-
const indexFilterCommand =
|
|
137
|
-
await this.
|
|
169
|
+
const indexFilterCommand = `node ${quoteForShell((0, path_1.join)(__dirname, 'git-utils.index-filter.js'))}`;
|
|
170
|
+
await this.execGit([
|
|
171
|
+
'filter-branch',
|
|
172
|
+
'-f',
|
|
173
|
+
'--index-filter',
|
|
174
|
+
indexFilterCommand,
|
|
175
|
+
'--prune-empty',
|
|
176
|
+
'--',
|
|
177
|
+
branchName,
|
|
178
|
+
], {
|
|
138
179
|
NX_IMPORT_SOURCE: sourcePosixPath,
|
|
139
180
|
NX_IMPORT_DESTINATION: destinationPosixPath,
|
|
140
181
|
});
|
|
141
182
|
}
|
|
142
183
|
// Then, move files to their new location if necessary.
|
|
143
184
|
if (source === '' || source !== destination) {
|
|
144
|
-
const treeFilterCommand =
|
|
145
|
-
await this.
|
|
185
|
+
const treeFilterCommand = `node ${quoteForShell((0, path_1.join)(__dirname, 'git-utils.tree-filter.js'))}`;
|
|
186
|
+
await this.execGit([
|
|
187
|
+
'filter-branch',
|
|
188
|
+
'-f',
|
|
189
|
+
'--tree-filter',
|
|
190
|
+
treeFilterCommand,
|
|
191
|
+
'--',
|
|
192
|
+
branchName,
|
|
193
|
+
], {
|
|
146
194
|
NX_IMPORT_SOURCE: sourcePosixPath,
|
|
147
195
|
NX_IMPORT_DESTINATION: destinationPosixPath,
|
|
148
196
|
});
|
|
149
197
|
}
|
|
150
198
|
}
|
|
151
|
-
|
|
152
|
-
return
|
|
199
|
+
execGit(args, env) {
|
|
200
|
+
return execFileAsync('git', args, {
|
|
153
201
|
cwd: this.root,
|
|
154
202
|
maxBuffer: 10 * 1024 * 1024,
|
|
155
203
|
env: {
|
|
@@ -158,25 +206,14 @@ class GitRepository {
|
|
|
158
206
|
},
|
|
159
207
|
});
|
|
160
208
|
}
|
|
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
209
|
}
|
|
179
210
|
exports.GitRepository = GitRepository;
|
|
211
|
+
function ensureTrailingSlash(path) {
|
|
212
|
+
return path !== '' && !path.endsWith('/') ? `${path}/` : path;
|
|
213
|
+
}
|
|
214
|
+
function quoteForShell(arg) {
|
|
215
|
+
return `'${arg.replaceAll("'", "'\"'\"'")}'`;
|
|
216
|
+
}
|
|
180
217
|
function parseVcsRemoteUrl(url) {
|
|
181
218
|
// Remove whitespace and handle common URL formats
|
|
182
219
|
const cleanUrl = url.trim();
|
|
@@ -273,6 +310,23 @@ function isGitRepository(directory) {
|
|
|
273
310
|
return false;
|
|
274
311
|
}
|
|
275
312
|
}
|
|
313
|
+
// Checked-out branch name, or null when there isn't one to act on: a detached
|
|
314
|
+
// HEAD reports the literal "HEAD" (treated as no branch), and any git error
|
|
315
|
+
// (not a repo, no commits yet) also yields null.
|
|
316
|
+
function getGitCurrentBranch(directory) {
|
|
317
|
+
try {
|
|
318
|
+
const branch = (0, child_process_1.execSync)('git rev-parse --abbrev-ref HEAD', {
|
|
319
|
+
encoding: 'utf8',
|
|
320
|
+
cwd: directory,
|
|
321
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
322
|
+
windowsHide: true,
|
|
323
|
+
}).trim();
|
|
324
|
+
return branch && branch !== 'HEAD' ? branch : null;
|
|
325
|
+
}
|
|
326
|
+
catch {
|
|
327
|
+
return null;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
276
330
|
// Sync companion to `GitRepository.hasUncommittedChanges` for callers that
|
|
277
331
|
// can't drop into the async class (e.g. the migrate orchestrator, which
|
|
278
332
|
// branches on this before spawning subprocesses synchronously).
|
|
@@ -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) {
|
|
@@ -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);
|
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.
|
|
3
|
+
"version": "23.2.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.",
|
|
@@ -176,16 +176,16 @@
|
|
|
176
176
|
}
|
|
177
177
|
},
|
|
178
178
|
"optionalDependencies": {
|
|
179
|
-
"@nx/nx-darwin-arm64": "23.
|
|
180
|
-
"@nx/nx-darwin-x64": "23.
|
|
181
|
-
"@nx/nx-freebsd-x64": "23.
|
|
182
|
-
"@nx/nx-linux-arm-gnueabihf": "23.
|
|
183
|
-
"@nx/nx-linux-arm64-gnu": "23.
|
|
184
|
-
"@nx/nx-linux-arm64-musl": "23.
|
|
185
|
-
"@nx/nx-linux-x64-gnu": "23.
|
|
186
|
-
"@nx/nx-linux-x64-musl": "23.
|
|
187
|
-
"@nx/nx-win32-arm64-msvc": "23.
|
|
188
|
-
"@nx/nx-win32-x64-msvc": "23.
|
|
179
|
+
"@nx/nx-darwin-arm64": "23.2.0-beta.0",
|
|
180
|
+
"@nx/nx-darwin-x64": "23.2.0-beta.0",
|
|
181
|
+
"@nx/nx-freebsd-x64": "23.2.0-beta.0",
|
|
182
|
+
"@nx/nx-linux-arm-gnueabihf": "23.2.0-beta.0",
|
|
183
|
+
"@nx/nx-linux-arm64-gnu": "23.2.0-beta.0",
|
|
184
|
+
"@nx/nx-linux-arm64-musl": "23.2.0-beta.0",
|
|
185
|
+
"@nx/nx-linux-x64-gnu": "23.2.0-beta.0",
|
|
186
|
+
"@nx/nx-linux-x64-musl": "23.2.0-beta.0",
|
|
187
|
+
"@nx/nx-win32-arm64-msvc": "23.2.0-beta.0",
|
|
188
|
+
"@nx/nx-win32-x64-msvc": "23.2.0-beta.0"
|
|
189
189
|
},
|
|
190
190
|
"nx-migrations": {
|
|
191
191
|
"migrations": "./migrations.json",
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.default = nxReleasePath;
|
|
4
|
-
exports.visitNotIgnoredFiles = visitNotIgnoredFiles;
|
|
5
|
-
const node_path_1 = require("node:path");
|
|
6
|
-
const ignore_1 = require("../../utils/ignore");
|
|
7
|
-
function nxReleasePath(tree) {
|
|
8
|
-
visitNotIgnoredFiles(tree, '', (file) => {
|
|
9
|
-
const contents = tree.read(file).toString('utf-8');
|
|
10
|
-
if (
|
|
11
|
-
// the deep import usage should be replaced by the new location
|
|
12
|
-
contents.includes('nx/src/command-line/release') ||
|
|
13
|
-
// changelog-renderer has moved into nx/release
|
|
14
|
-
contents.includes('nx/changelog-renderer')) {
|
|
15
|
-
const finalContents = contents
|
|
16
|
-
// replace instances of old changelog renderer location
|
|
17
|
-
.replace(/nx\/changelog-renderer/g, 'nx/release/changelog-renderer')
|
|
18
|
-
// replace instances of deep import for programmatic API (only perform the replacement if an actual import by checking for trailing ' or ")
|
|
19
|
-
.replace(/nx\/src\/command-line\/release(['"])/g, 'nx/release$1');
|
|
20
|
-
tree.write(file, finalContents);
|
|
21
|
-
}
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
// Adapted from devkit
|
|
25
|
-
function visitNotIgnoredFiles(tree, dirPath = tree.root, visitor) {
|
|
26
|
-
const ig = (0, ignore_1.getIgnoreObject)();
|
|
27
|
-
dirPath = normalizePathRelativeToRoot(dirPath, tree.root);
|
|
28
|
-
if (dirPath !== '' && ig?.ignores(dirPath)) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
for (const child of tree.children(dirPath)) {
|
|
32
|
-
const fullPath = (0, node_path_1.join)(dirPath, child);
|
|
33
|
-
if (ig?.ignores(fullPath)) {
|
|
34
|
-
continue;
|
|
35
|
-
}
|
|
36
|
-
if (tree.isFile(fullPath)) {
|
|
37
|
-
visitor(fullPath);
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
visitNotIgnoredFiles(tree, fullPath, visitor);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
// Copied from devkit
|
|
45
|
-
function normalizePathRelativeToRoot(path, root) {
|
|
46
|
-
return (0, node_path_1.relative)(root, (0, node_path_1.join)(root, path)).split(node_path_1.sep).join('/');
|
|
47
|
-
}
|