nx 18.1.0-canary.20240315-3b8cbae → 18.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +12 -12
- package/src/command-line/release/config/config.js +4 -3
- package/src/command-line/run/run.js +3 -3
- package/src/core/graph/main.js +1 -1
- package/src/core/graph/polyfills.js +1 -1
- package/src/executors/run-commands/run-commands.impl.js +14 -10
- package/src/executors/run-script/run-script.impl.js +5 -5
- package/src/migrations/update-17-3-0/nx-release-path.js +0 -1
- package/src/native/index.d.ts +14 -11
- package/src/native/index.js +3 -4
- package/src/project-graph/file-utils.js +4 -2
- package/src/project-graph/utils/project-configuration-utils.d.ts +2 -2
- package/src/project-graph/utils/project-configuration-utils.js +30 -30
- package/src/project-graph/utils/retrieve-workspace-files.js +3 -3
- package/src/tasks-runner/fork.js +7 -7
- package/src/tasks-runner/forked-process-task-runner.d.ts +2 -4
- package/src/tasks-runner/forked-process-task-runner.js +13 -17
- package/src/tasks-runner/{psuedo-ipc.d.ts → pseudo-ipc.d.ts} +7 -7
- package/src/tasks-runner/{psuedo-ipc.js → pseudo-ipc.js} +9 -9
- package/src/tasks-runner/pseudo-terminal.d.ts +42 -0
- package/src/tasks-runner/pseudo-terminal.js +133 -0
- package/src/tasks-runner/task-orchestrator.js +0 -1
- package/src/utils/ignore.js +1 -1
- package/src/utils/nx-plugin.d.ts +5 -1
@@ -6,8 +6,7 @@ const path = require("path");
|
|
6
6
|
const yargsParser = require("yargs-parser");
|
7
7
|
const npm_run_path_1 = require("npm-run-path");
|
8
8
|
const chalk = require("chalk");
|
9
|
-
const
|
10
|
-
const child_process_2 = require("../../utils/child-process");
|
9
|
+
const pseudo_terminal_1 = require("../../tasks-runner/pseudo-terminal");
|
11
10
|
exports.LARGE_BUFFER = 1024 * 1000000;
|
12
11
|
async function loadEnvVars(path) {
|
13
12
|
if (path) {
|
@@ -48,10 +47,11 @@ async function default_1(options, context) {
|
|
48
47
|
!options.parallel) {
|
49
48
|
throw new Error('ERROR: Bad executor config for run-commands - "prefix", "color" and "bgColor" can only be set when "parallel=true".');
|
50
49
|
}
|
50
|
+
const terminal = (0, pseudo_terminal_1.getPseudoTerminal)();
|
51
51
|
try {
|
52
52
|
const result = options.parallel
|
53
|
-
? await runInParallel(normalized, context)
|
54
|
-
: await runSerially(normalized, context);
|
53
|
+
? await runInParallel(terminal, normalized, context)
|
54
|
+
: await runSerially(terminal, normalized, context);
|
55
55
|
return result;
|
56
56
|
}
|
57
57
|
catch (e) {
|
@@ -62,8 +62,8 @@ async function default_1(options, context) {
|
|
62
62
|
}
|
63
63
|
}
|
64
64
|
exports.default = default_1;
|
65
|
-
async function runInParallel(options, context) {
|
66
|
-
const procs = options.commands.map((c) => createProcess(c, options.readyWhen, options.color, calculateCwd(options.cwd, context), options.env ?? {}, true, options.usePty, options.streamOutput).then((result) => ({
|
65
|
+
async function runInParallel(pseudoTerminal, options, context) {
|
66
|
+
const procs = options.commands.map((c) => createProcess(pseudoTerminal, c, options.readyWhen, options.color, calculateCwd(options.cwd, context), options.env ?? {}, true, options.usePty, options.streamOutput).then((result) => ({
|
67
67
|
result,
|
68
68
|
command: c.command,
|
69
69
|
})));
|
@@ -135,10 +135,10 @@ function normalizeOptions(options) {
|
|
135
135
|
});
|
136
136
|
return options;
|
137
137
|
}
|
138
|
-
async function runSerially(options, context) {
|
138
|
+
async function runSerially(pseudoTerminal, options, context) {
|
139
139
|
let terminalOutput = '';
|
140
140
|
for (const c of options.commands) {
|
141
|
-
const result = await createProcess(c, undefined, options.color, calculateCwd(options.cwd, context), options.env ?? {}, false, options.usePty, options.streamOutput);
|
141
|
+
const result = await createProcess(pseudoTerminal, c, undefined, options.color, calculateCwd(options.cwd, context), options.env ?? {}, false, options.usePty, options.streamOutput);
|
142
142
|
terminalOutput += result.terminalOutput;
|
143
143
|
if (!result.success) {
|
144
144
|
const output = `Warning: command "${c.command}" exited with non-zero status code`;
|
@@ -151,7 +151,7 @@ async function runSerially(options, context) {
|
|
151
151
|
}
|
152
152
|
return { success: true, terminalOutput };
|
153
153
|
}
|
154
|
-
async function createProcess(commandConfig, readyWhen, color, cwd, env, isParallel, usePty = true, streamOutput = true) {
|
154
|
+
async function createProcess(pseudoTerminal, commandConfig, readyWhen, color, cwd, env, isParallel, usePty = true, streamOutput = true) {
|
155
155
|
env = processEnv(color, cwd, env);
|
156
156
|
// The rust runCommand is always a tty, so it will not look nice in parallel and if we need prefixes
|
157
157
|
// currently does not work properly in windows
|
@@ -160,7 +160,11 @@ async function createProcess(commandConfig, readyWhen, color, cwd, env, isParall
|
|
160
160
|
!commandConfig.prefix &&
|
161
161
|
!isParallel &&
|
162
162
|
usePty) {
|
163
|
-
const cp =
|
163
|
+
const cp = pseudoTerminal.runCommand(commandConfig.command, {
|
164
|
+
cwd,
|
165
|
+
jsEnv: env,
|
166
|
+
quiet: !streamOutput,
|
167
|
+
});
|
164
168
|
let terminalOutput = '';
|
165
169
|
return new Promise((res) => {
|
166
170
|
cp.onOutput((output) => {
|
@@ -1,10 +1,9 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
const path = require("path");
|
4
|
-
const native_1 = require("../../native");
|
5
|
-
const child_process_1 = require("../../utils/child-process");
|
6
4
|
const package_manager_1 = require("../../utils/package-manager");
|
7
|
-
const
|
5
|
+
const child_process_1 = require("child_process");
|
6
|
+
const pseudo_terminal_1 = require("../../tasks-runner/pseudo-terminal");
|
8
7
|
async function default_1(options, context) {
|
9
8
|
const pm = (0, package_manager_1.getPackageManagerCommand)();
|
10
9
|
try {
|
@@ -32,15 +31,16 @@ async function default_1(options, context) {
|
|
32
31
|
}
|
33
32
|
exports.default = default_1;
|
34
33
|
function nodeProcess(command, cwd, env) {
|
35
|
-
(0,
|
34
|
+
(0, child_process_1.execSync)(command, {
|
36
35
|
stdio: ['inherit', 'inherit', 'inherit'],
|
37
36
|
cwd,
|
38
37
|
env,
|
39
38
|
});
|
40
39
|
}
|
41
40
|
async function ptyProcess(command, cwd, env) {
|
41
|
+
const terminal = (0, pseudo_terminal_1.getPseudoTerminal)();
|
42
42
|
return new Promise((res, rej) => {
|
43
|
-
const cp =
|
43
|
+
const cp = terminal.runCommand(command, { cwd, jsEnv: env });
|
44
44
|
cp.onExit((code) => {
|
45
45
|
if (code === 0) {
|
46
46
|
res();
|
@@ -5,7 +5,6 @@ const node_path_1 = require("node:path");
|
|
5
5
|
const ignore_1 = require("../../utils/ignore");
|
6
6
|
function nxReleasePath(tree) {
|
7
7
|
visitNotIgnoredFiles(tree, '', (file) => {
|
8
|
-
console.log({ file });
|
9
8
|
const contents = tree.read(file).toString('utf-8');
|
10
9
|
if (
|
11
10
|
// the deep import usage should be replaced by the new location
|
package/src/native/index.d.ts
CHANGED
@@ -21,12 +21,6 @@ export function expandOutputs(directory: string, entries: Array<string>): Array<
|
|
21
21
|
export function getFilesForOutputs(directory: string, entries: Array<string>): Array<string>
|
22
22
|
export function remove(src: string): void
|
23
23
|
export function copy(src: string, dest: string): void
|
24
|
-
export function runCommand(command: string, commandDir?: string | undefined | null, jsEnv?: Record<string, string> | undefined | null, quiet?: boolean | undefined | null): ChildProcess
|
25
|
-
/**
|
26
|
-
* This allows us to run a pseudoterminal with a fake node ipc channel
|
27
|
-
* this makes it possible to be backwards compatible with the old implementation
|
28
|
-
*/
|
29
|
-
export function nxFork(id: string, forkScript: string, psuedoIpcPath: string, commandDir: string | undefined | null, jsEnv: Record<string, string> | undefined | null, quiet: boolean): ChildProcess
|
30
24
|
export function hashArray(input: Array<string>): string
|
31
25
|
export function hashFile(file: string): string | null
|
32
26
|
export function findImports(projectFileMap: Record<string, Array<string>>): Array<ImportResult>
|
@@ -146,17 +140,26 @@ export interface FileMap {
|
|
146
140
|
nonProjectFiles: Array<FileData>
|
147
141
|
}
|
148
142
|
export function testOnlyTransferFileMap(projectFiles: Record<string, Array<FileData>>, nonProjectFiles: Array<FileData>): NxWorkspaceFilesExternals
|
149
|
-
export class ChildProcess {
|
150
|
-
kill(): void
|
151
|
-
onExit(callback: (message: string) => void): void
|
152
|
-
onOutput(callback: (message: string) => void): void
|
153
|
-
}
|
154
143
|
export class ImportResult {
|
155
144
|
file: string
|
156
145
|
sourceProject: string
|
157
146
|
dynamicImportExpressions: Array<string>
|
158
147
|
staticImportExpressions: Array<string>
|
159
148
|
}
|
149
|
+
export class ChildProcess {
|
150
|
+
kill(): void
|
151
|
+
onExit(callback: (message: string) => void): void
|
152
|
+
onOutput(callback: (message: string) => void): void
|
153
|
+
}
|
154
|
+
export class RustPseudoTerminal {
|
155
|
+
constructor()
|
156
|
+
runCommand(command: string, commandDir?: string | undefined | null, jsEnv?: Record<string, string> | undefined | null, quiet?: boolean | undefined | null): ChildProcess
|
157
|
+
/**
|
158
|
+
* This allows us to run a pseudoterminal with a fake node ipc channel
|
159
|
+
* this makes it possible to be backwards compatible with the old implementation
|
160
|
+
*/
|
161
|
+
fork(id: string, forkScript: string, pseudoIpcPath: string, commandDir: string | undefined | null, jsEnv: Record<string, string> | undefined | null, quiet: boolean): ChildProcess
|
162
|
+
}
|
160
163
|
export class HashPlanner {
|
161
164
|
constructor(nxJson: NxJson, projectGraph: ExternalObject<ProjectGraph>)
|
162
165
|
getPlans(taskIds: Array<string>, taskGraph: TaskGraph): Record<string, string[]>
|
package/src/native/index.js
CHANGED
@@ -246,20 +246,19 @@ if (!nativeBinding) {
|
|
246
246
|
throw new Error(`Failed to load native binding`)
|
247
247
|
}
|
248
248
|
|
249
|
-
const { expandOutputs, getFilesForOutputs, remove, copy,
|
249
|
+
const { expandOutputs, getFilesForOutputs, remove, copy, hashArray, hashFile, ImportResult, findImports, transferProjectGraph, ChildProcess, RustPseudoTerminal, HashPlanner, TaskHasher, EventType, Watcher, WorkspaceContext, WorkspaceErrors, testOnlyTransferFileMap } = nativeBinding
|
250
250
|
|
251
251
|
module.exports.expandOutputs = expandOutputs
|
252
252
|
module.exports.getFilesForOutputs = getFilesForOutputs
|
253
253
|
module.exports.remove = remove
|
254
254
|
module.exports.copy = copy
|
255
|
-
module.exports.ChildProcess = ChildProcess
|
256
|
-
module.exports.runCommand = runCommand
|
257
|
-
module.exports.nxFork = nxFork
|
258
255
|
module.exports.hashArray = hashArray
|
259
256
|
module.exports.hashFile = hashFile
|
260
257
|
module.exports.ImportResult = ImportResult
|
261
258
|
module.exports.findImports = findImports
|
262
259
|
module.exports.transferProjectGraph = transferProjectGraph
|
260
|
+
module.exports.ChildProcess = ChildProcess
|
261
|
+
module.exports.RustPseudoTerminal = RustPseudoTerminal
|
263
262
|
module.exports.HashPlanner = HashPlanner
|
264
263
|
module.exports.TaskHasher = TaskHasher
|
265
264
|
module.exports.EventType = EventType
|
@@ -147,7 +147,7 @@ Object.defineProperty(exports, "workspaceLayout", { enumerable: true, get: funct
|
|
147
147
|
* TODO(v19): Remove this function.
|
148
148
|
*/
|
149
149
|
function getProjectsSyncNoInference(root, nxJson) {
|
150
|
-
const
|
150
|
+
const allConfigFiles = (0, retrieve_workspace_files_1.retrieveProjectConfigurationPaths)(root, (0, nx_plugin_deprecated_1.getDefaultPluginsSync)(root));
|
151
151
|
const plugins = [
|
152
152
|
{ plugin: package_json_next_to_project_json_1.PackageJsonProjectsNextToProjectJsonPlugin },
|
153
153
|
...(0, nx_plugin_deprecated_1.getDefaultPluginsSync)(root),
|
@@ -159,11 +159,13 @@ function getProjectsSyncNoInference(root, nxJson) {
|
|
159
159
|
if (!pattern) {
|
160
160
|
continue;
|
161
161
|
}
|
162
|
-
|
162
|
+
const matchingConfigFiles = allConfigFiles.filter((file) => (0, minimatch_1.minimatch)(file, pattern, { dot: true }));
|
163
|
+
for (const file of matchingConfigFiles) {
|
163
164
|
if ((0, minimatch_1.minimatch)(file, pattern, { dot: true })) {
|
164
165
|
let r = createNodes(file, options, {
|
165
166
|
nxJsonConfiguration: nxJson,
|
166
167
|
workspaceRoot: root,
|
168
|
+
configFiles: matchingConfigFiles,
|
167
169
|
});
|
168
170
|
for (const node in r.projects) {
|
169
171
|
const project = {
|
@@ -20,11 +20,11 @@ export type ConfigurationResult = {
|
|
20
20
|
* Transforms a list of project paths into a map of project configurations.
|
21
21
|
*
|
22
22
|
* @param nxJson The NxJson configuration
|
23
|
-
* @param
|
23
|
+
* @param workspaceFiles A list of non-ignored workspace files
|
24
24
|
* @param plugins The plugins that should be used to infer project configuration
|
25
25
|
* @param root The workspace root
|
26
26
|
*/
|
27
|
-
export declare function buildProjectsConfigurationsFromProjectPathsAndPlugins(nxJson: NxJsonConfiguration,
|
27
|
+
export declare function buildProjectsConfigurationsFromProjectPathsAndPlugins(nxJson: NxJsonConfiguration, workspaceFiles: string[], // making this parameter allows devkit to pick up newly created projects
|
28
28
|
plugins: LoadedNxPlugin[], root?: string): Promise<ConfigurationResult>;
|
29
29
|
export declare function readProjectConfigurationsFromRootMap(projectRootMap: Map<string, ProjectConfiguration>): Record<string, ProjectConfiguration>;
|
30
30
|
/**
|
@@ -124,11 +124,11 @@ exports.mergeProjectConfigurationIntoRootMap = mergeProjectConfigurationIntoRoot
|
|
124
124
|
* Transforms a list of project paths into a map of project configurations.
|
125
125
|
*
|
126
126
|
* @param nxJson The NxJson configuration
|
127
|
-
* @param
|
127
|
+
* @param workspaceFiles A list of non-ignored workspace files
|
128
128
|
* @param plugins The plugins that should be used to infer project configuration
|
129
129
|
* @param root The workspace root
|
130
130
|
*/
|
131
|
-
function buildProjectsConfigurationsFromProjectPathsAndPlugins(nxJson,
|
131
|
+
function buildProjectsConfigurationsFromProjectPathsAndPlugins(nxJson, workspaceFiles, // making this parameter allows devkit to pick up newly created projects
|
132
132
|
plugins, root = workspace_root_1.workspaceRoot) {
|
133
133
|
const results = [];
|
134
134
|
// We iterate over plugins first - this ensures that plugins specified first take precedence.
|
@@ -139,40 +139,40 @@ plugins, root = workspace_root_1.workspaceRoot) {
|
|
139
139
|
if (!pattern) {
|
140
140
|
continue;
|
141
141
|
}
|
142
|
-
|
142
|
+
const matchingConfigFiles = workspaceFiles.filter(minimatch_1.minimatch.filter(pattern, { dot: true }));
|
143
|
+
for (const file of matchingConfigFiles) {
|
143
144
|
performance.mark(`${plugin.name}:createNodes:${file} - start`);
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
performance.mark(`${plugin.name}:createNodes:${file} - end`);
|
158
|
-
performance.measure(`${plugin.name}:createNodes:${file}`, `${plugin.name}:createNodes:${file} - start`, `${plugin.name}:createNodes:${file} - end`);
|
159
|
-
return { ...r, file, pluginName: plugin.name };
|
160
|
-
}));
|
161
|
-
}
|
162
|
-
else {
|
145
|
+
try {
|
146
|
+
let r = createNodes(file, options, {
|
147
|
+
nxJsonConfiguration: nxJson,
|
148
|
+
workspaceRoot: root,
|
149
|
+
configFiles: matchingConfigFiles,
|
150
|
+
});
|
151
|
+
if (r instanceof Promise) {
|
152
|
+
pluginResults.push(r
|
153
|
+
.catch((e) => {
|
154
|
+
performance.mark(`${plugin.name}:createNodes:${file} - end`);
|
155
|
+
throw new CreateNodesError(`Unable to create nodes for ${file} using plugin ${plugin.name}.`, e);
|
156
|
+
})
|
157
|
+
.then((r) => {
|
163
158
|
performance.mark(`${plugin.name}:createNodes:${file} - end`);
|
164
159
|
performance.measure(`${plugin.name}:createNodes:${file}`, `${plugin.name}:createNodes:${file} - start`, `${plugin.name}:createNodes:${file} - end`);
|
165
|
-
|
166
|
-
|
167
|
-
file,
|
168
|
-
pluginName: plugin.name,
|
169
|
-
});
|
170
|
-
}
|
160
|
+
return { ...r, file, pluginName: plugin.name };
|
161
|
+
}));
|
171
162
|
}
|
172
|
-
|
173
|
-
|
163
|
+
else {
|
164
|
+
performance.mark(`${plugin.name}:createNodes:${file} - end`);
|
165
|
+
performance.measure(`${plugin.name}:createNodes:${file}`, `${plugin.name}:createNodes:${file} - start`, `${plugin.name}:createNodes:${file} - end`);
|
166
|
+
pluginResults.push({
|
167
|
+
...r,
|
168
|
+
file,
|
169
|
+
pluginName: plugin.name,
|
170
|
+
});
|
174
171
|
}
|
175
172
|
}
|
173
|
+
catch (e) {
|
174
|
+
throw new CreateNodesError(`Unable to create nodes for ${file} using plugin ${plugin.name}.`, e);
|
175
|
+
}
|
176
176
|
}
|
177
177
|
// If there are no promises (counter undefined) or all promises have resolved (counter === 0)
|
178
178
|
results.push(Promise.all(pluginResults).then((results) => {
|
@@ -57,8 +57,8 @@ async function retrieveProjectConfigurationsWithAngularProjects(workspaceRoot, n
|
|
57
57
|
exports.retrieveProjectConfigurationsWithAngularProjects = retrieveProjectConfigurationsWithAngularProjects;
|
58
58
|
function _retrieveProjectConfigurations(workspaceRoot, nxJson, plugins) {
|
59
59
|
const globPatterns = configurationGlobs(plugins);
|
60
|
-
const
|
61
|
-
return createProjectConfigurations(workspaceRoot, nxJson,
|
60
|
+
const workspaceFiles = (0, workspace_context_1.globWithWorkspaceContext)(workspaceRoot, globPatterns);
|
61
|
+
return createProjectConfigurations(workspaceRoot, nxJson, workspaceFiles, plugins);
|
62
62
|
}
|
63
63
|
function retrieveProjectConfigurationPaths(root, plugins) {
|
64
64
|
const projectGlobPatterns = configurationGlobs(plugins);
|
@@ -75,7 +75,7 @@ async function retrieveProjectConfigurationsWithoutPluginInference(root) {
|
|
75
75
|
if (projectsWithoutPluginCache.has(cacheKey)) {
|
76
76
|
return projectsWithoutPluginCache.get(cacheKey);
|
77
77
|
}
|
78
|
-
const projectFiles = (0, workspace_context_1.globWithWorkspaceContext)(root, projectGlobPatterns);
|
78
|
+
const projectFiles = (0, workspace_context_1.globWithWorkspaceContext)(root, projectGlobPatterns) ?? [];
|
79
79
|
const { projects } = await createProjectConfigurations(root, nxJson, projectFiles, [
|
80
80
|
{ plugin: (0, package_json_workspaces_1.getNxPackageJsonWorkspacesPlugin)(root) },
|
81
81
|
{ plugin: project_json_1.ProjectJsonProjectsPlugin },
|
package/src/tasks-runner/fork.js
CHANGED
@@ -2,22 +2,22 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
const child_process_1 = require("child_process");
|
4
4
|
const path_1 = require("path");
|
5
|
-
const
|
6
|
-
const
|
5
|
+
const pseudo_ipc_1 = require("./pseudo-ipc");
|
6
|
+
const pseudoIPCPath = process.argv[2];
|
7
7
|
const forkId = process.argv[3];
|
8
8
|
const script = (0, path_1.join)(__dirname, '../../bin/run-executor.js');
|
9
9
|
const childProcess = (0, child_process_1.fork)(script, {
|
10
10
|
stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
|
11
11
|
});
|
12
|
-
const
|
13
|
-
|
12
|
+
const pseudoIPC = new pseudo_ipc_1.PseudoIPCClient(pseudoIPCPath);
|
13
|
+
pseudoIPC.onMessageFromParent(forkId, (message) => {
|
14
14
|
childProcess.send(message);
|
15
15
|
});
|
16
|
-
|
16
|
+
pseudoIPC.notifyChildIsReady(forkId);
|
17
17
|
process.on('message', (message) => {
|
18
|
-
|
18
|
+
pseudoIPC.sendMessageToParent(message);
|
19
19
|
});
|
20
20
|
childProcess.on('exit', (code) => {
|
21
|
-
|
21
|
+
pseudoIPC.close();
|
22
22
|
process.exit(code);
|
23
23
|
});
|
@@ -8,8 +8,7 @@ export declare class ForkedProcessTaskRunner {
|
|
8
8
|
cliPath: string;
|
9
9
|
private readonly verbose;
|
10
10
|
private processes;
|
11
|
-
private
|
12
|
-
private psuedoIPC;
|
11
|
+
private pseudoTerminal;
|
13
12
|
constructor(options: DefaultTasksRunnerOptions);
|
14
13
|
init(): Promise<void>;
|
15
14
|
forkProcessForBatch({ executorName, taskGraph: batchTaskGraph }: Batch, fullTaskGraph: TaskGraph, env: NodeJS.ProcessEnv): Promise<BatchResults>;
|
@@ -33,12 +32,11 @@ export declare class ForkedProcessTaskRunner {
|
|
33
32
|
code: number;
|
34
33
|
terminalOutput: string;
|
35
34
|
}>;
|
36
|
-
private
|
35
|
+
private forkProcessWithPseudoTerminal;
|
37
36
|
private forkProcessPipeOutputCapture;
|
38
37
|
private forkProcessWithPrefixAndNotTTY;
|
39
38
|
private forkProcessDirectOutputCapture;
|
40
39
|
private readTerminalOutput;
|
41
40
|
private writeTerminalOutput;
|
42
41
|
private setupProcessEventListeners;
|
43
|
-
destroy(): void;
|
44
42
|
}
|
@@ -11,10 +11,7 @@ const path_1 = require("path");
|
|
11
11
|
const batch_messages_1 = require("./batch/batch-messages");
|
12
12
|
const strip_indents_1 = require("../utils/strip-indents");
|
13
13
|
const stream_1 = require("stream");
|
14
|
-
const
|
15
|
-
const psuedo_ipc_1 = require("./psuedo-ipc");
|
16
|
-
const socket_utils_1 = require("../daemon/socket-utils");
|
17
|
-
const child_process_2 = require("../utils/child-process");
|
14
|
+
const pseudo_terminal_1 = require("./pseudo-terminal");
|
18
15
|
const exit_codes_1 = require("../utils/exit-codes");
|
19
16
|
const forkScript = (0, path_1.join)(__dirname, './fork.js');
|
20
17
|
const workerPath = (0, path_1.join)(__dirname, './batch/run-batch.js');
|
@@ -24,11 +21,10 @@ class ForkedProcessTaskRunner {
|
|
24
21
|
this.cliPath = (0, utils_1.getCliPath)();
|
25
22
|
this.verbose = process.env.NX_VERBOSE_LOGGING === 'true';
|
26
23
|
this.processes = new Set();
|
27
|
-
this.
|
28
|
-
this.psuedoIPC = new psuedo_ipc_1.PsuedoIPCServer(this.psuedoIPCPath);
|
24
|
+
this.pseudoTerminal = (0, pseudo_terminal_1.getPseudoTerminal)();
|
29
25
|
}
|
30
26
|
async init() {
|
31
|
-
await this.
|
27
|
+
await this.pseudoTerminal.init();
|
32
28
|
this.setupProcessEventListeners();
|
33
29
|
}
|
34
30
|
// TODO: vsavkin delegate terminal output printing
|
@@ -121,7 +117,7 @@ class ForkedProcessTaskRunner {
|
|
121
117
|
});
|
122
118
|
}
|
123
119
|
else {
|
124
|
-
return this.
|
120
|
+
return this.forkProcessWithPseudoTerminal(task, {
|
125
121
|
temporaryOutputPath,
|
126
122
|
streamOutput,
|
127
123
|
taskGraph,
|
@@ -129,15 +125,18 @@ class ForkedProcessTaskRunner {
|
|
129
125
|
});
|
130
126
|
}
|
131
127
|
}
|
132
|
-
async
|
128
|
+
async forkProcessWithPseudoTerminal(task, { streamOutput, taskGraph, env, }) {
|
133
129
|
const args = (0, utils_1.getPrintableCommandArgsForTask)(task);
|
134
130
|
if (streamOutput) {
|
135
131
|
output_1.output.logCommand(args.join(' '));
|
136
132
|
}
|
137
133
|
const childId = task.id;
|
138
|
-
const p =
|
139
|
-
|
140
|
-
|
134
|
+
const p = await this.pseudoTerminal.fork(childId, forkScript, {
|
135
|
+
cwd: process.cwd(),
|
136
|
+
jsEnv: env,
|
137
|
+
quiet: !streamOutput,
|
138
|
+
});
|
139
|
+
p.send({
|
141
140
|
targetDescription: task.target,
|
142
141
|
overrides: task.overrides,
|
143
142
|
taskGraph,
|
@@ -304,13 +303,13 @@ class ForkedProcessTaskRunner {
|
|
304
303
|
(0, fs_1.writeFileSync)(outputPath, content);
|
305
304
|
}
|
306
305
|
setupProcessEventListeners() {
|
307
|
-
this.
|
306
|
+
this.pseudoTerminal.onMessageFromChildren((message) => {
|
308
307
|
process.send(message);
|
309
308
|
});
|
310
309
|
// When the nx process gets a message, it will be sent into the task's process
|
311
310
|
process.on('message', (message) => {
|
312
311
|
// this.publisher.publish(message.toString());
|
313
|
-
this.
|
312
|
+
this.pseudoTerminal.sendMessageToChildren(message);
|
314
313
|
this.processes.forEach((p) => {
|
315
314
|
if ('connected' in p && p.connected) {
|
316
315
|
p.send(message);
|
@@ -353,9 +352,6 @@ class ForkedProcessTaskRunner {
|
|
353
352
|
// will store results to the cache and will terminate this process
|
354
353
|
});
|
355
354
|
}
|
356
|
-
destroy() {
|
357
|
-
this.psuedoIPC.close();
|
358
|
-
}
|
359
355
|
}
|
360
356
|
exports.ForkedProcessTaskRunner = ForkedProcessTaskRunner;
|
361
357
|
const colors = [
|
@@ -6,24 +6,24 @@
|
|
6
6
|
* Main Nx Process
|
7
7
|
* * Calls Rust Fork Function
|
8
8
|
* * `node fork.js`
|
9
|
-
* * Create a Rust - Node.js Agnostic Channel aka
|
9
|
+
* * Create a Rust - Node.js Agnostic Channel aka Pseudo IPC Channel
|
10
10
|
* * This returns RustChildProcess
|
11
11
|
* * RustChildProcess.onMessage(msg => ());
|
12
|
-
* *
|
12
|
+
* * pseudo_ipc_channel.on_message() => tx.send(msg);
|
13
13
|
* * Node.js Fork Wrapper (fork.js)
|
14
14
|
* * fork(run-command.js) with `inherit` and `ipc`
|
15
15
|
* * This will create a Node IPC Channel
|
16
|
-
* * channel =
|
17
|
-
* * forkChildProcess.on('message',
|
16
|
+
* * channel = getPseudoIpcChannel(process.env.NX_IPC_CHANNEL_ID)
|
17
|
+
* * forkChildProcess.on('message', writeToPseudoIpcChannel)
|
18
18
|
*/
|
19
19
|
/// <reference types="node" />
|
20
20
|
import { Serializable } from 'child_process';
|
21
|
-
export interface
|
21
|
+
export interface PseudoIPCMessage {
|
22
22
|
type: 'TO_CHILDREN_FROM_PARENT' | 'TO_PARENT_FROM_CHILDREN' | 'CHILD_READY';
|
23
23
|
id: string | undefined;
|
24
24
|
message: Serializable;
|
25
25
|
}
|
26
|
-
export declare class
|
26
|
+
export declare class PseudoIPCServer {
|
27
27
|
private path;
|
28
28
|
private sockets;
|
29
29
|
private server;
|
@@ -38,7 +38,7 @@ export declare class PsuedoIPCServer {
|
|
38
38
|
onMessageFromChildren(onMessage: (message: Serializable) => void, onClose?: () => void, onError?: (err: Error) => void): void;
|
39
39
|
close(): void;
|
40
40
|
}
|
41
|
-
export declare class
|
41
|
+
export declare class PseudoIPCClient {
|
42
42
|
private path;
|
43
43
|
private socket;
|
44
44
|
constructor(path: string);
|
@@ -7,21 +7,21 @@
|
|
7
7
|
* Main Nx Process
|
8
8
|
* * Calls Rust Fork Function
|
9
9
|
* * `node fork.js`
|
10
|
-
* * Create a Rust - Node.js Agnostic Channel aka
|
10
|
+
* * Create a Rust - Node.js Agnostic Channel aka Pseudo IPC Channel
|
11
11
|
* * This returns RustChildProcess
|
12
12
|
* * RustChildProcess.onMessage(msg => ());
|
13
|
-
* *
|
13
|
+
* * pseudo_ipc_channel.on_message() => tx.send(msg);
|
14
14
|
* * Node.js Fork Wrapper (fork.js)
|
15
15
|
* * fork(run-command.js) with `inherit` and `ipc`
|
16
16
|
* * This will create a Node IPC Channel
|
17
|
-
* * channel =
|
18
|
-
* * forkChildProcess.on('message',
|
17
|
+
* * channel = getPseudoIpcChannel(process.env.NX_IPC_CHANNEL_ID)
|
18
|
+
* * forkChildProcess.on('message', writeToPseudoIpcChannel)
|
19
19
|
*/
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
21
|
-
exports.
|
21
|
+
exports.PseudoIPCClient = exports.PseudoIPCServer = void 0;
|
22
22
|
const net_1 = require("net");
|
23
23
|
const consume_messages_from_socket_1 = require("../utils/consume-messages-from-socket");
|
24
|
-
class
|
24
|
+
class PseudoIPCServer {
|
25
25
|
constructor(path) {
|
26
26
|
this.path = path;
|
27
27
|
this.sockets = new Set();
|
@@ -98,8 +98,8 @@ class PsuedoIPCServer {
|
|
98
98
|
this.sockets.forEach((s) => s.destroy());
|
99
99
|
}
|
100
100
|
}
|
101
|
-
exports.
|
102
|
-
class
|
101
|
+
exports.PseudoIPCServer = PseudoIPCServer;
|
102
|
+
class PseudoIPCClient {
|
103
103
|
constructor(path) {
|
104
104
|
this.path = path;
|
105
105
|
this.socket = (0, net_1.connect)(this.path);
|
@@ -137,4 +137,4 @@ class PsuedoIPCClient {
|
|
137
137
|
this.socket?.destroy();
|
138
138
|
}
|
139
139
|
}
|
140
|
-
exports.
|
140
|
+
exports.PseudoIPCClient = PseudoIPCClient;
|
@@ -0,0 +1,42 @@
|
|
1
|
+
/// <reference types="node" />
|
2
|
+
import { ChildProcess, RustPseudoTerminal } from '../native';
|
3
|
+
import { PseudoIPCServer } from './pseudo-ipc';
|
4
|
+
import { Serializable } from 'child_process';
|
5
|
+
export declare function getPseudoTerminal(): PseudoTerminal;
|
6
|
+
export declare class PseudoTerminal {
|
7
|
+
private rustPseudoTerminal;
|
8
|
+
private pseudoIPCPath;
|
9
|
+
private pseudoIPC;
|
10
|
+
private initialized;
|
11
|
+
constructor(rustPseudoTerminal: RustPseudoTerminal);
|
12
|
+
init(): Promise<void>;
|
13
|
+
runCommand(command: string, { cwd, jsEnv, quiet, }?: {
|
14
|
+
cwd?: string;
|
15
|
+
jsEnv?: Record<string, string>;
|
16
|
+
quiet?: boolean;
|
17
|
+
}): PseudoTtyProcess;
|
18
|
+
fork(id: string, script: string, { cwd, jsEnv, quiet, }: {
|
19
|
+
cwd?: string;
|
20
|
+
jsEnv?: Record<string, string>;
|
21
|
+
quiet?: boolean;
|
22
|
+
}): Promise<PseudoTtyProcessWithSend>;
|
23
|
+
sendMessageToChildren(message: Serializable): void;
|
24
|
+
onMessageFromChildren(callback: (message: Serializable) => void): void;
|
25
|
+
private setupProcessListeners;
|
26
|
+
private shutdownPseudoIPC;
|
27
|
+
}
|
28
|
+
export declare class PseudoTtyProcess {
|
29
|
+
private childProcess;
|
30
|
+
isAlive: boolean;
|
31
|
+
exitCallbacks: any[];
|
32
|
+
constructor(childProcess: ChildProcess);
|
33
|
+
onExit(callback: (code: number) => void): void;
|
34
|
+
onOutput(callback: (message: string) => void): void;
|
35
|
+
kill(): void;
|
36
|
+
}
|
37
|
+
export declare class PseudoTtyProcessWithSend extends PseudoTtyProcess {
|
38
|
+
private id;
|
39
|
+
private pseudoIpc;
|
40
|
+
constructor(_childProcess: ChildProcess, id: string, pseudoIpc: PseudoIPCServer);
|
41
|
+
send(message: Serializable): void;
|
42
|
+
}
|