@mpis/run 0.0.9 → 0.0.11
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/lib/bin.js +15 -171
- package/lib/bin.js.map +1 -1
- package/lib/common/args.d.ts +4 -3
- package/lib/common/args.d.ts.map +1 -1
- package/lib/common/args.js +2 -3
- package/lib/common/args.js.map +1 -1
- package/lib/common/config-file.d.ts +1 -1
- package/lib/common/config-file.d.ts.map +1 -1
- package/lib/common/config-file.js +4 -1
- package/lib/common/config-file.js.map +1 -1
- package/lib/common/interactive.d.ts +2 -0
- package/lib/common/interactive.d.ts.map +1 -0
- package/lib/common/interactive.js +46 -0
- package/lib/common/interactive.js.map +1 -0
- package/lib/common/manager.d.ts +4 -0
- package/lib/common/manager.d.ts.map +1 -0
- package/lib/common/manager.js +61 -0
- package/lib/common/manager.js.map +1 -0
- package/lib/common/print-screen.d.ts +5 -0
- package/lib/common/print-screen.d.ts.map +1 -0
- package/lib/common/print-screen.js +67 -0
- package/lib/common/print-screen.js.map +1 -0
- package/loader/bin.js +2 -0
- package/package.json +11 -14
- package/src/bin.ts +18 -183
- package/src/common/args.ts +2 -4
- package/src/common/config-file.ts +5 -1
- package/src/common/interactive.ts +46 -0
- package/src/common/manager.ts +64 -0
- package/src/common/print-screen.ts +73 -0
- package/src/tsconfig.json +1 -1
- package/lib/autoindex.d.ts +0 -7
- package/lib/autoindex.d.ts.map +0 -1
- package/lib/autoindex.js +0 -14
- package/lib/autoindex.js.map +0 -1
- package/lib/tsconfig.tsbuildinfo +0 -1
- package/src/autoindex.ts +0 -18
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"print-screen.js","sourceRoot":"","sources":["../../src/common/print-screen.ts"],"names":[],"mappings":"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"}
|
package/loader/bin.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mpis/run",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.11",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"bin": {
|
|
7
7
|
"run": "./loader/bin.js",
|
|
@@ -12,22 +12,19 @@
|
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"split-cmd": "^1.1.0",
|
|
15
|
-
"
|
|
16
|
-
"@
|
|
17
|
-
"@idlebox/
|
|
18
|
-
"@idlebox/
|
|
19
|
-
"@idlebox/
|
|
20
|
-
"@mpis/client": "^0.0.
|
|
21
|
-
"@
|
|
22
|
-
"@
|
|
23
|
-
"@mpis/shared": "^0.0.7",
|
|
24
|
-
"@idlebox/source-map-support": "^0.0.8"
|
|
15
|
+
"@build-script/rushstack-config-loader": "^0.0.27",
|
|
16
|
+
"@idlebox/args": "^0.0.16",
|
|
17
|
+
"@idlebox/logger": "^0.0.9",
|
|
18
|
+
"@idlebox/node": "^1.4.15",
|
|
19
|
+
"@idlebox/common": "^1.5.0",
|
|
20
|
+
"@mpis/client": "^0.0.9",
|
|
21
|
+
"@mpis/server": "^0.0.8",
|
|
22
|
+
"@idlebox/source-map-support": "^0.0.9"
|
|
25
23
|
},
|
|
26
24
|
"devDependencies": {
|
|
27
25
|
"@types/node": "^24.0.14",
|
|
28
|
-
"@build-script/single-dog-asset": "
|
|
29
|
-
"@idlebox/esbuild-executer": "^0.0.7"
|
|
30
|
-
"@internal/local-rig": "^1.0.1"
|
|
26
|
+
"@build-script/single-dog-asset": "latest",
|
|
27
|
+
"@idlebox/esbuild-executer": "^0.0.7"
|
|
31
28
|
},
|
|
32
29
|
"sideEffects": false,
|
|
33
30
|
"license": "MIT",
|
package/src/bin.ts
CHANGED
|
@@ -1,44 +1,28 @@
|
|
|
1
|
-
import { humanDate,
|
|
1
|
+
import { functionToDisposable, humanDate, prettyPrintError, registerGlobalLifecycle } from '@idlebox/common';
|
|
2
2
|
import { logger } from '@idlebox/logger';
|
|
3
3
|
import { registerNodejsExitHandler, setExitCodeIfNot, shutdown } from '@idlebox/node';
|
|
4
4
|
import { channelClient } from '@mpis/client';
|
|
5
|
-
import {
|
|
5
|
+
import { ProcessIPCClient } from '@mpis/server';
|
|
6
6
|
import { rmSync } from 'node:fs';
|
|
7
7
|
import { dumpConfig } from './commands/config.js';
|
|
8
|
-
import { context
|
|
9
|
-
import {
|
|
8
|
+
import { context } from './common/args.js';
|
|
9
|
+
import { config } from './common/config-file.js';
|
|
10
|
+
import { addBreakModeDebugCommands } from './common/interactive.js';
|
|
11
|
+
import { initializeWorkers, workersManager } from './common/manager.js';
|
|
10
12
|
import { projectRoot } from './common/paths.js';
|
|
13
|
+
import { reprintWatchModeError } from './common/print-screen.js';
|
|
11
14
|
import { initializeStdin, registerCommand } from './common/stdin.js';
|
|
12
15
|
|
|
13
16
|
registerNodejsExitHandler();
|
|
14
17
|
|
|
15
|
-
parseCliArgs();
|
|
16
|
-
|
|
17
|
-
let execute_index = 0;
|
|
18
|
-
const start = Date.now();
|
|
19
|
-
registerGlobalLifecycle(
|
|
20
|
-
toDisposable(() => {
|
|
21
|
-
logger.info`Operation completed in ${humanDate.delta(Date.now() - start)} (${process.exitCode ? 'failed' : 'success'}).`;
|
|
22
|
-
}),
|
|
23
|
-
);
|
|
24
|
-
|
|
25
18
|
registerCommand({
|
|
26
19
|
name: ['status', 's'],
|
|
27
20
|
description: '显示当前状态',
|
|
28
21
|
callback: () => reprintWatchModeError(),
|
|
29
22
|
});
|
|
30
23
|
|
|
31
|
-
process.title = `MpisRun`;
|
|
32
|
-
|
|
33
24
|
logger.info`Running command "${context.command}" in ${projectRoot}`;
|
|
34
25
|
|
|
35
|
-
const defaultNoClear = logger.debug.isEnabled || !process.stderr.isTTY;
|
|
36
|
-
let workersManager: WorkersManager;
|
|
37
|
-
|
|
38
|
-
const config = loadConfigFile(context.watchMode);
|
|
39
|
-
logger.verbose`loaded config file: ${config}`;
|
|
40
|
-
const errors = new Map<ProcessIPCClient, Error | null>();
|
|
41
|
-
|
|
42
26
|
switch (context.command) {
|
|
43
27
|
case 'clean':
|
|
44
28
|
executeClean();
|
|
@@ -57,7 +41,7 @@ switch (context.command) {
|
|
|
57
41
|
logger.debug`build completed.`;
|
|
58
42
|
setExitCodeIfNot(0);
|
|
59
43
|
} catch (e: any) {
|
|
60
|
-
|
|
44
|
+
prettyPrintError(`failed ${context.command} project`, e);
|
|
61
45
|
shutdown(1);
|
|
62
46
|
}
|
|
63
47
|
}
|
|
@@ -69,16 +53,14 @@ switch (context.command) {
|
|
|
69
53
|
}
|
|
70
54
|
initializeStdin();
|
|
71
55
|
await executeBuild().catch((e: Error) => {
|
|
72
|
-
|
|
56
|
+
prettyPrintError(`failed ${context.command} project`, e);
|
|
73
57
|
shutdown(1);
|
|
74
58
|
});
|
|
75
59
|
break;
|
|
76
60
|
}
|
|
77
61
|
|
|
78
|
-
// channelClient.displayName = `MpisRun`;
|
|
79
|
-
|
|
80
62
|
async function executeBuild() {
|
|
81
|
-
|
|
63
|
+
let shuttingDown = false;
|
|
82
64
|
|
|
83
65
|
initializeWorkers();
|
|
84
66
|
const graph = workersManager.finalize();
|
|
@@ -93,7 +75,7 @@ async function executeBuild() {
|
|
|
93
75
|
|
|
94
76
|
const times = `(+${humanDate.delta(w.time.executeStart!, w.time.executeEnd!)})`;
|
|
95
77
|
|
|
96
|
-
if (context.watchMode) {
|
|
78
|
+
if (context.watchMode && !shuttingDown) {
|
|
97
79
|
printFailedRunError(w, `unexpected exit in watch mode ${times}`);
|
|
98
80
|
} else if (!w.isSuccess) {
|
|
99
81
|
printFailedRunError(w, `failed to execute ${times}`);
|
|
@@ -110,8 +92,7 @@ async function executeBuild() {
|
|
|
110
92
|
channelClient.start();
|
|
111
93
|
|
|
112
94
|
if (context.breakMode) {
|
|
113
|
-
|
|
114
|
-
addDebugCommand();
|
|
95
|
+
addBreakModeDebugCommands();
|
|
115
96
|
return;
|
|
116
97
|
}
|
|
117
98
|
logger.verbose`Workers initialized, starting execution...`;
|
|
@@ -119,6 +100,12 @@ async function executeBuild() {
|
|
|
119
100
|
|
|
120
101
|
logger.verbose`Startup returned.`;
|
|
121
102
|
|
|
103
|
+
registerGlobalLifecycle(
|
|
104
|
+
functionToDisposable(() => {
|
|
105
|
+
shuttingDown = true;
|
|
106
|
+
}),
|
|
107
|
+
);
|
|
108
|
+
|
|
122
109
|
reprintWatchModeError();
|
|
123
110
|
}
|
|
124
111
|
|
|
@@ -130,45 +117,6 @@ function executeClean() {
|
|
|
130
117
|
logger.success`Cleaned up ${config.clean.length} folders.`;
|
|
131
118
|
}
|
|
132
119
|
|
|
133
|
-
function initializeWorkers() {
|
|
134
|
-
let last: ProcessIPCClient | undefined;
|
|
135
|
-
for (const title of config.buildTitles) {
|
|
136
|
-
const cmds = config.build.get(title);
|
|
137
|
-
if (!cmds) throw logger.fatal`program state error, no build command "${title}"`;
|
|
138
|
-
|
|
139
|
-
if (!cmds.env['DEBUG']) cmds.env['DEBUG'] = '';
|
|
140
|
-
if (!cmds.env['DEBUG_LEVEL']) cmds.env['DEBUG_LEVEL'] = '';
|
|
141
|
-
const worker = new ProcessIPCClient(title.replace(/\s+/g, ''), cmds.command, cmds.cwd, cmds.env);
|
|
142
|
-
|
|
143
|
-
for (const path of config.additionalPaths) {
|
|
144
|
-
worker.pathvar.add(path);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
worker.displayTitle = `run:${cmds.command[0]}`;
|
|
148
|
-
|
|
149
|
-
workersManager.addWorker(worker, last ? [last._id] : []);
|
|
150
|
-
|
|
151
|
-
let nodeFirstTime = true;
|
|
152
|
-
worker.onFailure((e) => {
|
|
153
|
-
errors.set(worker, e);
|
|
154
|
-
reprintWatchModeError(nodeFirstTime);
|
|
155
|
-
nodeFirstTime = false;
|
|
156
|
-
sendStatus();
|
|
157
|
-
});
|
|
158
|
-
worker.onSuccess(() => {
|
|
159
|
-
errors.set(worker, null);
|
|
160
|
-
if (nodeFirstTime) {
|
|
161
|
-
nodeFirstTime = false;
|
|
162
|
-
} else {
|
|
163
|
-
reprintWatchModeError();
|
|
164
|
-
}
|
|
165
|
-
sendStatus();
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
last = worker;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
120
|
const cls = /\x1Bc/g;
|
|
173
121
|
|
|
174
122
|
function printFailedRunError(worker: ProcessIPCClient, message: string) {
|
|
@@ -190,116 +138,3 @@ function printFailedRunError(worker: ProcessIPCClient, message: string) {
|
|
|
190
138
|
logger.error`"${worker._id}" ${message}`;
|
|
191
139
|
shutdown(1);
|
|
192
140
|
}
|
|
193
|
-
|
|
194
|
-
let printTo: NodeJS.Timeout | undefined;
|
|
195
|
-
function reprintWatchModeError(noClear?: boolean) {
|
|
196
|
-
if (printTo) clearTimeout(printTo);
|
|
197
|
-
printTo = setTimeout(() => {
|
|
198
|
-
printTo = undefined;
|
|
199
|
-
|
|
200
|
-
if (context.watchMode) {
|
|
201
|
-
if (!noClear && !defaultNoClear) process.stderr.write('\x1Bc');
|
|
202
|
-
}
|
|
203
|
-
const graph = workersManager.finalize();
|
|
204
|
-
console.error('%s\n%s', graph.debugFormatList(), graph.debugFormatSummary());
|
|
205
|
-
printAllErrors();
|
|
206
|
-
}, 50);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
function addDebugCommand() {
|
|
210
|
-
registerCommand({
|
|
211
|
-
name: ['continue', 'c'],
|
|
212
|
-
description: '开始执行',
|
|
213
|
-
callback: () => {
|
|
214
|
-
workersManager.finalize().startup();
|
|
215
|
-
},
|
|
216
|
-
});
|
|
217
|
-
registerCommand({
|
|
218
|
-
name: ['debug'],
|
|
219
|
-
description: '切换调试模式(仅在启动前有效)',
|
|
220
|
-
callback: (text: string) => {
|
|
221
|
-
const [_, index, on_off] = text.split(/\s+/);
|
|
222
|
-
const list = workersManager._allWorkers as ProcessIPCClient[];
|
|
223
|
-
const worker = list[Number(index)];
|
|
224
|
-
if (!worker) {
|
|
225
|
-
logger.error`worker index out of range: ${index}`;
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
if (on_off === 'on') {
|
|
229
|
-
worker.env['DEBUG'] = '*,-executer:*,-dispose:*';
|
|
230
|
-
worker.env['DEBUG_LEVEL'] = 'verbose';
|
|
231
|
-
logger.success`debug mode enabled for worker "${worker._id}"`;
|
|
232
|
-
} else if (on_off === 'off') {
|
|
233
|
-
worker.env['DEBUG'] = '';
|
|
234
|
-
worker.env['DEBUG_LEVEL'] = '';
|
|
235
|
-
logger.success`debug mode disabled for worker "${worker._id}"`;
|
|
236
|
-
} else {
|
|
237
|
-
logger.error`invalid argument: ${text}`;
|
|
238
|
-
}
|
|
239
|
-
},
|
|
240
|
-
});
|
|
241
|
-
// registerCommand({
|
|
242
|
-
// name: ['print', 'p'],
|
|
243
|
-
// description: '显示命令执行输出',
|
|
244
|
-
// callback: () => {
|
|
245
|
-
// },
|
|
246
|
-
// });
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
function sendStatus() {
|
|
250
|
-
const noError = errors.values().every((e) => !e);
|
|
251
|
-
if (noError) {
|
|
252
|
-
channelClient.success(`all ${workersManager.size()} workers completed successfully.`);
|
|
253
|
-
} else {
|
|
254
|
-
let errorCnt = 0;
|
|
255
|
-
const arr: string[] = [];
|
|
256
|
-
for (const [client, err] of errors.entries()) {
|
|
257
|
-
if (err) {
|
|
258
|
-
errorCnt++;
|
|
259
|
-
arr.push(client._id);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
channelClient.failed(`mpis-run: ${arr.join(', ')} (${errorCnt} / ${workersManager.size()})`, formatAllErrors());
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
function formatAllErrors() {
|
|
267
|
-
const lines: string[] = [];
|
|
268
|
-
const colorEnabled = logger.colorEnabled;
|
|
269
|
-
let index = 0;
|
|
270
|
-
for (const [worker, error] of errors) {
|
|
271
|
-
if (error === null) continue;
|
|
272
|
-
|
|
273
|
-
index++;
|
|
274
|
-
|
|
275
|
-
let tag = '';
|
|
276
|
-
if (error.name !== 'Error') {
|
|
277
|
-
tag = ` (${error.name})`;
|
|
278
|
-
}
|
|
279
|
-
const banner = colorEnabled ? `\x1B[48;5;9m ERROR ${index} \x1B[0m` : `ERROR ${index}`;
|
|
280
|
-
lines.push(`\n${banner}${tag} ${worker._id}`);
|
|
281
|
-
if (error instanceof CompileError) {
|
|
282
|
-
lines.push(error.toString());
|
|
283
|
-
} else if (error instanceof Error) {
|
|
284
|
-
lines.push(prettyFormatError(error));
|
|
285
|
-
} else {
|
|
286
|
-
lines.push(`can not handle error: ${error}`);
|
|
287
|
-
}
|
|
288
|
-
lines.push(`\n${banner} ${worker._id}`);
|
|
289
|
-
}
|
|
290
|
-
return lines.join('\n');
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
function printAllErrors() {
|
|
294
|
-
execute_index++;
|
|
295
|
-
const execTip = `exec: ${execute_index} / ${humanDate.delta(Date.now() - start)}`;
|
|
296
|
-
|
|
297
|
-
const numFailed = [...errors.values().filter((e) => !!e)].length;
|
|
298
|
-
if (numFailed !== 0) {
|
|
299
|
-
console.error(formatAllErrors());
|
|
300
|
-
|
|
301
|
-
logger.error(`💥 ${numFailed} of ${workersManager.size()} worker failed (${execTip})`);
|
|
302
|
-
} else {
|
|
303
|
-
logger.success(`✅ no error in ${workersManager.size()} workers (${execTip})`);
|
|
304
|
-
}
|
|
305
|
-
}
|
package/src/common/args.ts
CHANGED
|
@@ -11,7 +11,7 @@ export function printUsage() {
|
|
|
11
11
|
// console.log(' init create config file if not');
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
function parseCliArgs() {
|
|
15
15
|
const debugLevel = argv.flag(['-d', '--debug']);
|
|
16
16
|
|
|
17
17
|
const debugMode = debugLevel > 0;
|
|
@@ -75,8 +75,6 @@ export function parseCliArgs() {
|
|
|
75
75
|
dumpConfig,
|
|
76
76
|
};
|
|
77
77
|
|
|
78
|
-
context = r;
|
|
79
|
-
|
|
80
78
|
if (argv.unused().length) {
|
|
81
79
|
printUsage();
|
|
82
80
|
console.error('');
|
|
@@ -85,4 +83,4 @@ export function parseCliArgs() {
|
|
|
85
83
|
return r;
|
|
86
84
|
}
|
|
87
85
|
|
|
88
|
-
export
|
|
86
|
+
export const context: Readonly<ReturnType<typeof parseCliArgs>> = parseCliArgs();
|
|
@@ -5,6 +5,7 @@ import { readFileSync } from 'node:fs';
|
|
|
5
5
|
import { resolve } from 'node:path';
|
|
6
6
|
import { fileURLToPath } from 'node:url';
|
|
7
7
|
import { split as splitCmd } from 'split-cmd';
|
|
8
|
+
import { context } from './args.js';
|
|
8
9
|
import { projectRoot, selfRoot } from './paths.js';
|
|
9
10
|
|
|
10
11
|
interface IPackageBinary {
|
|
@@ -54,7 +55,7 @@ function watchModeCmd(command: string | readonly string[], watch?: string | read
|
|
|
54
55
|
return [...cmdArr, ...watch];
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
|
|
58
|
+
function loadConfigFile(watchMode: boolean): IConfigFile {
|
|
58
59
|
const config = new ProjectConfig(projectRoot, undefined, logger);
|
|
59
60
|
const schemaFile = resolve(selfRoot, 'commands.schema.json');
|
|
60
61
|
|
|
@@ -236,3 +237,6 @@ function resolveCommandIsFile(config: ProjectConfig, command: string[]) {
|
|
|
236
237
|
|
|
237
238
|
command.splice(0, 1, process.execPath, r.effective);
|
|
238
239
|
}
|
|
240
|
+
|
|
241
|
+
export const config = loadConfigFile(context.watchMode);
|
|
242
|
+
logger.verbose`loaded config file: ${config}`;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { logger } from '@idlebox/logger';
|
|
2
|
+
import type { ProcessIPCClient } from '@mpis/server';
|
|
3
|
+
import { workersManager } from './manager.js';
|
|
4
|
+
import { registerCommand } from './stdin.js';
|
|
5
|
+
|
|
6
|
+
export function addBreakModeDebugCommands() {
|
|
7
|
+
logger.warn`Break mode enabled, waiting for input command...`;
|
|
8
|
+
|
|
9
|
+
registerCommand({
|
|
10
|
+
name: ['continue', 'c'],
|
|
11
|
+
description: '开始执行',
|
|
12
|
+
callback: () => {
|
|
13
|
+
workersManager.finalize().startup();
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
registerCommand({
|
|
17
|
+
name: ['debug'],
|
|
18
|
+
description: '切换调试模式(仅在启动前有效)',
|
|
19
|
+
callback: (text: string) => {
|
|
20
|
+
const [_, index, on_off] = text.split(/\s+/);
|
|
21
|
+
const list = workersManager._allWorkers as ProcessIPCClient[];
|
|
22
|
+
const worker = list[Number(index)];
|
|
23
|
+
if (!worker) {
|
|
24
|
+
logger.error`worker index out of range: ${index}`;
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (on_off === 'on') {
|
|
28
|
+
worker.env['DEBUG'] = '*,-executer:*,-dispose:*';
|
|
29
|
+
worker.env['DEBUG_LEVEL'] = 'verbose';
|
|
30
|
+
logger.success`debug mode enabled for worker "${worker._id}"`;
|
|
31
|
+
} else if (on_off === 'off') {
|
|
32
|
+
worker.env['DEBUG'] = '';
|
|
33
|
+
worker.env['DEBUG_LEVEL'] = '';
|
|
34
|
+
logger.success`debug mode disabled for worker "${worker._id}"`;
|
|
35
|
+
} else {
|
|
36
|
+
logger.error`invalid argument: ${text}`;
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
// registerCommand({
|
|
41
|
+
// name: ['print', 'p'],
|
|
42
|
+
// description: '显示命令执行输出',
|
|
43
|
+
// callback: () => {
|
|
44
|
+
// },
|
|
45
|
+
// });
|
|
46
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { logger } from '@idlebox/logger';
|
|
2
|
+
import { channelClient } from '@mpis/client';
|
|
3
|
+
import { ModeKind, ProcessIPCClient, WorkersManager } from '@mpis/server';
|
|
4
|
+
import { context } from './args.js';
|
|
5
|
+
import { config } from './config-file.js';
|
|
6
|
+
import { errors, formatAllErrors, reprintWatchModeError } from './print-screen.js';
|
|
7
|
+
|
|
8
|
+
export const workersManager = new WorkersManager(context.watchMode ? ModeKind.Watch : ModeKind.Build);
|
|
9
|
+
|
|
10
|
+
export function initializeWorkers() {
|
|
11
|
+
let last: ProcessIPCClient | undefined;
|
|
12
|
+
for (const title of config.buildTitles) {
|
|
13
|
+
const cmds = config.build.get(title);
|
|
14
|
+
if (!cmds) throw logger.fatal`program state error, no build command "${title}"`;
|
|
15
|
+
|
|
16
|
+
if (!cmds.env['DEBUG']) cmds.env['DEBUG'] = '';
|
|
17
|
+
if (!cmds.env['DEBUG_LEVEL']) cmds.env['DEBUG_LEVEL'] = '';
|
|
18
|
+
const worker = new ProcessIPCClient(title.replace(/\s+/g, ''), cmds.command, cmds.cwd, cmds.env);
|
|
19
|
+
|
|
20
|
+
for (const path of config.additionalPaths) {
|
|
21
|
+
worker.pathvar.add(path);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
worker.displayTitle = `run:${cmds.command[0]}`;
|
|
25
|
+
|
|
26
|
+
workersManager.addWorker(worker, last ? [last._id] : []);
|
|
27
|
+
|
|
28
|
+
let nodeFirstTime = true;
|
|
29
|
+
worker.onFailure((e) => {
|
|
30
|
+
errors.set(worker, e);
|
|
31
|
+
reprintWatchModeError(nodeFirstTime);
|
|
32
|
+
nodeFirstTime = false;
|
|
33
|
+
sendStatus();
|
|
34
|
+
});
|
|
35
|
+
worker.onSuccess(() => {
|
|
36
|
+
errors.set(worker, null);
|
|
37
|
+
if (nodeFirstTime) {
|
|
38
|
+
nodeFirstTime = false;
|
|
39
|
+
} else {
|
|
40
|
+
reprintWatchModeError();
|
|
41
|
+
}
|
|
42
|
+
sendStatus();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
last = worker;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function sendStatus() {
|
|
50
|
+
const noError = errors.values().every((e) => !e);
|
|
51
|
+
if (noError) {
|
|
52
|
+
channelClient.success(`all ${workersManager.size()} workers completed successfully.`);
|
|
53
|
+
} else {
|
|
54
|
+
let errorCnt = 0;
|
|
55
|
+
const arr: string[] = [];
|
|
56
|
+
for (const [client, err] of errors.entries()) {
|
|
57
|
+
if (err) {
|
|
58
|
+
errorCnt++;
|
|
59
|
+
arr.push(client._id);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
channelClient.failed(`mpis-run: ${arr.join(', ')} (${errorCnt} / ${workersManager.size()})`, formatAllErrors());
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { humanDate, prettyFormatError, registerGlobalLifecycle, toDisposable } from '@idlebox/common';
|
|
2
|
+
import { logger } from '@idlebox/logger';
|
|
3
|
+
import { CompileError, type ProcessIPCClient } from '@mpis/server';
|
|
4
|
+
import { context } from './args.js';
|
|
5
|
+
import { workersManager } from './manager.js';
|
|
6
|
+
|
|
7
|
+
let printTo: NodeJS.Timeout | undefined;
|
|
8
|
+
const defaultNoClear = logger.debug.isEnabled || !process.stderr.isTTY;
|
|
9
|
+
export const errors = new Map<ProcessIPCClient, Error | null>();
|
|
10
|
+
|
|
11
|
+
export function reprintWatchModeError(noClear?: boolean) {
|
|
12
|
+
if (printTo) clearTimeout(printTo);
|
|
13
|
+
printTo = setTimeout(() => {
|
|
14
|
+
printTo = undefined;
|
|
15
|
+
|
|
16
|
+
if (context.watchMode) {
|
|
17
|
+
if (!noClear && !defaultNoClear) process.stderr.write('\x1Bc');
|
|
18
|
+
}
|
|
19
|
+
const graph = workersManager.finalize();
|
|
20
|
+
console.error('%s\n%s', graph.debugFormatList(), graph.debugFormatSummary());
|
|
21
|
+
printAllErrors();
|
|
22
|
+
}, 50);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let execute_index = 0;
|
|
26
|
+
const start = Date.now();
|
|
27
|
+
|
|
28
|
+
function printAllErrors() {
|
|
29
|
+
execute_index++;
|
|
30
|
+
const execTip = `exec: ${execute_index} / ${humanDate.delta(Date.now() - start)}`;
|
|
31
|
+
|
|
32
|
+
const numFailed = [...errors.values().filter((e) => !!e)].length;
|
|
33
|
+
if (numFailed !== 0) {
|
|
34
|
+
console.error(formatAllErrors());
|
|
35
|
+
|
|
36
|
+
logger.error(`💥 ${numFailed} of ${workersManager.size()} worker failed (${execTip})`);
|
|
37
|
+
} else {
|
|
38
|
+
logger.success(`✅ no error in ${workersManager.size()} workers (${execTip})`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function formatAllErrors() {
|
|
43
|
+
const lines: string[] = [];
|
|
44
|
+
const colorEnabled = logger.colorEnabled;
|
|
45
|
+
let index = 0;
|
|
46
|
+
for (const [worker, error] of errors) {
|
|
47
|
+
if (error === null) continue;
|
|
48
|
+
|
|
49
|
+
index++;
|
|
50
|
+
|
|
51
|
+
let tag = '';
|
|
52
|
+
if (error.name !== 'Error') {
|
|
53
|
+
tag = ` (${error.name})`;
|
|
54
|
+
}
|
|
55
|
+
const banner = colorEnabled ? `\x1B[48;5;9m ERROR ${index} \x1B[0m` : `ERROR ${index}`;
|
|
56
|
+
lines.push(`\n${banner}${tag} ${worker._id}`);
|
|
57
|
+
if (error instanceof CompileError) {
|
|
58
|
+
lines.push(error.toString());
|
|
59
|
+
} else if (error instanceof Error) {
|
|
60
|
+
lines.push(prettyFormatError(error));
|
|
61
|
+
} else {
|
|
62
|
+
lines.push(`can not handle error: ${error}`);
|
|
63
|
+
}
|
|
64
|
+
lines.push(`\n${banner} ${worker._id}`);
|
|
65
|
+
}
|
|
66
|
+
return lines.join('\n');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
registerGlobalLifecycle(
|
|
70
|
+
toDisposable(() => {
|
|
71
|
+
logger.info`Operation completed in ${humanDate.delta(Date.now() - start)} (${process.exitCode !== 0 ? 'failed' : 'success'}).`;
|
|
72
|
+
}),
|
|
73
|
+
);
|
package/src/tsconfig.json
CHANGED
package/lib/autoindex.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export { printUsage } from './common/args.js';
|
|
2
|
-
export { projectRoot } from './common/paths.js';
|
|
3
|
-
export { selfRoot } from './common/paths.js';
|
|
4
|
-
export type { ICommand } from './common/config-file.js';
|
|
5
|
-
export type { IConfigFile } from './common/config-file.js';
|
|
6
|
-
export { loadConfigFile } from './common/config-file.js';
|
|
7
|
-
//# sourceMappingURL=autoindex.d.ts.map
|
package/lib/autoindex.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"autoindex.d.ts","sourceRoot":"","sources":["../src/autoindex.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAG7C,YAAY,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACxD,YAAY,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC"}
|
package/lib/autoindex.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
// DO NOT EDIT THIS FILE
|
|
2
|
-
// @ts-ignore
|
|
3
|
-
/* eslint-disable */
|
|
4
|
-
/* common/args.ts */
|
|
5
|
-
// Identifiers
|
|
6
|
-
export { printUsage } from './common/args.js';
|
|
7
|
-
/* common/paths.ts */
|
|
8
|
-
// Identifiers
|
|
9
|
-
export { projectRoot } from './common/paths.js';
|
|
10
|
-
export { selfRoot } from './common/paths.js';
|
|
11
|
-
export { loadConfigFile } from './common/config-file.js';
|
|
12
|
-
/* bin.ts */
|
|
13
|
-
// Identifiers
|
|
14
|
-
//# sourceMappingURL=autoindex.js.map
|
package/lib/autoindex.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"autoindex.js","sourceRoot":"","sources":["../src/autoindex.ts"],"names":[],"mappings":"AAAA,wBAAwB;AACxB,aAAa;AACb,oBAAoB;AAEpB,oBAAoB;AACpB,cAAc;AACd,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,qBAAqB;AACrB,cAAc;AACd,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAK7C,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,YAAY;AACZ,cAAc"}
|