nx 18.1.1 → 18.1.3
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 -12
- package/src/command-line/add/add.js +1 -1
- package/src/command-line/init/init-v2.js +43 -31
- package/src/command-line/run/run.js +15 -5
- package/src/executors/run-commands/run-commands.impl.js +15 -9
- package/src/executors/run-script/run-script.impl.js +1 -1
- package/src/plugins/js/index.js +1 -1
- package/src/plugins/js/lock-file/lock-file.d.ts +2 -2
- package/src/plugins/js/lock-file/lock-file.js +2 -2
- package/src/tasks-runner/cache.js +6 -3
- package/src/tasks-runner/forked-process-task-runner.d.ts +2 -1
- package/src/tasks-runner/forked-process-task-runner.js +19 -8
- package/src/tasks-runner/pseudo-terminal.d.ts +2 -1
- package/src/tasks-runner/pseudo-terminal.js +27 -1
- package/src/tasks-runner/task-orchestrator.js +4 -22
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "nx",
|
3
|
-
"version": "18.1.
|
3
|
+
"version": "18.1.3",
|
4
4
|
"private": false,
|
5
5
|
"description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
|
6
6
|
"repository": {
|
@@ -66,7 +66,7 @@
|
|
66
66
|
"yargs-parser": "21.1.1",
|
67
67
|
"node-machine-id": "1.1.12",
|
68
68
|
"ora": "5.3.0",
|
69
|
-
"@nrwl/tao": "18.1.
|
69
|
+
"@nrwl/tao": "18.1.3"
|
70
70
|
},
|
71
71
|
"peerDependencies": {
|
72
72
|
"@swc-node/register": "^1.8.0",
|
@@ -81,16 +81,16 @@
|
|
81
81
|
}
|
82
82
|
},
|
83
83
|
"optionalDependencies": {
|
84
|
-
"@nx/nx-darwin-x64": "18.1.
|
85
|
-
"@nx/nx-darwin-arm64": "18.1.
|
86
|
-
"@nx/nx-linux-x64-gnu": "18.1.
|
87
|
-
"@nx/nx-linux-x64-musl": "18.1.
|
88
|
-
"@nx/nx-win32-x64-msvc": "18.1.
|
89
|
-
"@nx/nx-linux-arm64-gnu": "18.1.
|
90
|
-
"@nx/nx-linux-arm64-musl": "18.1.
|
91
|
-
"@nx/nx-linux-arm-gnueabihf": "18.1.
|
92
|
-
"@nx/nx-win32-arm64-msvc": "18.1.
|
93
|
-
"@nx/nx-freebsd-x64": "18.1.
|
84
|
+
"@nx/nx-darwin-x64": "18.1.3",
|
85
|
+
"@nx/nx-darwin-arm64": "18.1.3",
|
86
|
+
"@nx/nx-linux-x64-gnu": "18.1.3",
|
87
|
+
"@nx/nx-linux-x64-musl": "18.1.3",
|
88
|
+
"@nx/nx-win32-x64-msvc": "18.1.3",
|
89
|
+
"@nx/nx-linux-arm64-gnu": "18.1.3",
|
90
|
+
"@nx/nx-linux-arm64-musl": "18.1.3",
|
91
|
+
"@nx/nx-linux-arm-gnueabihf": "18.1.3",
|
92
|
+
"@nx/nx-win32-arm64-msvc": "18.1.3",
|
93
|
+
"@nx/nx-freebsd-x64": "18.1.3"
|
94
94
|
},
|
95
95
|
"nx-migrations": {
|
96
96
|
"migrations": "./migrations.json",
|
@@ -55,7 +55,7 @@ async function installPackage(pkgName, version) {
|
|
55
55
|
nxJson.installation.plugins[pkgName] = version;
|
56
56
|
(0, fileutils_1.writeJsonFile)('nx.json', nxJson);
|
57
57
|
try {
|
58
|
-
await (0, child_process_2.runNxAsync)('');
|
58
|
+
await (0, child_process_2.runNxAsync)('--help', { silent: true });
|
59
59
|
}
|
60
60
|
catch (e) {
|
61
61
|
// revert adding the plugin to nx.json
|
@@ -32,6 +32,12 @@ async function initHandler(options) {
|
|
32
32
|
console.log('Setting Nx up installation in `.nx`. You can run Nx commands like: `./nx.bat --help`');
|
33
33
|
}
|
34
34
|
(0, add_nx_scripts_1.generateDotNxSetup)(version);
|
35
|
+
const { plugins } = await detectPlugins();
|
36
|
+
plugins.forEach((plugin) => {
|
37
|
+
(0, child_process_2.execSync)(`./nx add ${plugin}`, {
|
38
|
+
stdio: 'inherit',
|
39
|
+
});
|
40
|
+
});
|
35
41
|
// invokes the wrapper, thus invoking the initial installation process
|
36
42
|
(0, child_process_1.runNxSync)('--version', { stdio: 'ignore' });
|
37
43
|
return;
|
@@ -45,8 +51,8 @@ async function initHandler(options) {
|
|
45
51
|
return;
|
46
52
|
}
|
47
53
|
output_1.output.log({ title: '🧐 Checking dependencies' });
|
48
|
-
const
|
49
|
-
if (!
|
54
|
+
const { plugins, updatePackageScripts } = await detectPlugins();
|
55
|
+
if (!plugins.length) {
|
50
56
|
// If no plugins are detected/chosen, guide users to setup
|
51
57
|
// their targetDefaults correctly so their package scripts will work.
|
52
58
|
const packageJson = (0, fileutils_1.readJsonFile)('package.json');
|
@@ -66,19 +72,17 @@ async function initHandler(options) {
|
|
66
72
|
const pmc = (0, package_manager_1.getPackageManagerCommand)();
|
67
73
|
(0, utils_1.createNxJsonFile)(repoRoot, [], [], {});
|
68
74
|
(0, utils_1.updateGitIgnore)(repoRoot);
|
69
|
-
(0, utils_1.addDepsToPackageJson)(repoRoot,
|
75
|
+
(0, utils_1.addDepsToPackageJson)(repoRoot, plugins);
|
70
76
|
output_1.output.log({ title: '📦 Installing Nx' });
|
71
77
|
(0, utils_1.runInstall)(repoRoot, pmc);
|
72
78
|
output_1.output.log({ title: '🔨 Configuring plugins' });
|
73
|
-
for (const plugin of
|
74
|
-
(0, child_process_2.execSync)(`${pmc.exec} nx g ${plugin}:init --keepExistingVersions ${
|
75
|
-
? '--updatePackageScripts'
|
76
|
-
: ''} --no-interactive`, {
|
79
|
+
for (const plugin of plugins) {
|
80
|
+
(0, child_process_2.execSync)(`${pmc.exec} nx g ${plugin}:init --keepExistingVersions ${updatePackageScripts ? '--updatePackageScripts' : ''} --no-interactive`, {
|
77
81
|
stdio: [0, 1, 2],
|
78
82
|
cwd: repoRoot,
|
79
83
|
});
|
80
84
|
}
|
81
|
-
if (!
|
85
|
+
if (!updatePackageScripts) {
|
82
86
|
const rootPackageJsonPath = (0, path_1.join)(repoRoot, 'package.json');
|
83
87
|
const json = (0, fileutils_1.readJsonFile)(rootPackageJsonPath);
|
84
88
|
json.nx = { includedScripts: [] };
|
@@ -146,9 +150,16 @@ async function detectPlugins() {
|
|
146
150
|
}
|
147
151
|
}
|
148
152
|
}
|
153
|
+
if ((0, fs_1.existsSync)('gradlew') || (0, fs_1.existsSync)('gradlew.bat')) {
|
154
|
+
detectedPlugins.add('@nx/gradle');
|
155
|
+
}
|
149
156
|
const plugins = Array.from(detectedPlugins);
|
150
|
-
if (plugins.length === 0)
|
151
|
-
return
|
157
|
+
if (plugins.length === 0) {
|
158
|
+
return {
|
159
|
+
plugins: [],
|
160
|
+
updatePackageScripts: false,
|
161
|
+
};
|
162
|
+
}
|
152
163
|
output_1.output.log({
|
153
164
|
title: `Recommended Plugins:`,
|
154
165
|
bodyLines: [
|
@@ -165,25 +176,26 @@ async function detectPlugins() {
|
|
165
176
|
},
|
166
177
|
]).then((r) => r.plugins);
|
167
178
|
if (pluginsToInstall?.length === 0)
|
168
|
-
return
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
179
|
+
return {
|
180
|
+
plugins: [],
|
181
|
+
updatePackageScripts: false,
|
182
|
+
};
|
183
|
+
const updatePackageScripts = (0, fs_1.existsSync)('package.json') &&
|
184
|
+
(await (0, enquirer_1.prompt)([
|
185
|
+
{
|
186
|
+
name: 'updatePackageScripts',
|
187
|
+
type: 'autocomplete',
|
188
|
+
message: `Do you want to start using Nx in your package.json scripts?`,
|
189
|
+
choices: [
|
190
|
+
{
|
191
|
+
name: 'Yes',
|
192
|
+
},
|
193
|
+
{
|
194
|
+
name: 'No',
|
195
|
+
},
|
196
|
+
],
|
197
|
+
initial: 0,
|
198
|
+
},
|
199
|
+
]).then((r) => r.updatePackageScripts === 'Yes'));
|
200
|
+
return { plugins: pluginsToInstall, updatePackageScripts };
|
189
201
|
}
|
@@ -10,6 +10,7 @@ const configuration_1 = require("../../config/configuration");
|
|
10
10
|
const async_iterator_1 = require("../../utils/async-iterator");
|
11
11
|
const executor_utils_1 = require("./executor-utils");
|
12
12
|
const pseudo_terminal_1 = require("../../tasks-runner/pseudo-terminal");
|
13
|
+
const child_process_1 = require("child_process");
|
13
14
|
function printRunHelp(opts, schema, plugin) {
|
14
15
|
(0, print_help_1.printHelp)(`run ${opts.project}:${opts.target}`, schema, {
|
15
16
|
mode: 'run',
|
@@ -66,13 +67,22 @@ async function printTargetRunHelpInternal({ project, target }, root, projectsCon
|
|
66
67
|
executor === 'run-commands' &&
|
67
68
|
targetConfig.options.command) {
|
68
69
|
const command = targetConfig.options.command.split(' ')[0];
|
69
|
-
const
|
70
|
-
|
71
|
-
const
|
72
|
-
|
70
|
+
const helpCommand = `${command} --help`;
|
71
|
+
if (pseudo_terminal_1.PseudoTerminal.isSupported()) {
|
72
|
+
const terminal = (0, pseudo_terminal_1.getPseudoTerminal)();
|
73
|
+
await new Promise(() => {
|
74
|
+
const cp = terminal.runCommand(helpCommand);
|
75
|
+
cp.onExit((code) => {
|
76
|
+
process.exit(code);
|
77
|
+
});
|
78
|
+
});
|
79
|
+
}
|
80
|
+
else {
|
81
|
+
const cp = (0, child_process_1.exec)(helpCommand);
|
82
|
+
cp.on('exit', (code) => {
|
73
83
|
process.exit(code);
|
74
84
|
});
|
75
|
-
}
|
85
|
+
}
|
76
86
|
}
|
77
87
|
else {
|
78
88
|
process.exit(0);
|
@@ -47,11 +47,10 @@ async function default_1(options, context) {
|
|
47
47
|
!options.parallel) {
|
48
48
|
throw new Error('ERROR: Bad executor config for run-commands - "prefix", "color" and "bgColor" can only be set when "parallel=true".');
|
49
49
|
}
|
50
|
-
const terminal = (0, pseudo_terminal_1.getPseudoTerminal)();
|
51
50
|
try {
|
52
51
|
const result = options.parallel
|
53
|
-
? await runInParallel(
|
54
|
-
: await runSerially(
|
52
|
+
? await runInParallel(normalized, context)
|
53
|
+
: await runSerially(normalized, context);
|
55
54
|
return result;
|
56
55
|
}
|
57
56
|
catch (e) {
|
@@ -62,8 +61,8 @@ async function default_1(options, context) {
|
|
62
61
|
}
|
63
62
|
}
|
64
63
|
exports.default = default_1;
|
65
|
-
async function runInParallel(
|
66
|
-
const procs = options.commands.map((c) => createProcess(
|
64
|
+
async function runInParallel(options, context) {
|
65
|
+
const procs = options.commands.map((c) => createProcess(null, c, options.readyWhen, options.color, calculateCwd(options.cwd, context), options.env ?? {}, true, options.usePty, options.streamOutput).then((result) => ({
|
67
66
|
result,
|
68
67
|
command: c.command,
|
69
68
|
})));
|
@@ -135,7 +134,10 @@ function normalizeOptions(options) {
|
|
135
134
|
});
|
136
135
|
return options;
|
137
136
|
}
|
138
|
-
async function runSerially(
|
137
|
+
async function runSerially(options, context) {
|
138
|
+
const pseudoTerminal = pseudo_terminal_1.PseudoTerminal.isSupported()
|
139
|
+
? (0, pseudo_terminal_1.getPseudoTerminal)()
|
140
|
+
: null;
|
139
141
|
let terminalOutput = '';
|
140
142
|
for (const c of options.commands) {
|
141
143
|
const result = await createProcess(pseudoTerminal, c, undefined, options.color, calculateCwd(options.cwd, context), options.env ?? {}, false, options.usePty, options.streamOutput);
|
@@ -155,8 +157,8 @@ async function createProcess(pseudoTerminal, commandConfig, readyWhen, color, cw
|
|
155
157
|
env = processEnv(color, cwd, env);
|
156
158
|
// The rust runCommand is always a tty, so it will not look nice in parallel and if we need prefixes
|
157
159
|
// currently does not work properly in windows
|
158
|
-
if (
|
159
|
-
process.
|
160
|
+
if (pseudoTerminal &&
|
161
|
+
process.env.NX_NATIVE_COMMAND_RUNNER !== 'false' &&
|
160
162
|
!commandConfig.prefix &&
|
161
163
|
!isParallel &&
|
162
164
|
usePty) {
|
@@ -265,7 +267,11 @@ function processEnv(color, cwd, env) {
|
|
265
267
|
...localEnv,
|
266
268
|
...env,
|
267
269
|
};
|
268
|
-
|
270
|
+
// need to override PATH to make sure we are using the local node_modules
|
271
|
+
if (localEnv.PATH)
|
272
|
+
res.PATH = localEnv.PATH; // UNIX-like
|
273
|
+
if (localEnv.Path)
|
274
|
+
res.Path = localEnv.Path; // Windows
|
269
275
|
if (color) {
|
270
276
|
res.FORCE_COLOR = `${color}`;
|
271
277
|
}
|
@@ -17,7 +17,7 @@ async function default_1(options, context) {
|
|
17
17
|
.filter((p) => !p.startsWith(path.join(context.root, 'node_modules')))
|
18
18
|
.join(path.delimiter) ?? '';
|
19
19
|
env.PATH = filteredPath;
|
20
|
-
if (
|
20
|
+
if (pseudo_terminal_1.PseudoTerminal.isSupported()) {
|
21
21
|
await ptyProcess(command, cwd, env);
|
22
22
|
}
|
23
23
|
else {
|
package/src/plugins/js/index.js
CHANGED
@@ -39,7 +39,7 @@ exports.createNodes = [
|
|
39
39
|
externalNodes: nodes,
|
40
40
|
};
|
41
41
|
}
|
42
|
-
const externalNodes = (0, lock_file_1.getLockFileNodes)(packageManager, lockFileContents, lockFileHash);
|
42
|
+
const externalNodes = (0, lock_file_1.getLockFileNodes)(packageManager, lockFileContents, lockFileHash, context);
|
43
43
|
parsedLockFile.externalNodes = externalNodes;
|
44
44
|
return {
|
45
45
|
externalNodes,
|
@@ -6,12 +6,12 @@ import { PackageManager } from '../../../utils/package-manager';
|
|
6
6
|
import { ProjectGraph, ProjectGraphExternalNode } from '../../../config/project-graph';
|
7
7
|
import { RawProjectGraphDependency } from '../../../project-graph/project-graph-builder';
|
8
8
|
import { PackageJson } from '../../../utils/package-json';
|
9
|
-
import { CreateDependenciesContext } from '../../../utils/nx-plugin';
|
9
|
+
import { CreateDependenciesContext, CreateNodesContext } from '../../../utils/nx-plugin';
|
10
10
|
export declare const LOCKFILES: string[];
|
11
11
|
/**
|
12
12
|
* Parses lock file and maps dependencies and metadata to {@link LockFileGraph}
|
13
13
|
*/
|
14
|
-
export declare function getLockFileNodes(packageManager: PackageManager, contents: string, lockFileHash: string): Record<string, ProjectGraphExternalNode>;
|
14
|
+
export declare function getLockFileNodes(packageManager: PackageManager, contents: string, lockFileHash: string, context: CreateNodesContext): Record<string, ProjectGraphExternalNode>;
|
15
15
|
/**
|
16
16
|
* Parses lock file and maps dependencies and metadata to {@link LockFileGraph}
|
17
17
|
*/
|
@@ -26,10 +26,10 @@ const PNPM_LOCK_PATH = (0, path_1.join)(workspace_root_1.workspaceRoot, PNPM_LOC
|
|
26
26
|
/**
|
27
27
|
* Parses lock file and maps dependencies and metadata to {@link LockFileGraph}
|
28
28
|
*/
|
29
|
-
function getLockFileNodes(packageManager, contents, lockFileHash) {
|
29
|
+
function getLockFileNodes(packageManager, contents, lockFileHash, context) {
|
30
30
|
try {
|
31
31
|
if (packageManager === 'yarn') {
|
32
|
-
const packageJson = (0, fileutils_1.readJsonFile)('package.json');
|
32
|
+
const packageJson = (0, fileutils_1.readJsonFile)((0, path_1.join)(context.workspaceRoot, 'package.json'));
|
33
33
|
return (0, yarn_parser_1.getYarnLockfileNodes)(contents, lockFileHash, packageJson);
|
34
34
|
}
|
35
35
|
if (packageManager === 'pnpm') {
|
@@ -215,18 +215,21 @@ class Cache {
|
|
215
215
|
}
|
216
216
|
tryAndRetry(fn) {
|
217
217
|
let attempts = 0;
|
218
|
-
const baseTimeout =
|
218
|
+
const baseTimeout = 5;
|
219
|
+
// Generate a random number between 2 and 4 to raise to the power of attempts
|
220
|
+
const baseExponent = Math.random() * 2 + 2;
|
219
221
|
const _try = async () => {
|
220
222
|
try {
|
221
223
|
attempts++;
|
222
224
|
return await fn();
|
223
225
|
}
|
224
226
|
catch (e) {
|
225
|
-
|
227
|
+
// Max time is 5 * 4^3 = 20480ms
|
228
|
+
if (attempts === 6) {
|
226
229
|
// After enough attempts, throw the error
|
227
230
|
throw e;
|
228
231
|
}
|
229
|
-
await new Promise((res) => setTimeout(res,
|
232
|
+
await new Promise((res) => setTimeout(res, baseExponent ** attempts));
|
230
233
|
return await _try();
|
231
234
|
}
|
232
235
|
};
|
@@ -22,12 +22,13 @@ export declare class ForkedProcessTaskRunner {
|
|
22
22
|
code: number;
|
23
23
|
terminalOutput: string;
|
24
24
|
}>;
|
25
|
-
forkProcess(task: Task, { temporaryOutputPath, streamOutput,
|
25
|
+
forkProcess(task: Task, { temporaryOutputPath, streamOutput, taskGraph, env, disablePseudoTerminal, }: {
|
26
26
|
temporaryOutputPath: string;
|
27
27
|
streamOutput: boolean;
|
28
28
|
pipeOutput: boolean;
|
29
29
|
taskGraph: TaskGraph;
|
30
30
|
env: NodeJS.ProcessEnv;
|
31
|
+
disablePseudoTerminal: boolean;
|
31
32
|
}): Promise<{
|
32
33
|
code: number;
|
33
34
|
terminalOutput: string;
|
@@ -21,10 +21,14 @@ class ForkedProcessTaskRunner {
|
|
21
21
|
this.cliPath = (0, utils_1.getCliPath)();
|
22
22
|
this.verbose = process.env.NX_VERBOSE_LOGGING === 'true';
|
23
23
|
this.processes = new Set();
|
24
|
-
this.pseudoTerminal =
|
24
|
+
this.pseudoTerminal = pseudo_terminal_1.PseudoTerminal.isSupported()
|
25
|
+
? (0, pseudo_terminal_1.getPseudoTerminal)()
|
26
|
+
: null;
|
25
27
|
}
|
26
28
|
async init() {
|
27
|
-
|
29
|
+
if (this.pseudoTerminal) {
|
30
|
+
await this.pseudoTerminal.init();
|
31
|
+
}
|
28
32
|
this.setupProcessEventListeners();
|
29
33
|
}
|
30
34
|
// TODO: vsavkin delegate terminal output printing
|
@@ -104,11 +108,14 @@ class ForkedProcessTaskRunner {
|
|
104
108
|
env,
|
105
109
|
});
|
106
110
|
}
|
107
|
-
async forkProcess(task, { temporaryOutputPath, streamOutput,
|
111
|
+
async forkProcess(task, { temporaryOutputPath, streamOutput, taskGraph, env, disablePseudoTerminal, }) {
|
108
112
|
const shouldPrefix = streamOutput && process.env.NX_PREFIX_OUTPUT === 'true';
|
109
113
|
// streamOutput would be false if we are running multiple targets
|
110
114
|
// there's no point in running the commands in a pty if we are not streaming the output
|
111
|
-
if (!
|
115
|
+
if (!this.pseudoTerminal ||
|
116
|
+
disablePseudoTerminal ||
|
117
|
+
!streamOutput ||
|
118
|
+
shouldPrefix) {
|
112
119
|
return this.forkProcessWithPrefixAndNotTTY(task, {
|
113
120
|
temporaryOutputPath,
|
114
121
|
streamOutput,
|
@@ -303,13 +310,17 @@ class ForkedProcessTaskRunner {
|
|
303
310
|
(0, fs_1.writeFileSync)(outputPath, content);
|
304
311
|
}
|
305
312
|
setupProcessEventListeners() {
|
306
|
-
this.pseudoTerminal
|
307
|
-
|
308
|
-
|
313
|
+
if (this.pseudoTerminal) {
|
314
|
+
this.pseudoTerminal.onMessageFromChildren((message) => {
|
315
|
+
process.send(message);
|
316
|
+
});
|
317
|
+
}
|
309
318
|
// When the nx process gets a message, it will be sent into the task's process
|
310
319
|
process.on('message', (message) => {
|
311
320
|
// this.publisher.publish(message.toString());
|
312
|
-
this.pseudoTerminal
|
321
|
+
if (this.pseudoTerminal) {
|
322
|
+
this.pseudoTerminal.sendMessageToChildren(message);
|
323
|
+
}
|
313
324
|
this.processes.forEach((p) => {
|
314
325
|
if ('connected' in p && p.connected) {
|
315
326
|
p.send(message);
|
@@ -2,12 +2,13 @@
|
|
2
2
|
import { ChildProcess, RustPseudoTerminal } from '../native';
|
3
3
|
import { PseudoIPCServer } from './pseudo-ipc';
|
4
4
|
import { Serializable } from 'child_process';
|
5
|
-
export declare function getPseudoTerminal(): PseudoTerminal;
|
5
|
+
export declare function getPseudoTerminal(skipSupportCheck?: boolean): PseudoTerminal;
|
6
6
|
export declare class PseudoTerminal {
|
7
7
|
private rustPseudoTerminal;
|
8
8
|
private pseudoIPCPath;
|
9
9
|
private pseudoIPC;
|
10
10
|
private initialized;
|
11
|
+
static isSupported(): boolean;
|
11
12
|
constructor(rustPseudoTerminal: RustPseudoTerminal);
|
12
13
|
init(): Promise<void>;
|
13
14
|
runCommand(command: string, { cwd, jsEnv, quiet, }?: {
|
@@ -4,13 +4,20 @@ exports.PseudoTtyProcessWithSend = exports.PseudoTtyProcess = exports.PseudoTerm
|
|
4
4
|
const native_1 = require("../native");
|
5
5
|
const pseudo_ipc_1 = require("./pseudo-ipc");
|
6
6
|
const socket_utils_1 = require("../daemon/socket-utils");
|
7
|
+
const os = require("os");
|
7
8
|
let pseudoTerminal;
|
8
|
-
function getPseudoTerminal() {
|
9
|
+
function getPseudoTerminal(skipSupportCheck = false) {
|
10
|
+
if (!skipSupportCheck && !PseudoTerminal.isSupported()) {
|
11
|
+
throw new Error('Pseudo terminal is not supported on this platform.');
|
12
|
+
}
|
9
13
|
pseudoTerminal ??= new PseudoTerminal(new native_1.RustPseudoTerminal());
|
10
14
|
return pseudoTerminal;
|
11
15
|
}
|
12
16
|
exports.getPseudoTerminal = getPseudoTerminal;
|
13
17
|
class PseudoTerminal {
|
18
|
+
static isSupported() {
|
19
|
+
return process.stdout.isTTY && supportedPtyPlatform();
|
20
|
+
}
|
14
21
|
constructor(rustPseudoTerminal) {
|
15
22
|
this.rustPseudoTerminal = rustPseudoTerminal;
|
16
23
|
this.pseudoIPCPath = (0, socket_utils_1.FORKED_PROCESS_OS_SOCKET_PATH)(process.pid.toString());
|
@@ -131,3 +138,22 @@ function messageToCode(message) {
|
|
131
138
|
return 1;
|
132
139
|
}
|
133
140
|
}
|
141
|
+
function supportedPtyPlatform() {
|
142
|
+
if (process.platform !== 'win32') {
|
143
|
+
return true;
|
144
|
+
}
|
145
|
+
let windowsVersion = os.release().split('.');
|
146
|
+
let windowsBuild = windowsVersion[2];
|
147
|
+
if (!windowsBuild) {
|
148
|
+
return false;
|
149
|
+
}
|
150
|
+
// Mininum supported Windows version:
|
151
|
+
// https://en.wikipedia.org/wiki/Windows_10,_version_1809
|
152
|
+
// https://learn.microsoft.com/en-us/windows/console/createpseudoconsole#requirements
|
153
|
+
if (+windowsBuild < 17763) {
|
154
|
+
return false;
|
155
|
+
}
|
156
|
+
else {
|
157
|
+
return true;
|
158
|
+
}
|
159
|
+
}
|
@@ -11,7 +11,6 @@ const utils_1 = require("./utils");
|
|
11
11
|
const tasks_schedule_1 = require("./tasks-schedule");
|
12
12
|
const hash_task_1 = require("../hasher/hash-task");
|
13
13
|
const task_env_1 = require("./task-env");
|
14
|
-
const os = require("os");
|
15
14
|
const workspace_root_1 = require("../utils/workspace-root");
|
16
15
|
const output_1 = require("../utils/output");
|
17
16
|
const params_1 = require("../utils/params");
|
@@ -253,8 +252,9 @@ class TaskOrchestrator {
|
|
253
252
|
}
|
254
253
|
async runTaskInForkedProcess(task, env, pipeOutput, temporaryOutputPath, streamOutput) {
|
255
254
|
try {
|
256
|
-
|
257
|
-
|
255
|
+
const usePtyFork = process.env.NX_NATIVE_COMMAND_RUNNER !== 'false';
|
256
|
+
// Disable the pseudo terminal if this is a run-many
|
257
|
+
const disablePseudoTerminal = !this.initiatingProject;
|
258
258
|
// execution
|
259
259
|
const { code, terminalOutput } = usePtyFork
|
260
260
|
? await this.forkedProcessTaskRunner.forkProcess(task, {
|
@@ -263,6 +263,7 @@ class TaskOrchestrator {
|
|
263
263
|
pipeOutput,
|
264
264
|
taskGraph: this.taskGraph,
|
265
265
|
env,
|
266
|
+
disablePseudoTerminal,
|
266
267
|
})
|
267
268
|
: await this.forkedProcessTaskRunner.forkProcessLegacy(task, {
|
268
269
|
temporaryOutputPath,
|
@@ -412,22 +413,3 @@ class TaskOrchestrator {
|
|
412
413
|
}
|
413
414
|
}
|
414
415
|
exports.TaskOrchestrator = TaskOrchestrator;
|
415
|
-
function supportedPtyPlatform() {
|
416
|
-
if (process.platform !== 'win32') {
|
417
|
-
return true;
|
418
|
-
}
|
419
|
-
let windowsVersion = os.release().split('.');
|
420
|
-
let windowsBuild = windowsVersion[2];
|
421
|
-
if (!windowsBuild) {
|
422
|
-
return false;
|
423
|
-
}
|
424
|
-
// Mininum supported Windows version:
|
425
|
-
// https://en.wikipedia.org/wiki/Windows_10,_version_1809
|
426
|
-
// https://learn.microsoft.com/en-us/windows/console/createpseudoconsole#requirements
|
427
|
-
if (+windowsBuild < 17763) {
|
428
|
-
return false;
|
429
|
-
}
|
430
|
-
else {
|
431
|
-
return true;
|
432
|
-
}
|
433
|
-
}
|