nx 20.5.0-canary.20250201-05e0679 → 21.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +12 -11
- package/plugins/package-json.js +2 -1
- package/schemas/nx-schema.json +7 -0
- package/src/command-line/graph/graph.js +2 -0
- package/src/commands-runner/get-command-projects.js +17 -2
- package/src/config/schema-utils.js +4 -4
- package/src/config/task-graph.d.ts +5 -0
- package/src/config/workspace-json-project-json.d.ts +6 -0
- package/src/executors/run-commands/run-commands.impl.d.ts +16 -13
- package/src/executors/run-commands/run-commands.impl.js +24 -263
- package/src/executors/run-commands/running-tasks.d.ts +38 -0
- package/src/executors/run-commands/running-tasks.js +349 -0
- package/src/native/index.d.ts +1 -0
- package/src/native/nx.wasm32-wasi.wasm +0 -0
- package/src/plugins/js/project-graph/build-dependencies/target-project-locator.d.ts +2 -1
- package/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +11 -3
- package/src/plugins/js/utils/packages.d.ts +6 -1
- package/src/plugins/js/utils/packages.js +59 -12
- package/src/plugins/package-json/create-nodes.d.ts +3 -3
- package/src/plugins/package-json/create-nodes.js +8 -12
- package/src/project-graph/file-utils.js +2 -1
- package/src/project-graph/plugins/resolve-plugin.js +11 -2
- package/src/tasks-runner/create-task-graph.d.ts +3 -0
- package/src/tasks-runner/create-task-graph.js +36 -5
- package/src/tasks-runner/forked-process-task-runner.d.ts +6 -12
- package/src/tasks-runner/forked-process-task-runner.js +110 -263
- package/src/tasks-runner/init-tasks-runner.js +4 -0
- package/src/tasks-runner/pseudo-terminal.d.ts +7 -1
- package/src/tasks-runner/pseudo-terminal.js +26 -12
- package/src/tasks-runner/running-tasks/batch-process.d.ts +14 -0
- package/src/tasks-runner/running-tasks/batch-process.js +70 -0
- package/src/tasks-runner/running-tasks/node-child-process.d.ts +36 -0
- package/src/tasks-runner/running-tasks/node-child-process.js +184 -0
- package/src/tasks-runner/running-tasks/noop-child-process.d.ts +15 -0
- package/src/tasks-runner/running-tasks/noop-child-process.js +19 -0
- package/src/tasks-runner/running-tasks/running-task.d.ts +8 -0
- package/src/tasks-runner/running-tasks/running-task.js +6 -0
- package/src/tasks-runner/task-orchestrator.d.ts +7 -1
- package/src/tasks-runner/task-orchestrator.js +137 -82
- package/src/tasks-runner/tasks-schedule.js +5 -1
- package/src/tasks-runner/utils.d.ts +0 -8
- package/src/tasks-runner/utils.js +12 -4
- package/src/utils/package-json.d.ts +1 -1
- package/src/utils/package-json.js +4 -2
@@ -78,28 +78,42 @@ class PseudoTtyProcess {
|
|
78
78
|
this.childProcess = childProcess;
|
79
79
|
this.isAlive = true;
|
80
80
|
this.exitCallbacks = [];
|
81
|
+
this.outputCallbacks = [];
|
82
|
+
this.terminalOutput = '';
|
83
|
+
childProcess.onOutput((output) => {
|
84
|
+
this.terminalOutput += output;
|
85
|
+
this.outputCallbacks.forEach((cb) => cb(output));
|
86
|
+
});
|
81
87
|
childProcess.onExit((message) => {
|
82
88
|
this.isAlive = false;
|
83
|
-
const
|
84
|
-
|
89
|
+
const code = messageToCode(message);
|
90
|
+
childProcess.cleanup();
|
91
|
+
this.exitCallbacks.forEach((cb) => cb(code));
|
92
|
+
});
|
93
|
+
}
|
94
|
+
async getResults() {
|
95
|
+
return new Promise((res) => {
|
96
|
+
this.onExit((code) => {
|
97
|
+
res({ code, terminalOutput: this.terminalOutput });
|
98
|
+
});
|
85
99
|
});
|
86
100
|
}
|
87
101
|
onExit(callback) {
|
88
102
|
this.exitCallbacks.push(callback);
|
89
103
|
}
|
90
104
|
onOutput(callback) {
|
91
|
-
this.
|
105
|
+
this.outputCallbacks.push(callback);
|
92
106
|
}
|
93
107
|
kill() {
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
108
|
+
if (this.isAlive) {
|
109
|
+
try {
|
110
|
+
this.childProcess.kill();
|
111
|
+
}
|
112
|
+
catch {
|
113
|
+
// when the child process completes before we explicitly call kill, this will throw
|
114
|
+
// do nothing
|
115
|
+
}
|
116
|
+
finally {
|
103
117
|
this.isAlive = false;
|
104
118
|
}
|
105
119
|
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import { BatchResults } from '../batch/batch-messages';
|
2
|
+
import { ChildProcess, Serializable } from 'child_process';
|
3
|
+
export declare class BatchProcess {
|
4
|
+
private childProcess;
|
5
|
+
private executorName;
|
6
|
+
private exitCallbacks;
|
7
|
+
private resultsCallbacks;
|
8
|
+
constructor(childProcess: ChildProcess, executorName: string);
|
9
|
+
onExit(cb: (code: number) => void): void;
|
10
|
+
onResults(cb: (results: BatchResults) => void): void;
|
11
|
+
getResults(): Promise<BatchResults>;
|
12
|
+
send(message: Serializable): void;
|
13
|
+
kill(signal?: NodeJS.Signals | number): void;
|
14
|
+
}
|
@@ -0,0 +1,70 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.BatchProcess = void 0;
|
4
|
+
const batch_messages_1 = require("../batch/batch-messages");
|
5
|
+
const exit_codes_1 = require("../../utils/exit-codes");
|
6
|
+
class BatchProcess {
|
7
|
+
constructor(childProcess, executorName) {
|
8
|
+
this.childProcess = childProcess;
|
9
|
+
this.executorName = executorName;
|
10
|
+
this.exitCallbacks = [];
|
11
|
+
this.resultsCallbacks = [];
|
12
|
+
this.childProcess.on('message', (message) => {
|
13
|
+
switch (message.type) {
|
14
|
+
case batch_messages_1.BatchMessageType.CompleteBatchExecution: {
|
15
|
+
for (const cb of this.resultsCallbacks) {
|
16
|
+
cb(message.results);
|
17
|
+
}
|
18
|
+
break;
|
19
|
+
}
|
20
|
+
case batch_messages_1.BatchMessageType.RunTasks: {
|
21
|
+
break;
|
22
|
+
}
|
23
|
+
default: {
|
24
|
+
// Re-emit any non-batch messages from the task process
|
25
|
+
if (process.send) {
|
26
|
+
process.send(message);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
});
|
31
|
+
this.childProcess.once('exit', (code, signal) => {
|
32
|
+
if (code === null)
|
33
|
+
code = (0, exit_codes_1.signalToCode)(signal);
|
34
|
+
for (const cb of this.exitCallbacks) {
|
35
|
+
cb(code);
|
36
|
+
}
|
37
|
+
});
|
38
|
+
}
|
39
|
+
onExit(cb) {
|
40
|
+
this.exitCallbacks.push(cb);
|
41
|
+
}
|
42
|
+
onResults(cb) {
|
43
|
+
this.resultsCallbacks.push(cb);
|
44
|
+
}
|
45
|
+
async getResults() {
|
46
|
+
return Promise.race([
|
47
|
+
new Promise((_, rej) => {
|
48
|
+
this.onExit((code) => {
|
49
|
+
if (code !== 0) {
|
50
|
+
rej(new Error(`"${this.executorName}" exited unexpectedly with code: ${code}`));
|
51
|
+
}
|
52
|
+
});
|
53
|
+
}),
|
54
|
+
new Promise((res) => {
|
55
|
+
this.onResults(res);
|
56
|
+
}),
|
57
|
+
]);
|
58
|
+
}
|
59
|
+
send(message) {
|
60
|
+
if (this.childProcess.connected) {
|
61
|
+
this.childProcess.send(message);
|
62
|
+
}
|
63
|
+
}
|
64
|
+
kill(signal) {
|
65
|
+
if (this.childProcess.connected) {
|
66
|
+
this.childProcess.kill(signal);
|
67
|
+
}
|
68
|
+
}
|
69
|
+
}
|
70
|
+
exports.BatchProcess = BatchProcess;
|
@@ -0,0 +1,36 @@
|
|
1
|
+
import { ChildProcess, Serializable } from 'child_process';
|
2
|
+
import { RunningTask } from './running-task';
|
3
|
+
export declare class NodeChildProcessWithNonDirectOutput implements RunningTask {
|
4
|
+
private childProcess;
|
5
|
+
private terminalOutput;
|
6
|
+
private exitCallbacks;
|
7
|
+
constructor(childProcess: ChildProcess, { streamOutput, prefix }: {
|
8
|
+
streamOutput: boolean;
|
9
|
+
prefix: string;
|
10
|
+
});
|
11
|
+
onExit(cb: (code: number, terminalOutput: string) => void): void;
|
12
|
+
getResults(): Promise<{
|
13
|
+
code: number;
|
14
|
+
terminalOutput: string;
|
15
|
+
}>;
|
16
|
+
send(message: Serializable): void;
|
17
|
+
kill(signal?: NodeJS.Signals | number): void;
|
18
|
+
}
|
19
|
+
export declare class NodeChildProcessWithDirectOutput implements RunningTask {
|
20
|
+
private childProcess;
|
21
|
+
private temporaryOutputPath;
|
22
|
+
private terminalOutput;
|
23
|
+
private exitCallbacks;
|
24
|
+
private exited;
|
25
|
+
private exitCode;
|
26
|
+
constructor(childProcess: ChildProcess, temporaryOutputPath: string);
|
27
|
+
send(message: Serializable): void;
|
28
|
+
onExit(cb: (code: number, signal: NodeJS.Signals) => void): void;
|
29
|
+
getResults(): Promise<{
|
30
|
+
code: number;
|
31
|
+
terminalOutput: string;
|
32
|
+
}>;
|
33
|
+
waitForExit(): Promise<void>;
|
34
|
+
getTerminalOutput(): string;
|
35
|
+
kill(signal?: NodeJS.Signals | number): void;
|
36
|
+
}
|
@@ -0,0 +1,184 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.NodeChildProcessWithDirectOutput = exports.NodeChildProcessWithNonDirectOutput = void 0;
|
4
|
+
const exit_codes_1 = require("../../utils/exit-codes");
|
5
|
+
const stream_1 = require("stream");
|
6
|
+
const chalk = require("chalk");
|
7
|
+
const fs_1 = require("fs");
|
8
|
+
class NodeChildProcessWithNonDirectOutput {
|
9
|
+
constructor(childProcess, { streamOutput, prefix }) {
|
10
|
+
this.childProcess = childProcess;
|
11
|
+
this.terminalOutput = '';
|
12
|
+
this.exitCallbacks = [];
|
13
|
+
if (streamOutput) {
|
14
|
+
if (process.env.NX_PREFIX_OUTPUT === 'true') {
|
15
|
+
const color = getColor(prefix);
|
16
|
+
const prefixText = `${prefix}:`;
|
17
|
+
this.childProcess.stdout
|
18
|
+
.pipe(logClearLineToPrefixTransformer(color.bold(prefixText) + ' '))
|
19
|
+
.pipe(addPrefixTransformer(color.bold(prefixText)))
|
20
|
+
.pipe(process.stdout);
|
21
|
+
this.childProcess.stderr
|
22
|
+
.pipe(logClearLineToPrefixTransformer(color(prefixText) + ' '))
|
23
|
+
.pipe(addPrefixTransformer(color(prefixText)))
|
24
|
+
.pipe(process.stderr);
|
25
|
+
}
|
26
|
+
else {
|
27
|
+
this.childProcess.stdout
|
28
|
+
.pipe(addPrefixTransformer())
|
29
|
+
.pipe(process.stdout);
|
30
|
+
this.childProcess.stderr
|
31
|
+
.pipe(addPrefixTransformer())
|
32
|
+
.pipe(process.stderr);
|
33
|
+
}
|
34
|
+
}
|
35
|
+
this.childProcess.on('exit', (code, signal) => {
|
36
|
+
if (code === null)
|
37
|
+
code = (0, exit_codes_1.signalToCode)(signal);
|
38
|
+
for (const cb of this.exitCallbacks) {
|
39
|
+
cb(code, this.terminalOutput);
|
40
|
+
}
|
41
|
+
});
|
42
|
+
// Re-emit any messages from the task process
|
43
|
+
this.childProcess.on('message', (message) => {
|
44
|
+
if (process.send) {
|
45
|
+
process.send(message);
|
46
|
+
}
|
47
|
+
});
|
48
|
+
this.childProcess.stdout.on('data', (chunk) => {
|
49
|
+
this.terminalOutput += chunk.toString();
|
50
|
+
});
|
51
|
+
this.childProcess.stderr.on('data', (chunk) => {
|
52
|
+
this.terminalOutput += chunk.toString();
|
53
|
+
});
|
54
|
+
}
|
55
|
+
onExit(cb) {
|
56
|
+
this.exitCallbacks.push(cb);
|
57
|
+
}
|
58
|
+
async getResults() {
|
59
|
+
return new Promise((res) => {
|
60
|
+
this.onExit((code, terminalOutput) => {
|
61
|
+
res({ code, terminalOutput });
|
62
|
+
});
|
63
|
+
});
|
64
|
+
}
|
65
|
+
send(message) {
|
66
|
+
if (this.childProcess.connected) {
|
67
|
+
this.childProcess.send(message);
|
68
|
+
}
|
69
|
+
}
|
70
|
+
kill(signal) {
|
71
|
+
if (this.childProcess.connected) {
|
72
|
+
this.childProcess.kill(signal);
|
73
|
+
}
|
74
|
+
}
|
75
|
+
}
|
76
|
+
exports.NodeChildProcessWithNonDirectOutput = NodeChildProcessWithNonDirectOutput;
|
77
|
+
function addPrefixTransformer(prefix) {
|
78
|
+
const newLineSeparator = process.platform.startsWith('win') ? '\r\n' : '\n';
|
79
|
+
return new stream_1.Transform({
|
80
|
+
transform(chunk, _encoding, callback) {
|
81
|
+
const list = chunk.toString().split(/\r\n|[\n\v\f\r\x85\u2028\u2029]/g);
|
82
|
+
list
|
83
|
+
.filter(Boolean)
|
84
|
+
.forEach((m) => this.push(prefix ? prefix + ' ' + m + newLineSeparator : m + newLineSeparator));
|
85
|
+
callback();
|
86
|
+
},
|
87
|
+
});
|
88
|
+
}
|
89
|
+
const colors = [
|
90
|
+
chalk.green,
|
91
|
+
chalk.greenBright,
|
92
|
+
chalk.red,
|
93
|
+
chalk.redBright,
|
94
|
+
chalk.cyan,
|
95
|
+
chalk.cyanBright,
|
96
|
+
chalk.yellow,
|
97
|
+
chalk.yellowBright,
|
98
|
+
chalk.magenta,
|
99
|
+
chalk.magentaBright,
|
100
|
+
];
|
101
|
+
function getColor(projectName) {
|
102
|
+
let code = 0;
|
103
|
+
for (let i = 0; i < projectName.length; ++i) {
|
104
|
+
code += projectName.charCodeAt(i);
|
105
|
+
}
|
106
|
+
const colorIndex = code % colors.length;
|
107
|
+
return colors[colorIndex];
|
108
|
+
}
|
109
|
+
/**
|
110
|
+
* Prevents terminal escape sequence from clearing line prefix.
|
111
|
+
*/
|
112
|
+
function logClearLineToPrefixTransformer(prefix) {
|
113
|
+
let prevChunk = null;
|
114
|
+
return new stream_1.Transform({
|
115
|
+
transform(chunk, _encoding, callback) {
|
116
|
+
if (prevChunk && prevChunk.toString() === '\x1b[2K') {
|
117
|
+
chunk = chunk.toString().replace(/\x1b\[1G/g, (m) => m + prefix);
|
118
|
+
}
|
119
|
+
this.push(chunk);
|
120
|
+
prevChunk = chunk;
|
121
|
+
callback();
|
122
|
+
},
|
123
|
+
});
|
124
|
+
}
|
125
|
+
class NodeChildProcessWithDirectOutput {
|
126
|
+
constructor(childProcess, temporaryOutputPath) {
|
127
|
+
this.childProcess = childProcess;
|
128
|
+
this.temporaryOutputPath = temporaryOutputPath;
|
129
|
+
this.exitCallbacks = [];
|
130
|
+
this.exited = false;
|
131
|
+
// Re-emit any messages from the task process
|
132
|
+
this.childProcess.on('message', (message) => {
|
133
|
+
if (process.send) {
|
134
|
+
process.send(message);
|
135
|
+
}
|
136
|
+
});
|
137
|
+
this.childProcess.on('exit', (code, signal) => {
|
138
|
+
if (code === null)
|
139
|
+
code = (0, exit_codes_1.signalToCode)(signal);
|
140
|
+
this.exited = true;
|
141
|
+
this.exitCode = code;
|
142
|
+
for (const cb of this.exitCallbacks) {
|
143
|
+
cb(code, signal);
|
144
|
+
}
|
145
|
+
});
|
146
|
+
}
|
147
|
+
send(message) {
|
148
|
+
if (this.childProcess.connected) {
|
149
|
+
this.childProcess.send(message);
|
150
|
+
}
|
151
|
+
}
|
152
|
+
onExit(cb) {
|
153
|
+
this.exitCallbacks.push(cb);
|
154
|
+
}
|
155
|
+
async getResults() {
|
156
|
+
const terminalOutput = this.getTerminalOutput();
|
157
|
+
if (this.exited) {
|
158
|
+
return Promise.resolve({
|
159
|
+
code: this.exitCode,
|
160
|
+
terminalOutput,
|
161
|
+
});
|
162
|
+
}
|
163
|
+
await this.waitForExit();
|
164
|
+
return Promise.resolve({
|
165
|
+
code: this.exitCode,
|
166
|
+
terminalOutput,
|
167
|
+
});
|
168
|
+
}
|
169
|
+
waitForExit() {
|
170
|
+
return new Promise((res) => {
|
171
|
+
this.onExit(() => res());
|
172
|
+
});
|
173
|
+
}
|
174
|
+
getTerminalOutput() {
|
175
|
+
this.terminalOutput ??= (0, fs_1.readFileSync)(this.temporaryOutputPath).toString();
|
176
|
+
return this.terminalOutput;
|
177
|
+
}
|
178
|
+
kill(signal) {
|
179
|
+
if (this.childProcess.connected) {
|
180
|
+
this.childProcess.kill(signal);
|
181
|
+
}
|
182
|
+
}
|
183
|
+
}
|
184
|
+
exports.NodeChildProcessWithDirectOutput = NodeChildProcessWithDirectOutput;
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { RunningTask } from './running-task';
|
2
|
+
export declare class NoopChildProcess implements RunningTask {
|
3
|
+
private results;
|
4
|
+
constructor(results: {
|
5
|
+
code: number;
|
6
|
+
terminalOutput: string;
|
7
|
+
});
|
8
|
+
send(): void;
|
9
|
+
getResults(): Promise<{
|
10
|
+
code: number;
|
11
|
+
terminalOutput: string;
|
12
|
+
}>;
|
13
|
+
kill(): void;
|
14
|
+
onExit(cb: (code: number) => void): void;
|
15
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.NoopChildProcess = void 0;
|
4
|
+
class NoopChildProcess {
|
5
|
+
constructor(results) {
|
6
|
+
this.results = results;
|
7
|
+
}
|
8
|
+
send() { }
|
9
|
+
async getResults() {
|
10
|
+
return this.results;
|
11
|
+
}
|
12
|
+
kill() {
|
13
|
+
return;
|
14
|
+
}
|
15
|
+
onExit(cb) {
|
16
|
+
cb(this.results.code);
|
17
|
+
}
|
18
|
+
}
|
19
|
+
exports.NoopChildProcess = NoopChildProcess;
|
@@ -5,6 +5,7 @@ import { ProjectGraph } from '../config/project-graph';
|
|
5
5
|
import { TaskGraph } from '../config/task-graph';
|
6
6
|
import { DaemonClient } from '../daemon/client/client';
|
7
7
|
import { NxJsonConfiguration } from '../config/nx-json';
|
8
|
+
import { NxArgs } from '../utils/command-line-utils';
|
8
9
|
export declare class TaskOrchestrator {
|
9
10
|
private readonly hasher;
|
10
11
|
private readonly initiatingProject;
|
@@ -27,7 +28,9 @@ export declare class TaskOrchestrator {
|
|
27
28
|
private waitingForTasks;
|
28
29
|
private groups;
|
29
30
|
private bailed;
|
30
|
-
|
31
|
+
private runningContinuousTasks;
|
32
|
+
private cleaningUp;
|
33
|
+
constructor(hasher: TaskHasher, initiatingProject: string | undefined, projectGraph: ProjectGraph, taskGraph: TaskGraph, nxJson: NxJsonConfiguration, options: NxArgs & DefaultTasksRunnerOptions, bail: boolean, daemon: DaemonClient, outputStyle: string);
|
31
34
|
run(): Promise<{
|
32
35
|
[id: string]: TaskStatus;
|
33
36
|
}>;
|
@@ -40,7 +43,9 @@ export declare class TaskOrchestrator {
|
|
40
43
|
private applyFromCacheOrRunBatch;
|
41
44
|
private runBatch;
|
42
45
|
private applyFromCacheOrRunTask;
|
46
|
+
private runTask;
|
43
47
|
private runTaskInForkedProcess;
|
48
|
+
private startContinuousTask;
|
44
49
|
private preRunSteps;
|
45
50
|
private postRunSteps;
|
46
51
|
private complete;
|
@@ -50,4 +55,5 @@ export declare class TaskOrchestrator {
|
|
50
55
|
private openGroup;
|
51
56
|
private shouldCopyOutputsFromCache;
|
52
57
|
private recordOutputsHash;
|
58
|
+
private cleanup;
|
53
59
|
}
|