nx 20.0.0-canary.20240925-6182d20 → 20.0.0-canary.20240928-f221a41
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/.eslintrc.json +9 -1
- package/package.json +14 -15
- package/schemas/nx-schema.json +26 -21
- package/src/command-line/graph/graph.js +9 -9
- package/src/command-line/import/utils/prepare-source-repo.js +8 -3
- package/src/command-line/init/implementation/add-nx-to-nest.js +5 -5
- package/src/command-line/init/implementation/react/clean-up-files.js +7 -7
- package/src/command-line/init/implementation/react/index.js +19 -12
- package/src/command-line/init/implementation/react/rename-js-to-jsx.js +3 -3
- package/src/command-line/release/changelog.js +1 -2
- package/src/command-line/release/config/version-plans.js +6 -7
- package/src/command-line/release/plan.js +6 -5
- package/src/command-line/release/release.js +2 -2
- package/src/command-line/release/version.js +5 -3
- package/src/command-line/reset/reset.js +20 -13
- package/src/core/graph/main.js +1 -1
- package/src/core/graph/styles.css +1 -1
- package/src/core/graph/styles.js +1 -1
- package/src/daemon/cache.d.ts +1 -2
- package/src/daemon/cache.js +12 -21
- package/src/daemon/client/client.js +9 -8
- package/src/daemon/server/handle-hash-tasks.js +1 -1
- package/src/daemon/tmp-dir.js +6 -7
- package/src/executors/run-commands/run-commands.impl.js +15 -22
- package/src/generators/tree.d.ts +1 -1
- package/src/generators/tree.js +11 -11
- package/src/generators/utils/project-configuration.js +2 -1
- package/src/hasher/create-task-hasher.js +1 -1
- package/src/hasher/hash-task.d.ts +4 -2
- package/src/hasher/hash-task.js +6 -9
- package/src/hasher/task-hasher.d.ts +2 -6
- package/src/hasher/task-hasher.js +6 -32
- package/src/native/nx.wasm32-wasi.wasm +0 -0
- package/src/plugins/js/index.js +1 -2
- package/src/project-graph/nx-deps-cache.js +5 -6
- package/src/tasks-runner/cache.js +17 -16
- package/src/tasks-runner/forked-process-task-runner.js +16 -5
- package/src/tasks-runner/life-cycles/dynamic-run-many-terminal-output-life-cycle.js +5 -0
- package/src/tasks-runner/life-cycles/static-run-many-terminal-output-life-cycle.js +7 -0
- package/src/tasks-runner/remove-old-cache-records.js +2 -3
- package/src/tasks-runner/run-command.js +3 -1
- package/src/tasks-runner/task-orchestrator.d.ts +1 -0
- package/src/tasks-runner/task-orchestrator.js +6 -2
- package/src/tasks-runner/tasks-schedule.d.ts +1 -0
- package/src/tasks-runner/tasks-schedule.js +6 -2
- package/src/utils/fileutils.d.ts +9 -1
- package/src/utils/fileutils.js +29 -12
- package/src/utils/ignore.js +2 -2
- package/src/utils/package-json.d.ts +1 -0
- package/src/utils/package-manager.js +2 -2
- package/src/utils/plugins/core-plugins.js +4 -0
- package/src/utils/plugins/output.js +1 -1
- package/src/hasher/node-task-hasher-impl.d.ts +0 -48
- package/src/hasher/node-task-hasher-impl.js +0 -449
@@ -11,7 +11,6 @@ exports.expandSingleProjectInputs = expandSingleProjectInputs;
|
|
11
11
|
exports.expandNamedInput = expandNamedInput;
|
12
12
|
exports.filterUsingGlobPatterns = filterUsingGlobPatterns;
|
13
13
|
const file_hasher_1 = require("./file-hasher");
|
14
|
-
const node_task_hasher_impl_1 = require("./node-task-hasher-impl");
|
15
14
|
const minimatch_1 = require("minimatch");
|
16
15
|
const native_task_hasher_impl_1 = require("./native-task-hasher-impl");
|
17
16
|
const workspace_root_1 = require("../utils/workspace-root");
|
@@ -29,42 +28,18 @@ class DaemonBasedTaskHasher {
|
|
29
28
|
}
|
30
29
|
exports.DaemonBasedTaskHasher = DaemonBasedTaskHasher;
|
31
30
|
class InProcessTaskHasher {
|
32
|
-
constructor(
|
33
|
-
this.projectFileMap = projectFileMap;
|
34
|
-
this.allWorkspaceFiles = allWorkspaceFiles;
|
31
|
+
constructor(projectGraph, nxJson, externalRustReferences, options) {
|
35
32
|
this.projectGraph = projectGraph;
|
36
33
|
this.nxJson = nxJson;
|
37
34
|
this.externalRustReferences = externalRustReferences;
|
38
35
|
this.options = options;
|
39
|
-
this.
|
40
|
-
|
41
|
-
|
42
|
-
: []).map((r) => ({ runtime: r }));
|
43
|
-
if (process.env.NX_CLOUD_ENCRYPTION_KEY) {
|
44
|
-
legacyRuntimeInputs.push({ env: 'NX_CLOUD_ENCRYPTION_KEY' });
|
45
|
-
}
|
46
|
-
const legacyFilesetInputs = [
|
47
|
-
'nx.json',
|
48
|
-
// ignore files will change the set of inputs to the hasher
|
49
|
-
'.gitignore',
|
50
|
-
'.nxignore',
|
51
|
-
].map((d) => ({ fileset: `{workspaceRoot}/${d}` }));
|
52
|
-
this.taskHasher = !this.useNativeTaskHasher
|
53
|
-
? new node_task_hasher_impl_1.NodeTaskHasherImpl(nxJson, legacyRuntimeInputs, legacyFilesetInputs, this.projectFileMap, this.allWorkspaceFiles, this.projectGraph, {
|
54
|
-
selectivelyHashTsConfig: this.options?.selectivelyHashTsConfig ?? false,
|
55
|
-
})
|
56
|
-
: new native_task_hasher_impl_1.NativeTaskHasherImpl(workspace_root_1.workspaceRoot, nxJson, this.projectGraph, this.externalRustReferences, {
|
57
|
-
selectivelyHashTsConfig: this.options?.selectivelyHashTsConfig ?? false,
|
58
|
-
});
|
36
|
+
this.taskHasher = new native_task_hasher_impl_1.NativeTaskHasherImpl(workspace_root_1.workspaceRoot, this.nxJson, this.projectGraph, this.externalRustReferences, {
|
37
|
+
selectivelyHashTsConfig: this.options?.selectivelyHashTsConfig ?? false,
|
38
|
+
});
|
59
39
|
}
|
60
40
|
async hashTasks(tasks, taskGraph, env) {
|
61
|
-
|
62
|
-
|
63
|
-
return tasks.map((task, index) => this.createHashDetails(task, hashes[index]));
|
64
|
-
}
|
65
|
-
else {
|
66
|
-
return await Promise.all(tasks.map((t) => this.hashTask(t, taskGraph, env)));
|
67
|
-
}
|
41
|
+
const hashes = await this.taskHasher.hashTasks(tasks, taskGraph, env ?? process.env);
|
42
|
+
return tasks.map((task, index) => this.createHashDetails(task, hashes[index]));
|
68
43
|
}
|
69
44
|
async hashTask(task, taskGraph, env) {
|
70
45
|
const res = await this.taskHasher.hashTask(task, taskGraph, env ?? process.env);
|
@@ -98,7 +73,6 @@ class InProcessTaskHasher {
|
|
98
73
|
}
|
99
74
|
}
|
100
75
|
exports.InProcessTaskHasher = InProcessTaskHasher;
|
101
|
-
InProcessTaskHasher.version = '3.0';
|
102
76
|
const DEFAULT_INPUTS = [
|
103
77
|
{
|
104
78
|
fileset: '{projectRoot}/**/*',
|
Binary file
|
package/src/plugins/js/index.js
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.createDependencies = exports.createNodes = exports.name = void 0;
|
4
4
|
const fs_1 = require("fs");
|
5
|
-
const fs_extra_1 = require("fs-extra");
|
6
5
|
const path_1 = require("path");
|
7
6
|
const perf_hooks_1 = require("perf_hooks");
|
8
7
|
const cache_directory_1 = require("../../utils/cache-directory");
|
@@ -96,7 +95,7 @@ function lockFileNeedsReprocessing(lockHash) {
|
|
96
95
|
}
|
97
96
|
}
|
98
97
|
function writeLastProcessedLockfileHash(hash, lockFile) {
|
99
|
-
(0,
|
98
|
+
(0, fs_1.mkdirSync)((0, path_1.dirname)(lockFileHashFile), { recursive: true });
|
100
99
|
(0, fs_1.writeFileSync)(cachedParsedLockFile, JSON.stringify(lockFile, null, 2));
|
101
100
|
(0, fs_1.writeFileSync)(lockFileHashFile, hash);
|
102
101
|
}
|
@@ -8,8 +8,7 @@ exports.createProjectFileMapCache = createProjectFileMapCache;
|
|
8
8
|
exports.writeCache = writeCache;
|
9
9
|
exports.shouldRecomputeWholeGraph = shouldRecomputeWholeGraph;
|
10
10
|
exports.extractCachedFileData = extractCachedFileData;
|
11
|
-
const
|
12
|
-
const fs_extra_1 = require("fs-extra");
|
11
|
+
const node_fs_1 = require("node:fs");
|
13
12
|
const path_1 = require("path");
|
14
13
|
const perf_hooks_1 = require("perf_hooks");
|
15
14
|
const cache_directory_1 = require("../utils/cache-directory");
|
@@ -19,8 +18,8 @@ exports.nxProjectGraph = (0, path_1.join)(cache_directory_1.workspaceDataDirecto
|
|
19
18
|
exports.nxFileMap = (0, path_1.join)(cache_directory_1.workspaceDataDirectory, 'file-map.json');
|
20
19
|
function ensureCacheDirectory() {
|
21
20
|
try {
|
22
|
-
if (!(0,
|
23
|
-
(0,
|
21
|
+
if (!(0, node_fs_1.existsSync)(cache_directory_1.workspaceDataDirectory)) {
|
22
|
+
(0, node_fs_1.mkdirSync)(cache_directory_1.workspaceDataDirectory, { recursive: true });
|
24
23
|
}
|
25
24
|
}
|
26
25
|
catch (e) {
|
@@ -102,9 +101,9 @@ function writeCache(cache, projectGraph) {
|
|
102
101
|
const tmpFileMapPath = `${exports.nxFileMap}~${unique}`;
|
103
102
|
try {
|
104
103
|
(0, fileutils_1.writeJsonFile)(tmpProjectGraphPath, projectGraph);
|
105
|
-
(0,
|
104
|
+
(0, node_fs_1.renameSync)(tmpProjectGraphPath, exports.nxProjectGraph);
|
106
105
|
(0, fileutils_1.writeJsonFile)(tmpFileMapPath, cache);
|
107
|
-
(0,
|
106
|
+
(0, node_fs_1.renameSync)(tmpFileMapPath, exports.nxFileMap);
|
108
107
|
done = true;
|
109
108
|
}
|
110
109
|
catch (err) {
|
@@ -3,11 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Cache = exports.DbCache = void 0;
|
4
4
|
exports.getCache = getCache;
|
5
5
|
const workspace_root_1 = require("../utils/workspace-root");
|
6
|
-
const fs_extra_1 = require("fs-extra");
|
7
6
|
const path_1 = require("path");
|
8
7
|
const perf_hooks_1 = require("perf_hooks");
|
9
8
|
const default_tasks_runner_1 = require("./default-tasks-runner");
|
10
9
|
const child_process_1 = require("child_process");
|
10
|
+
const node_fs_1 = require("node:fs");
|
11
|
+
const promises_1 = require("node:fs/promises");
|
11
12
|
const cache_directory_1 = require("../utils/cache-directory");
|
12
13
|
const node_machine_id_1 = require("node-machine-id");
|
13
14
|
const native_1 = require("../native");
|
@@ -233,13 +234,13 @@ class Cache {
|
|
233
234
|
// might be left overs from partially-completed cache invocations
|
234
235
|
await this.remove(tdCommit);
|
235
236
|
await this.remove(td);
|
236
|
-
await (0,
|
237
|
-
await (0,
|
238
|
-
await (0,
|
237
|
+
await (0, promises_1.mkdir)(td, { recursive: true });
|
238
|
+
await (0, promises_1.writeFile)((0, path_1.join)(td, 'terminalOutput'), terminalOutput ?? 'no terminal output');
|
239
|
+
await (0, promises_1.mkdir)((0, path_1.join)(td, 'outputs'));
|
239
240
|
const expandedOutputs = await this.expandOutputsInWorkspace(outputs);
|
240
241
|
await Promise.all(expandedOutputs.map(async (f) => {
|
241
242
|
const src = (0, path_1.join)(this.root, f);
|
242
|
-
if (
|
243
|
+
if ((0, node_fs_1.existsSync)(src)) {
|
243
244
|
const cached = (0, path_1.join)(td, 'outputs', f);
|
244
245
|
await this.copy(src, cached);
|
245
246
|
}
|
@@ -248,15 +249,15 @@ class Cache {
|
|
248
249
|
// creating this file is atomic, whereas creating a folder is not.
|
249
250
|
// so if the process gets terminated while we are copying stuff into cache,
|
250
251
|
// the cache entry won't be used.
|
251
|
-
await (0,
|
252
|
-
await (0,
|
253
|
-
await (0,
|
252
|
+
await (0, promises_1.writeFile)((0, path_1.join)(td, 'code'), code.toString());
|
253
|
+
await (0, promises_1.writeFile)((0, path_1.join)(td, 'source'), await this.currentMachineId());
|
254
|
+
await (0, promises_1.writeFile)(tdCommit, 'true');
|
254
255
|
if (this.options.remoteCache) {
|
255
256
|
await this.options.remoteCache.store(task.hash, this.cachePath);
|
256
257
|
}
|
257
258
|
if (terminalOutput) {
|
258
259
|
const outputPath = this.temporaryOutputPath(task);
|
259
|
-
await (0,
|
260
|
+
await (0, promises_1.writeFile)(outputPath, terminalOutput);
|
260
261
|
}
|
261
262
|
});
|
262
263
|
}
|
@@ -265,7 +266,7 @@ class Cache {
|
|
265
266
|
const expandedOutputs = await this.expandOutputsInCache(outputs, cachedResult);
|
266
267
|
await Promise.all(expandedOutputs.map(async (f) => {
|
267
268
|
const cached = (0, path_1.join)(cachedResult.outputsPath, f);
|
268
|
-
if (
|
269
|
+
if ((0, node_fs_1.existsSync)(cached)) {
|
269
270
|
const src = (0, path_1.join)(this.root, f);
|
270
271
|
await this.remove(src);
|
271
272
|
await this.copy(cached, src);
|
@@ -321,11 +322,11 @@ class Cache {
|
|
321
322
|
async getFromLocalDir(task) {
|
322
323
|
const tdCommit = (0, path_1.join)(this.cachePath, `${task.hash}.commit`);
|
323
324
|
const td = (0, path_1.join)(this.cachePath, task.hash);
|
324
|
-
if (
|
325
|
-
const terminalOutput = await (0,
|
325
|
+
if ((0, node_fs_1.existsSync)(tdCommit)) {
|
326
|
+
const terminalOutput = await (0, promises_1.readFile)((0, path_1.join)(td, 'terminalOutput'), 'utf-8');
|
326
327
|
let code = 0;
|
327
328
|
try {
|
328
|
-
code = Number(await (0,
|
329
|
+
code = Number(await (0, promises_1.readFile)((0, path_1.join)(td, 'code'), 'utf-8'));
|
329
330
|
}
|
330
331
|
catch { }
|
331
332
|
return {
|
@@ -342,7 +343,7 @@ class Cache {
|
|
342
343
|
const td = (0, path_1.join)(this.cachePath, task.hash);
|
343
344
|
let sourceMachineId = null;
|
344
345
|
try {
|
345
|
-
sourceMachineId = await (0,
|
346
|
+
sourceMachineId = await (0, promises_1.readFile)((0, path_1.join)(td, 'source'), 'utf-8');
|
346
347
|
}
|
347
348
|
catch { }
|
348
349
|
if (sourceMachineId && sourceMachineId != (await this.currentMachineId())) {
|
@@ -361,12 +362,12 @@ class Cache {
|
|
361
362
|
}
|
362
363
|
}
|
363
364
|
createCacheDir() {
|
364
|
-
(0,
|
365
|
+
(0, node_fs_1.mkdirSync)(cache_directory_1.cacheDir, { recursive: true });
|
365
366
|
return cache_directory_1.cacheDir;
|
366
367
|
}
|
367
368
|
createTerminalOutputsDir() {
|
368
369
|
const path = (0, path_1.join)(this.cachePath, 'terminalOutputs');
|
369
|
-
(0,
|
370
|
+
(0, node_fs_1.mkdirSync)(path, { recursive: true });
|
370
371
|
return path;
|
371
372
|
}
|
372
373
|
}
|
@@ -4,7 +4,6 @@ exports.ForkedProcessTaskRunner = void 0;
|
|
4
4
|
const fs_1 = require("fs");
|
5
5
|
const child_process_1 = require("child_process");
|
6
6
|
const chalk = require("chalk");
|
7
|
-
const logTransformer = require("strong-log-transformer");
|
8
7
|
const output_1 = require("../utils/output");
|
9
8
|
const utils_1 = require("./utils");
|
10
9
|
const path_1 = require("path");
|
@@ -208,16 +207,16 @@ class ForkedProcessTaskRunner {
|
|
208
207
|
const prefixText = `${task.target.project}:`;
|
209
208
|
p.stdout
|
210
209
|
.pipe(logClearLineToPrefixTransformer(color.bold(prefixText) + ' '))
|
211
|
-
.pipe(
|
210
|
+
.pipe(addPrefixTransformer(color.bold(prefixText)))
|
212
211
|
.pipe(process.stdout);
|
213
212
|
p.stderr
|
214
213
|
.pipe(logClearLineToPrefixTransformer(color(prefixText) + ' '))
|
215
|
-
.pipe(
|
214
|
+
.pipe(addPrefixTransformer(color(prefixText)))
|
216
215
|
.pipe(process.stderr);
|
217
216
|
}
|
218
217
|
else {
|
219
|
-
p.stdout.pipe(
|
220
|
-
p.stderr.pipe(
|
218
|
+
p.stdout.pipe(addPrefixTransformer()).pipe(process.stdout);
|
219
|
+
p.stderr.pipe(addPrefixTransformer()).pipe(process.stderr);
|
221
220
|
}
|
222
221
|
}
|
223
222
|
let outWithErr = [];
|
@@ -403,3 +402,15 @@ function logClearLineToPrefixTransformer(prefix) {
|
|
403
402
|
},
|
404
403
|
});
|
405
404
|
}
|
405
|
+
function addPrefixTransformer(prefix) {
|
406
|
+
const newLineSeparator = process.platform.startsWith('win') ? '\r\n' : '\n';
|
407
|
+
return new stream_1.Transform({
|
408
|
+
transform(chunk, _encoding, callback) {
|
409
|
+
const list = chunk.toString().split(/\r\n|[\n\v\f\r\x85\u2028\u2029]/g);
|
410
|
+
list
|
411
|
+
.filter(Boolean)
|
412
|
+
.forEach((m) => this.push(prefix ? prefix + ' ' + m + newLineSeparator : m + newLineSeparator));
|
413
|
+
callback();
|
414
|
+
},
|
415
|
+
});
|
416
|
+
}
|
@@ -224,6 +224,11 @@ async function createRunManyDynamicOutputRenderer({ projectNames, tasks, args, o
|
|
224
224
|
clearRenderInterval();
|
225
225
|
const timeTakenText = (0, pretty_time_1.prettyTime)(process.hrtime(start));
|
226
226
|
moveCursorToStartOfPinnedFooter();
|
227
|
+
if (totalTasks === 0) {
|
228
|
+
renderPinnedFooter([output_1.output.applyNxPrefix('gray', 'No tasks were run')]);
|
229
|
+
resolveRenderIsDonePromise();
|
230
|
+
return;
|
231
|
+
}
|
227
232
|
if (totalSuccessfulTasks === totalTasks) {
|
228
233
|
const text = `Successfully ran ${(0, formatting_utils_1.formatTargetsAndProjects)(projectNames, targets, tasks)}`;
|
229
234
|
const taskOverridesRows = [];
|
@@ -23,6 +23,9 @@ class StaticRunManyTerminalOutputLifeCycle {
|
|
23
23
|
this.allCompletedTasks = new Map();
|
24
24
|
}
|
25
25
|
startCommand() {
|
26
|
+
if (this.tasks.length === 0) {
|
27
|
+
return;
|
28
|
+
}
|
26
29
|
if (this.projectNames.length <= 0) {
|
27
30
|
output_1.output.logSingleLine(`No projects with ${(0, formatting_utils_1.formatTargetsAndProjects)(this.projectNames, this.args.targets, this.tasks)} were run`);
|
28
31
|
return;
|
@@ -45,6 +48,10 @@ class StaticRunManyTerminalOutputLifeCycle {
|
|
45
48
|
}
|
46
49
|
endCommand() {
|
47
50
|
output_1.output.addNewline();
|
51
|
+
if (this.tasks.length === 0) {
|
52
|
+
output_1.output.logSingleLine(`No tasks were run`);
|
53
|
+
return;
|
54
|
+
}
|
48
55
|
if (this.failedTasks.length === 0) {
|
49
56
|
output_1.output.addVerticalSeparatorWithoutNewLines('green');
|
50
57
|
const bodyLines = this.cachedTasks.length > 0
|
@@ -1,7 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
const fs_1 = require("fs");
|
4
|
-
const fs_extra_1 = require("fs-extra");
|
5
4
|
const path_1 = require("path");
|
6
5
|
const WEEK_IN_MS = 1000 * 60 * 60 * 24 * 7;
|
7
6
|
const folder = process.argv[2];
|
@@ -34,11 +33,11 @@ function removeOld(records) {
|
|
34
33
|
if (time - s.mtimeMs > WEEK_IN_MS) {
|
35
34
|
if (s.isDirectory()) {
|
36
35
|
try {
|
37
|
-
(0,
|
36
|
+
(0, fs_1.rmSync)(`${r}.commit`, { recursive: true, force: true });
|
38
37
|
}
|
39
38
|
catch (e) { }
|
40
39
|
}
|
41
|
-
(0,
|
40
|
+
(0, fs_1.rmSync)(r, { recursive: true, force: true });
|
42
41
|
}
|
43
42
|
}
|
44
43
|
catch (e) { }
|
@@ -363,12 +363,14 @@ function setEnvVarsBasedOnArgs(nxArgs, loadDotEnvFiles) {
|
|
363
363
|
}
|
364
364
|
async function invokeTasksRunner({ tasks, projectGraph, taskGraph, lifeCycle, nxJson, nxArgs, loadDotEnvFiles, initiatingProject, }) {
|
365
365
|
setEnvVarsBasedOnArgs(nxArgs, loadDotEnvFiles);
|
366
|
+
// this needs to be done before we start to run the tasks
|
367
|
+
const taskDetails = (0, hash_task_1.getTaskDetails)();
|
366
368
|
const { tasksRunner, runnerOptions } = getRunner(nxArgs, nxJson);
|
367
369
|
let hasher = (0, create_task_hasher_1.createTaskHasher)(projectGraph, nxJson, runnerOptions);
|
368
370
|
// this is used for two reasons: to fetch all remote cache hits AND
|
369
371
|
// to submit everything that is known in advance to Nx Cloud to run in
|
370
372
|
// a distributed fashion
|
371
|
-
await (0, hash_task_1.hashTasksThatDoNotDependOnOutputsOfOtherTasks)(hasher, projectGraph, taskGraph, nxJson);
|
373
|
+
await (0, hash_task_1.hashTasksThatDoNotDependOnOutputsOfOtherTasks)(hasher, projectGraph, taskGraph, nxJson, taskDetails);
|
372
374
|
const taskResultsLifecycle = new task_results_life_cycle_1.TaskResultsLifeCycle();
|
373
375
|
const compositedLifeCycle = new life_cycle_1.CompositeLifeCycle([
|
374
376
|
...constructLifeCycles(lifeCycle),
|
@@ -27,6 +27,7 @@ class TaskOrchestrator {
|
|
27
27
|
this.bail = bail;
|
28
28
|
this.daemon = daemon;
|
29
29
|
this.outputStyle = outputStyle;
|
30
|
+
this.taskDetails = (0, hash_task_1.getTaskDetails)();
|
30
31
|
this.cache = (0, cache_1.getCache)(this.nxJson, this.options);
|
31
32
|
this.forkedProcessTaskRunner = new forked_process_task_runner_1.ForkedProcessTaskRunner(this.options);
|
32
33
|
this.tasksSchedule = new tasks_schedule_1.TasksSchedule(this.projectGraph, this.taskGraph, this.options);
|
@@ -93,7 +94,7 @@ class TaskOrchestrator {
|
|
93
94
|
const task = this.taskGraph.tasks[taskId];
|
94
95
|
const taskSpecificEnv = (0, task_env_1.getTaskSpecificEnv)(task);
|
95
96
|
if (!task.hash) {
|
96
|
-
await (0, hash_task_1.hashTask)(this.hasher, this.projectGraph, this.taskGraph, task, taskSpecificEnv);
|
97
|
+
await (0, hash_task_1.hashTask)(this.hasher, this.projectGraph, this.taskGraph, task, taskSpecificEnv, this.taskDetails);
|
97
98
|
}
|
98
99
|
await this.options.lifeCycle.scheduleTask(task);
|
99
100
|
return taskSpecificEnv;
|
@@ -101,7 +102,7 @@ class TaskOrchestrator {
|
|
101
102
|
async processScheduledBatch(batch) {
|
102
103
|
await Promise.all(Object.values(batch.taskGraph.tasks).map(async (task) => {
|
103
104
|
if (!task.hash) {
|
104
|
-
await (0, hash_task_1.hashTask)(this.hasher, this.projectGraph, this.taskGraph, task, this.batchEnv);
|
105
|
+
await (0, hash_task_1.hashTask)(this.hasher, this.projectGraph, this.taskGraph, task, this.batchEnv, this.taskDetails);
|
105
106
|
}
|
106
107
|
await this.options.lifeCycle.scheduleTask(task);
|
107
108
|
}));
|
@@ -321,6 +322,9 @@ class TaskOrchestrator {
|
|
321
322
|
};
|
322
323
|
}
|
323
324
|
catch (e) {
|
325
|
+
if (process.env.NX_VERBOSE_LOGGING === 'true') {
|
326
|
+
console.error(e);
|
327
|
+
}
|
324
328
|
return {
|
325
329
|
code: 1,
|
326
330
|
};
|
@@ -19,6 +19,7 @@ export declare class TasksSchedule {
|
|
19
19
|
private completedTasks;
|
20
20
|
private scheduleRequestsExecutionChain;
|
21
21
|
private estimatedTaskTimings;
|
22
|
+
private projectDependencies;
|
22
23
|
constructor(projectGraph: ProjectGraph, taskGraph: TaskGraph, options: DefaultTasksRunnerOptions);
|
23
24
|
init(): Promise<void>;
|
24
25
|
scheduleNextTasks(): Promise<void>;
|
@@ -20,12 +20,16 @@ class TasksSchedule {
|
|
20
20
|
this.completedTasks = new Set();
|
21
21
|
this.scheduleRequestsExecutionChain = Promise.resolve();
|
22
22
|
this.estimatedTaskTimings = {};
|
23
|
+
this.projectDependencies = {};
|
23
24
|
}
|
24
25
|
async init() {
|
25
26
|
if (this.taskHistory) {
|
26
27
|
this.estimatedTaskTimings =
|
27
28
|
await this.taskHistory.getEstimatedTaskTimings(Object.values(this.taskGraph.tasks).map((t) => t.target));
|
28
29
|
}
|
30
|
+
for (const project of Object.values(this.taskGraph.tasks).map((t) => t.target.project)) {
|
31
|
+
this.projectDependencies[project] ??= (0, project_graph_utils_1.findAllProjectNodeDependencies)(project, this.reverseProjectGraph).length;
|
32
|
+
}
|
29
33
|
}
|
30
34
|
async scheduleNextTasks() {
|
31
35
|
this.scheduleRequestsExecutionChain =
|
@@ -90,8 +94,8 @@ class TasksSchedule {
|
|
90
94
|
// Most likely tasks with no dependencies such as test
|
91
95
|
const project1 = this.taskGraph.tasks[taskId1].target.project;
|
92
96
|
const project2 = this.taskGraph.tasks[taskId2].target.project;
|
93
|
-
const project1NodeDependencies =
|
94
|
-
const project2NodeDependencies =
|
97
|
+
const project1NodeDependencies = this.projectDependencies[project1];
|
98
|
+
const project2NodeDependencies = this.projectDependencies[project2];
|
95
99
|
const dependenciesDiff = project2NodeDependencies - project1NodeDependencies;
|
96
100
|
if (dependenciesDiff !== 0) {
|
97
101
|
return dependenciesDiff;
|
package/src/utils/fileutils.d.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import type { JsonParseOptions, JsonSerializeOptions } from './json';
|
2
|
-
import { PathLike } from 'fs';
|
2
|
+
import { PathLike } from 'node:fs';
|
3
3
|
export interface JsonReadOptions extends JsonParseOptions {
|
4
4
|
/**
|
5
5
|
* mutable field recording whether JSON ends with new line
|
@@ -43,6 +43,14 @@ export declare function readYamlFile<T extends object = any>(path: string, optio
|
|
43
43
|
* @param options JSON serialize options
|
44
44
|
*/
|
45
45
|
export declare function writeJsonFile<T extends object = object>(path: string, data: T, options?: JsonWriteOptions): void;
|
46
|
+
/**
|
47
|
+
* Serializes the given data to JSON and writes it to a file asynchronously.
|
48
|
+
*
|
49
|
+
* @param path A path to a file.
|
50
|
+
* @param data data which should be serialized to JSON and written to the file
|
51
|
+
* @param options JSON serialize options
|
52
|
+
*/
|
53
|
+
export declare function writeJsonFileAsync<T extends object = object>(path: string, data: T, options?: JsonWriteOptions): Promise<void>;
|
46
54
|
/**
|
47
55
|
* Check if a directory exists
|
48
56
|
* @param path Path to directory
|
package/src/utils/fileutils.js
CHANGED
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.readJsonFile = readJsonFile;
|
4
4
|
exports.readYamlFile = readYamlFile;
|
5
5
|
exports.writeJsonFile = writeJsonFile;
|
6
|
+
exports.writeJsonFileAsync = writeJsonFileAsync;
|
6
7
|
exports.directoryExists = directoryExists;
|
7
8
|
exports.fileExists = fileExists;
|
8
9
|
exports.createDirectory = createDirectory;
|
@@ -10,7 +11,8 @@ exports.isRelativePath = isRelativePath;
|
|
10
11
|
exports.extractFileFromTarball = extractFileFromTarball;
|
11
12
|
exports.readFileIfExisting = readFileIfExisting;
|
12
13
|
const json_1 = require("./json");
|
13
|
-
const
|
14
|
+
const node_fs_1 = require("node:fs");
|
15
|
+
const promises_1 = require("node:fs/promises");
|
14
16
|
const path_1 = require("path");
|
15
17
|
const tar = require("tar-stream");
|
16
18
|
const zlib_1 = require("zlib");
|
@@ -22,7 +24,7 @@ const zlib_1 = require("zlib");
|
|
22
24
|
* @returns Object the JSON content of the file represents
|
23
25
|
*/
|
24
26
|
function readJsonFile(path, options) {
|
25
|
-
const content = (0,
|
27
|
+
const content = (0, node_fs_1.readFileSync)(path, 'utf-8');
|
26
28
|
if (options) {
|
27
29
|
options.endsWithNewline = content.charCodeAt(content.length - 1) === 10;
|
28
30
|
}
|
@@ -41,7 +43,7 @@ function readJsonFile(path, options) {
|
|
41
43
|
* @returns
|
42
44
|
*/
|
43
45
|
function readYamlFile(path, options) {
|
44
|
-
const content = (0,
|
46
|
+
const content = (0, node_fs_1.readFileSync)(path, 'utf-8');
|
45
47
|
const { load } = require('@zkochan/js-yaml');
|
46
48
|
return load(content, { ...options, filename: path });
|
47
49
|
}
|
@@ -53,12 +55,27 @@ function readYamlFile(path, options) {
|
|
53
55
|
* @param options JSON serialize options
|
54
56
|
*/
|
55
57
|
function writeJsonFile(path, data, options) {
|
56
|
-
(0,
|
58
|
+
(0, node_fs_1.mkdirSync)((0, path_1.dirname)(path), { recursive: true });
|
57
59
|
const serializedJson = (0, json_1.serializeJson)(data, options);
|
58
60
|
const content = options?.appendNewLine
|
59
61
|
? `${serializedJson}\n`
|
60
62
|
: serializedJson;
|
61
|
-
(0,
|
63
|
+
(0, node_fs_1.writeFileSync)(path, content, { encoding: 'utf-8' });
|
64
|
+
}
|
65
|
+
/**
|
66
|
+
* Serializes the given data to JSON and writes it to a file asynchronously.
|
67
|
+
*
|
68
|
+
* @param path A path to a file.
|
69
|
+
* @param data data which should be serialized to JSON and written to the file
|
70
|
+
* @param options JSON serialize options
|
71
|
+
*/
|
72
|
+
async function writeJsonFileAsync(path, data, options) {
|
73
|
+
await (0, promises_1.mkdir)((0, path_1.dirname)(path), { recursive: true });
|
74
|
+
const serializedJson = (0, json_1.serializeJson)(data, options);
|
75
|
+
const content = options?.appendNewLine
|
76
|
+
? `${serializedJson}\n`
|
77
|
+
: serializedJson;
|
78
|
+
await (0, promises_1.writeFile)(path, content, { encoding: 'utf-8' });
|
62
79
|
}
|
63
80
|
/**
|
64
81
|
* Check if a directory exists
|
@@ -66,7 +83,7 @@ function writeJsonFile(path, data, options) {
|
|
66
83
|
*/
|
67
84
|
function directoryExists(path) {
|
68
85
|
try {
|
69
|
-
return (0,
|
86
|
+
return (0, node_fs_1.statSync)(path).isDirectory();
|
70
87
|
}
|
71
88
|
catch {
|
72
89
|
return false;
|
@@ -78,14 +95,14 @@ function directoryExists(path) {
|
|
78
95
|
*/
|
79
96
|
function fileExists(path) {
|
80
97
|
try {
|
81
|
-
return (0,
|
98
|
+
return (0, node_fs_1.statSync)(path).isFile();
|
82
99
|
}
|
83
100
|
catch {
|
84
101
|
return false;
|
85
102
|
}
|
86
103
|
}
|
87
104
|
function createDirectory(path) {
|
88
|
-
(0,
|
105
|
+
(0, node_fs_1.mkdirSync)(path, { recursive: true });
|
89
106
|
}
|
90
107
|
function isRelativePath(path) {
|
91
108
|
return (path === '.' ||
|
@@ -102,9 +119,9 @@ function isRelativePath(path) {
|
|
102
119
|
*/
|
103
120
|
async function extractFileFromTarball(tarballPath, file, destinationFilePath) {
|
104
121
|
return new Promise((resolve, reject) => {
|
105
|
-
(0,
|
122
|
+
(0, node_fs_1.mkdirSync)((0, path_1.dirname)(destinationFilePath), { recursive: true });
|
106
123
|
var tarExtractStream = tar.extract();
|
107
|
-
const destinationFileStream = (0,
|
124
|
+
const destinationFileStream = (0, node_fs_1.createWriteStream)(destinationFilePath);
|
108
125
|
let isFileExtracted = false;
|
109
126
|
tarExtractStream.on('entry', function (header, stream, next) {
|
110
127
|
if (header.name === file) {
|
@@ -126,9 +143,9 @@ async function extractFileFromTarball(tarballPath, file, destinationFilePath) {
|
|
126
143
|
reject();
|
127
144
|
}
|
128
145
|
});
|
129
|
-
(0,
|
146
|
+
(0, node_fs_1.createReadStream)(tarballPath).pipe((0, zlib_1.createGunzip)()).pipe(tarExtractStream);
|
130
147
|
});
|
131
148
|
}
|
132
149
|
function readFileIfExisting(path) {
|
133
|
-
return (0,
|
150
|
+
return (0, node_fs_1.existsSync)(path) ? (0, node_fs_1.readFileSync)(path, 'utf-8') : '';
|
134
151
|
}
|
package/src/utils/ignore.js
CHANGED
@@ -4,7 +4,7 @@ exports.ALWAYS_IGNORE = void 0;
|
|
4
4
|
exports.getIgnoredGlobs = getIgnoredGlobs;
|
5
5
|
exports.getAlwaysIgnore = getAlwaysIgnore;
|
6
6
|
exports.getIgnoreObject = getIgnoreObject;
|
7
|
-
const
|
7
|
+
const node_fs_1 = require("node:fs");
|
8
8
|
const ignore_1 = require("ignore");
|
9
9
|
const fileutils_1 = require("./fileutils");
|
10
10
|
const path_1 = require("./path");
|
@@ -48,7 +48,7 @@ function getIgnoreObject(root = workspace_root_1.workspaceRoot) {
|
|
48
48
|
function getIgnoredGlobsFromFile(file, root) {
|
49
49
|
try {
|
50
50
|
const results = [];
|
51
|
-
const contents = (0,
|
51
|
+
const contents = (0, node_fs_1.readFileSync)(file, 'utf-8');
|
52
52
|
const lines = contents.split('\n');
|
53
53
|
for (const line of lines) {
|
54
54
|
const trimmed = line.trim();
|
@@ -15,7 +15,7 @@ exports.packageRegistryView = packageRegistryView;
|
|
15
15
|
exports.packageRegistryPack = packageRegistryPack;
|
16
16
|
const child_process_1 = require("child_process");
|
17
17
|
const fs_1 = require("fs");
|
18
|
-
const
|
18
|
+
const promises_1 = require("node:fs/promises");
|
19
19
|
const path_1 = require("path");
|
20
20
|
const semver_1 = require("semver");
|
21
21
|
const tmp_1 = require("tmp");
|
@@ -301,7 +301,7 @@ function createTempNpmDirectory() {
|
|
301
301
|
copyPackageManagerConfigurationFiles(workspace_root_1.workspaceRoot, dir);
|
302
302
|
const cleanup = async () => {
|
303
303
|
try {
|
304
|
-
await (0,
|
304
|
+
await (0, promises_1.rm)(dir, { recursive: true, force: true });
|
305
305
|
}
|
306
306
|
catch {
|
307
307
|
// It's okay if this fails, the OS will clean it up eventually
|
@@ -47,7 +47,7 @@ function listAlsoAvailableCorePlugins(installedPlugins) {
|
|
47
47
|
}
|
48
48
|
}
|
49
49
|
function listPowerpackPlugins() {
|
50
|
-
const powerpackLink = 'https://nx.dev/plugin-registry';
|
50
|
+
const powerpackLink = 'https://nx.dev/plugin-registry#powerpack';
|
51
51
|
output_1.output.log({
|
52
52
|
title: `Available Powerpack Plugins: ${powerpackLink}`,
|
53
53
|
});
|