@idlebox/node 1.2.12 → 1.2.13
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/index.generated.cjs.map +1 -1
- package/lib/index.generated.js.map +1 -1
- package/{dist → lib}/node-alpha.d.ts +0 -0
- package/{dist → lib}/node-beta.d.ts +0 -0
- package/{dist → lib}/node-public.d.ts +0 -0
- package/{dist → lib}/node.d.ts +0 -0
- package/lib/preload.cjs +3 -0
- package/lib/preload.cjs.map +1 -0
- package/lib/preload.js +2 -0
- package/lib/preload.js.map +1 -0
- package/{dist → lib}/tsdoc-metadata.json +1 -1
- package/package.json +17 -17
- package/src/asyncLoad.ts +32 -0
- package/src/child_process/error.ts +63 -0
- package/src/child_process/execa.ts +108 -0
- package/src/child_process/lateError.ts +53 -0
- package/src/child_process/respawn.ts +132 -0
- package/src/cli-io/output.ts +3 -0
- package/src/crypto/md5.ts +8 -0
- package/src/crypto/sha256.ts +8 -0
- package/src/environment/findBinary.ts +13 -0
- package/src/environment/getEnvironment.ts +56 -0
- package/src/environment/npmConfig.ts +15 -0
- package/src/environment/pathEnvironment.ts +45 -0
- package/src/error/code.ts +124 -0
- package/src/error/pretty.ts +240 -0
- package/src/events/dumpEventEmitter.ts +9 -0
- package/src/fs/commandExists.ts +48 -0
- package/src/fs/exists.ts +17 -0
- package/src/fs/tempFolder.ts +54 -0
- package/src/fs/weiteChanged.ts +46 -0
- package/src/index.generated.ts +133 -0
- package/src/log/terminal.ts +41 -0
- package/src/path-resolve/findPackageRoot.ts +20 -0
- package/src/path-resolve/findUp.ts +34 -0
- package/src/path-resolve/getAllUp.ts +15 -0
- package/src/path-resolve/lrelative.ts +20 -0
- package/src/path-resolve/nodeResolvePathArray.ts +10 -0
- package/src/path-resolve/resolvePath.ts +43 -0
- package/src/preload.ts +1 -0
- package/src/stream/blackHoleStream.ts +7 -0
- package/src/stream/collectingStream.ts +85 -0
- package/src/stream/disposableStream.ts +24 -0
- package/src/stream/drainStream.ts +19 -0
- package/src/stream/loggerStream.ts +61 -0
- package/src/stream/streamPromise.ts +23 -0
- package/src/tsconfig.json +14 -0
- package/docs/node.api.json +0 -7222
- package/docs/node.api.md +0 -666
- package/docs/package-public.d.ts +0 -380
- package/docs/tsdoc-metadata.json +0 -11
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.generated.js","sourceRoot":"","sources":["../src/index.generated.ts"],"names":[],"mappings":";AAAA,wBAAwB;AACxB,aAAa;AACb,oBAAoB;;;;
|
|
1
|
+
{"version":3,"file":"index.generated.js","sourceRoot":"","sources":["../src/index.generated.ts"],"names":[],"mappings":";AAAA,wBAAwB;AACxB,aAAa;AACb,oBAAoB;;;;AAQlB,8DAAuD;AAA/C,0GAAA,WAAW,OAAA;AAEnB,8DAAyD;AAAjD,4GAAA,aAAa,OAAA;AACrB,8DAAqD;AAA7C,wGAAA,SAAS,OAAA;AACjB,8DAAwD;AAAhD,2GAAA,YAAY,OAAA;AACtB,qBAAqB;AACpB,cAAc;AACb,6CAA+C;AAAvC,yGAAA,eAAe,OAAA;AACvB,6CAAgD;AAAxC,0GAAA,gBAAgB,OAAA;AACxB,6CAAiD;AAAzC,2GAAA,iBAAiB,OAAA;AAIzB,6CAAsC;AAA9B,sGAAA,SAAS,OAAA;AACjB,6CAAoC;AAA5B,oGAAA,OAAO,OAAA;AACjB,4BAA4B;AAC3B,cAAc;AACb,mDAA8D;AAAtD,gHAAA,uBAAuB,OAAA;AAM/B,mDAAyD;AAAjD,2GAAA,kBAAkB,OAAA;AAC1B,mDAAqD;AAA7C,uGAAA,cAAc,OAAA;AACtB,mDAAyD;AAAjD,2GAAA,kBAAkB,OAAA;AAC5B,sBAAsB;AACrB,cAAc;AACb,8CAA0C;AAAlC,mGAAA,SAAS,OAAA;AAIjB,2DAAwD;AAAhD,0GAAA,aAAa,OAAA;AACvB,kBAAkB;AACjB,cAAc;AACb,0CAAuC;AAA/B,oGAAA,UAAU,OAAA;AAClB,0CAAmC;AAA3B,gGAAA,MAAM,OAAA;AAId,mEAA4D;AAApD,gHAAA,cAAc,OAAA;AACtB,mEAA+D;AAAvD,mHAAA,iBAAiB,OAAA;AACzB,mEAAgE;AAAxD,oHAAA,kBAAkB,OAAA;AAC5B,oCAAoC;AACnC,cAAc;AACb,qEAA6D;AAArD,iHAAA,cAAc,OAAA;AACtB,qEAA8D;AAAtD,kHAAA,eAAe,OAAA;AACzB,+BAA+B;AAC9B,cAAc;AACb,2DAAoD;AAA5C,wGAAA,UAAU,OAAA;AACpB,8BAA8B;AAC7B,cAAc;AACb,uDAAmE;AAA3D,qHAAA,0BAA0B,OAAA;AAClC,uDAAwD;AAAhD,0GAAA,eAAe,OAAA;AACvB,uDAAuD;AAA/C,yGAAA,cAAc,OAAA;AACxB,mBAAmB;AAClB,cAAc;AACb,wCAAiC;AAAzB,0FAAA,GAAG,OAAA;AACb,sBAAsB;AACrB,cAAc;AACb,8CAAuC;AAA/B,gGAAA,MAAM,OAAA;AAChB,8BAA8B;AAC7B,cAAc;AACb,yDAA0D;AAAlD,8GAAA,iBAAiB,OAAA;AAC3B,mBAAmB;AAClB,cAAc;AACb,yCAAyC;AAAjC,mGAAA,WAAW,OAAA;AACrB,gCAAgC;AAC/B,cAAc;AACb,kEAA+D;AAAvD,wHAAA,oBAAoB,OAAA;AAC9B,yBAAyB;AACxB,cAAc;AACb,wDAAiD;AAAzC,8GAAA,aAAa,OAAA;AACrB,wDAAsD;AAA9C,mHAAA,kBAAkB,OAAA;AAC5B,sBAAsB;AACrB,cAAc;AACb,kDAAiD;AAAzC,8GAAA,gBAAgB,OAAA;AAC1B,wBAAwB;AACvB,cAAc;AACb,sDAAwD;AAAhD,qHAAA,qBAAqB,OAAA;AAC7B,sDAAoD;AAA5C,iHAAA,iBAAiB,OAAA;AAC3B,qBAAqB;AACpB,cAAc;AACb,+CAAsD;AAA9C,kHAAA,sBAAsB,OAAA;AAChC,4BAA4B;AAC3B,cAAc;AACb,oDAAkD;AAA1C,qGAAA,WAAW,OAAA;AACnB,oDAAsD;AAA9C,yGAAA,eAAe,OAAA;AACzB,qCAAqC;AACpC,cAAc;AACb,sEAA+D;AAAvD,kHAAA,eAAe,OAAA;AACzB,8BAA8B;AAC7B,cAAc;AACb,wDAA2D;AAAnD,8GAAA,kBAAkB,OAAA;AAC5B,+BAA+B;AAC9B,cAAc;AACb,0DAAmD;AAA3C,sGAAA,SAAS,OAAA;AACnB,0CAA0C;AACzC,cAAc;AACb,gFAAyE;AAAjE,4HAAA,oBAAoB,OAAA;AAC9B,+BAA+B;AAC9B,cAAc;AACb,gEAAyD;AAAjD,kHAAA,eAAe,OAAA;AACzB,6BAA6B;AAC5B,cAAc;AACb,4DAAqD;AAA7C,8GAAA,aAAa,OAAA;AACrB,4DAAoD;AAA5C,6GAAA,YAAY,OAAA;AACtB,gCAAgC;AAC/B,cAAc;AACb,kEAAyD;AAAjD,kHAAA,cAAc,OAAA;AACtB,kEAA8D;AAAtD,uHAAA,mBAAmB,OAAA;AAC3B,kEAA2D;AAAnD,oHAAA,gBAAgB,OAAA;AAC1B,gCAAgC;AAC/B,cAAc;AACb,kEAA2D;AAAnD,oHAAA,gBAAgB,OAAA;AAC1B,2BAA2B;AAC1B,cAAc;AACb,wDAAiD;AAAzC,0GAAA,WAAW,OAAA;AAInB,0DAAmD;AAA3C,4GAAA,YAAY,OAAA;AACpB,0DAA0D;AAAlD,mHAAA,mBAAmB,OAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.generated.js","sourceRoot":"","sources":["../src/index.generated.ts"],"names":[],"mappings":"AAAA,wBAAwB;AACxB,aAAa;AACb,oBAAoB;
|
|
1
|
+
{"version":3,"file":"index.generated.js","sourceRoot":"","sources":["../src/index.generated.ts"],"names":[],"mappings":"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"}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/{dist → lib}/node.d.ts
RENAMED
|
File without changes
|
package/lib/preload.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preload.js","sourceRoot":"","sources":["../src/preload.ts"],"names":[],"mappings":""}
|
package/lib/preload.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preload.js","sourceRoot":"","sources":["../src/preload.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@idlebox/node",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.2.
|
|
4
|
+
"version": "1.2.13",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "./fix_esm_loader.cjs",
|
|
7
7
|
"module": "./lib/index.generated.js",
|
|
@@ -9,30 +9,29 @@
|
|
|
9
9
|
".": {
|
|
10
10
|
"import": "./lib/index.generated.js",
|
|
11
11
|
"require": "./fix_esm_loader.cjs"
|
|
12
|
-
}
|
|
12
|
+
},
|
|
13
|
+
"./package.json": "./package.json"
|
|
13
14
|
},
|
|
14
|
-
"types": "
|
|
15
|
+
"types": "./lib/node-public.d.ts",
|
|
15
16
|
"repository": "https://github.com/GongT/baobao",
|
|
16
17
|
"dependencies": {
|
|
17
|
-
"@gongt/fix-esm": "^0.0.8",
|
|
18
|
-
"@idlebox/common": "^1.3.14",
|
|
19
18
|
"execa": "^6.1.0",
|
|
20
19
|
"source-map-support": "^0.5.21",
|
|
21
|
-
"tslib": "^2.4.
|
|
20
|
+
"tslib": "^2.4.1",
|
|
21
|
+
"@gongt/fix-esm": "0.0.9",
|
|
22
|
+
"@idlebox/common": "1.3.16"
|
|
22
23
|
},
|
|
23
24
|
"devDependencies": {
|
|
24
|
-
"@build-script/heft-duel-stack": "^1.0.4",
|
|
25
|
-
"@build-script/single-dog-asset": "^1.0.22",
|
|
26
|
-
"@build-script/typescript-transformer-dual-package": "^2.0.2",
|
|
27
25
|
"@gongt/kexec": "^3.0.0",
|
|
28
|
-
"@rushstack/heft": "^0.
|
|
29
|
-
"@types/node": "^18.
|
|
30
|
-
"chai": "^4.3.
|
|
26
|
+
"@rushstack/heft": "^0.48.8",
|
|
27
|
+
"@types/node": "^18.11.9",
|
|
28
|
+
"chai": "^4.3.7",
|
|
31
29
|
"fs-extra": "^10.1.0",
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
30
|
+
"mocha": "^10.1.0",
|
|
31
|
+
"typescript": "^4.8.4",
|
|
32
|
+
"@build-script/heft-duel-stack": "1.0.7",
|
|
33
|
+
"@build-script/single-dog-asset": "1.0.23",
|
|
34
|
+
"local-rig": "1.0.1"
|
|
36
35
|
},
|
|
37
36
|
"optionalDependencies": {
|
|
38
37
|
"@gongt/kexec": "latest"
|
|
@@ -41,7 +40,8 @@
|
|
|
41
40
|
"scripts": {
|
|
42
41
|
"test": "heft test",
|
|
43
42
|
"lint": "heft build",
|
|
44
|
-
"build": "heft build --
|
|
43
|
+
"build": "heft build --production",
|
|
44
|
+
"build:watch": "heft build --lite",
|
|
45
45
|
"watch": "heft build --watch",
|
|
46
46
|
"clean": "heft clean"
|
|
47
47
|
}
|
package/src/asyncLoad.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { prettyPrintError } from './error/pretty';
|
|
2
|
+
|
|
3
|
+
export type AsyncMainFunction = () => Promise<void | number>;
|
|
4
|
+
|
|
5
|
+
export class ExitError extends Error {
|
|
6
|
+
constructor(message: string, public readonly code: number = 1) {
|
|
7
|
+
super(message);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* should do this before:
|
|
13
|
+
* ```
|
|
14
|
+
* setErrorLogRoot(require('path').dirname(__dirname));
|
|
15
|
+
* ```
|
|
16
|
+
**/
|
|
17
|
+
export function runMain(main: AsyncMainFunction) {
|
|
18
|
+
Promise.resolve()
|
|
19
|
+
.then(main)
|
|
20
|
+
.catch((e) => {
|
|
21
|
+
if (e instanceof ExitError) {
|
|
22
|
+
console.error(e.message);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
prettyPrintError('build-script', e);
|
|
27
|
+
return e.code || 1;
|
|
28
|
+
})
|
|
29
|
+
.then((code) => {
|
|
30
|
+
process.exit(code || 0);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
interface IChildProcessStatus {
|
|
2
|
+
// child_process sync return
|
|
3
|
+
signal?: NodeJS.Signals | string | null;
|
|
4
|
+
status?: number | null;
|
|
5
|
+
error?: Error;
|
|
6
|
+
|
|
7
|
+
// spawn async process (after promise)
|
|
8
|
+
signalCode?: NodeJS.Signals | string | null;
|
|
9
|
+
exitCode?: number | null;
|
|
10
|
+
|
|
11
|
+
// execa
|
|
12
|
+
signalDescription?: string;
|
|
13
|
+
command?: string;
|
|
14
|
+
killed?: boolean;
|
|
15
|
+
failed?: boolean;
|
|
16
|
+
timedOut?: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** @throws */
|
|
20
|
+
export function checkChildProcessResult(result: IChildProcessStatus): void {
|
|
21
|
+
const title = result.command ? `command [${result.command}] ` : 'child process ';
|
|
22
|
+
|
|
23
|
+
if (result.error) {
|
|
24
|
+
const msg: string = result.error.message || (result.error as any);
|
|
25
|
+
const e = new Error(title + 'failed to start: ' + msg.replace(/^Error: /, ''));
|
|
26
|
+
if (result.error.stack) {
|
|
27
|
+
const stack = result.error.stack.split(/\n/);
|
|
28
|
+
stack.splice(0, 1, e.message);
|
|
29
|
+
e.stack = stack.join('\n');
|
|
30
|
+
}
|
|
31
|
+
throw e;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const code = result.exitCode ?? result.status ?? undefined;
|
|
35
|
+
if (code === 0) {
|
|
36
|
+
return; // yes!
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let signal = result.signalCode || result.signal;
|
|
40
|
+
|
|
41
|
+
if (result.timedOut) {
|
|
42
|
+
throw new Error(title + 'timed out (killed)');
|
|
43
|
+
}
|
|
44
|
+
if (result.killed && !signal) {
|
|
45
|
+
throw new Error(title + 'killed by unknown reason');
|
|
46
|
+
}
|
|
47
|
+
if (result.failed) {
|
|
48
|
+
throw new Error(title + 'failed to execute');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (signal) {
|
|
52
|
+
if (result.signalDescription) {
|
|
53
|
+
signal += `: ${result.signalDescription}`;
|
|
54
|
+
}
|
|
55
|
+
throw new Error(title + 'killed by signal ' + signal);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (code! > 0) {
|
|
59
|
+
throw new Error(title + 'exit with code ' + code);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
throw new Error(title + 'status unknown');
|
|
63
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { isWindows, sepList } from '@idlebox/common';
|
|
2
|
+
import { execa, ExecaReturnBase, execaSync, SyncOptions } from 'execa';
|
|
3
|
+
import { checkChildProcessResult } from './error';
|
|
4
|
+
|
|
5
|
+
export interface Sync {
|
|
6
|
+
sync: true;
|
|
7
|
+
}
|
|
8
|
+
export interface Async {
|
|
9
|
+
sync?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
type ProcessEnv = Record<string, string> & {
|
|
13
|
+
Path?: never;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export interface ICommand {
|
|
17
|
+
exec: string[];
|
|
18
|
+
addonPath?: string[];
|
|
19
|
+
cwd?: string;
|
|
20
|
+
sync?: boolean;
|
|
21
|
+
env?: ProcessEnv;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function sanitizeEnv(env?: ProcessEnv, addonPath?: string[]) {
|
|
25
|
+
if (!env) return undefined;
|
|
26
|
+
|
|
27
|
+
if (addonPath) {
|
|
28
|
+
env.PATH = addonPath.join(sepList) + sepList + (env.PATH ?? process.env.PATH);
|
|
29
|
+
}
|
|
30
|
+
if (isWindows) {
|
|
31
|
+
(env as any).Path = env.PATH.replace(/:/g, sepList);
|
|
32
|
+
delete env.PATH;
|
|
33
|
+
}
|
|
34
|
+
return env;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function handleError<T extends ExecaReturnBase<string>>(result: T): T {
|
|
38
|
+
if (result.exitCode !== 0) {
|
|
39
|
+
throw new Error('command exit with code ' + result.exitCode);
|
|
40
|
+
} else if (result.signal) {
|
|
41
|
+
throw new Error('command killed by signal ' + result.signal);
|
|
42
|
+
}
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function spawnWithoutOutput(opt: ICommand & Sync): void;
|
|
47
|
+
export function spawnWithoutOutput(opt: ICommand & Async): Promise<void>;
|
|
48
|
+
export function spawnWithoutOutput({ exec, cwd, sync, env, addonPath }: ICommand & Async): void | Promise<void> {
|
|
49
|
+
const [cmd, ...args] = exec;
|
|
50
|
+
const opts: SyncOptions = {
|
|
51
|
+
stdio: ['ignore', process.stderr, process.stderr],
|
|
52
|
+
cwd,
|
|
53
|
+
reject: false,
|
|
54
|
+
env: sanitizeEnv(env, addonPath),
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
if (sync) {
|
|
58
|
+
checkChildProcessResult(execaSync(cmd, args, opts));
|
|
59
|
+
} else {
|
|
60
|
+
return execa(cmd, args, opts)
|
|
61
|
+
.then(checkChildProcessResult)
|
|
62
|
+
.then(() => {
|
|
63
|
+
return;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function spawnGetOutput(opt: ICommand & Sync): string;
|
|
69
|
+
export function spawnGetOutput(opt: ICommand & Async): Promise<string>;
|
|
70
|
+
export function spawnGetOutput({ exec, cwd, sync, env, addonPath }: ICommand) {
|
|
71
|
+
const [cmd, ...args] = exec;
|
|
72
|
+
const opts: SyncOptions = {
|
|
73
|
+
stdio: ['ignore', 'pipe', process.stderr],
|
|
74
|
+
cwd,
|
|
75
|
+
reject: false,
|
|
76
|
+
stripFinalNewline: true,
|
|
77
|
+
encoding: 'utf8',
|
|
78
|
+
env: sanitizeEnv(env, addonPath),
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
if (sync) {
|
|
82
|
+
const result = handleError(execaSync(cmd, args, opts));
|
|
83
|
+
return result.stdout;
|
|
84
|
+
} else {
|
|
85
|
+
return execa(cmd, args, opts)
|
|
86
|
+
.then(handleError)
|
|
87
|
+
.then((result) => {
|
|
88
|
+
return result.stdout;
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export async function spawnGetEverything({ exec, cwd, env, addonPath }: ICommand) {
|
|
94
|
+
const [cmd, ...args] = exec;
|
|
95
|
+
const opts: SyncOptions = {
|
|
96
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
97
|
+
cwd,
|
|
98
|
+
reject: false,
|
|
99
|
+
stripFinalNewline: true,
|
|
100
|
+
encoding: 'utf8',
|
|
101
|
+
all: true,
|
|
102
|
+
env: sanitizeEnv(env, addonPath),
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const result = await execa(cmd, args, opts);
|
|
106
|
+
handleError(result);
|
|
107
|
+
return result.all;
|
|
108
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { execa, ExecaReturnValue, Options as ExecaOptions } from 'execa';
|
|
2
|
+
import { printLine } from '../cli-io/output';
|
|
3
|
+
import { checkChildProcessResult } from './error';
|
|
4
|
+
|
|
5
|
+
export interface ISpawnAdditionOptions {
|
|
6
|
+
verbose?: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export async function execLazyError(
|
|
10
|
+
cmd: string,
|
|
11
|
+
args: string[],
|
|
12
|
+
spawnOptions: Omit<ExecaOptions, 'reject' | 'stdio' | 'encoding' | 'all' | 'stderr'> & ISpawnAdditionOptions = {}
|
|
13
|
+
): Promise<ExecaReturnValue<string>> {
|
|
14
|
+
let all = false;
|
|
15
|
+
let { stdout, stdin, verbose, ...options } = spawnOptions;
|
|
16
|
+
|
|
17
|
+
if (stdout === 'inherit') {
|
|
18
|
+
all = true;
|
|
19
|
+
stdout = 'pipe';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (verbose) {
|
|
23
|
+
if (process.stderr.isTTY) {
|
|
24
|
+
process.stderr.write(`\x1B[2m + ${cmd} ${args.join(' ')}\x1B[0m\n`);
|
|
25
|
+
} else {
|
|
26
|
+
process.stderr.write(` + ${cmd} ${args.join(' ')}\n`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const p = execa(cmd, args, {
|
|
31
|
+
...options,
|
|
32
|
+
stdio: [stdin || 'ignore', stdout, 'pipe'],
|
|
33
|
+
all: all,
|
|
34
|
+
encoding: 'utf8',
|
|
35
|
+
reject: false,
|
|
36
|
+
});
|
|
37
|
+
return p.then((ret) => {
|
|
38
|
+
try {
|
|
39
|
+
checkChildProcessResult(ret);
|
|
40
|
+
} catch (e) {
|
|
41
|
+
if (process.stderr.isTTY) {
|
|
42
|
+
printLine();
|
|
43
|
+
console.error('\x1B[2m + %s %s:\x1B[0m', cmd, args.join(' '));
|
|
44
|
+
}
|
|
45
|
+
console.error(ret.all || ret.stderr);
|
|
46
|
+
if (process.stderr.isTTY) {
|
|
47
|
+
printLine();
|
|
48
|
+
}
|
|
49
|
+
throw e;
|
|
50
|
+
}
|
|
51
|
+
return ret;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { spawnSync } from 'child_process';
|
|
2
|
+
import { createRequire } from 'module';
|
|
3
|
+
import { platform } from 'os';
|
|
4
|
+
import { findBinary } from '../environment/findBinary';
|
|
5
|
+
import { spawnGetOutput } from './execa';
|
|
6
|
+
|
|
7
|
+
const unshareArgs = ['--pid', '--cgroup', '--fork', '--mount-proc', '--propagation=slave'];
|
|
8
|
+
|
|
9
|
+
if (platform() === 'linux' && process.getuid!() !== 0) {
|
|
10
|
+
unshareArgs.push('--map-root-user');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function spawnRecreateEventHandlers() {
|
|
14
|
+
process.on('SIGINT', () => shutdown_quit('SIGINT', 130));
|
|
15
|
+
process.on('SIGTERM', () => shutdown_quit('SIGTERM', 143));
|
|
16
|
+
process.on('SIGHUP', () => shutdown_quit('SIGHUP', 129));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function shutdown_quit(signal: string, code: number) {
|
|
20
|
+
// console.error('receive signal', signal);
|
|
21
|
+
if (process.listenerCount(signal) > 1) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
process.exit(code);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Spawn a command, replace current node process
|
|
29
|
+
* If can't do that (eg. on Windows), spawn as normal, but quit self after it quit.
|
|
30
|
+
*/
|
|
31
|
+
export function trySpawnInScope(cmds: string[]): never {
|
|
32
|
+
if (process.env.NEVER_UNSHARE || insideScope() || !supportScope()) {
|
|
33
|
+
spawnSimulate(cmds[0], cmds.slice(1));
|
|
34
|
+
} else {
|
|
35
|
+
execLinux(cmds);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Self restart in a pid/cgroup namespace on linux.
|
|
41
|
+
* Your application must inside mainFunc, not before or after it.
|
|
42
|
+
*
|
|
43
|
+
* ```typescript
|
|
44
|
+
* import {respawnInScope} from '@idlebox/node'
|
|
45
|
+
* respawnInScope(() => {
|
|
46
|
+
* import('./real-application');
|
|
47
|
+
* });
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export function respawnInScope(mainFunc: Function): unknown | never {
|
|
51
|
+
if (process.env.NEVER_UNSHARE || insideScope() || !supportScope()) {
|
|
52
|
+
spawnRecreateEventHandlers();
|
|
53
|
+
mainFunc();
|
|
54
|
+
return undefined;
|
|
55
|
+
} else {
|
|
56
|
+
execLinux(process.argv);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let unshare: string;
|
|
61
|
+
|
|
62
|
+
function insideScope() {
|
|
63
|
+
return process.pid === 1;
|
|
64
|
+
}
|
|
65
|
+
function supportScope() {
|
|
66
|
+
if (platform() === 'linux') {
|
|
67
|
+
unshare = findBinary('unshare');
|
|
68
|
+
if (!unshare) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
const supported = spawnGetOutput({
|
|
74
|
+
exec: [unshare, ...unshareArgs, 'echo', 'yes'],
|
|
75
|
+
sync: true,
|
|
76
|
+
});
|
|
77
|
+
if (supported !== 'yes') {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
} catch {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return true;
|
|
85
|
+
} else {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function spawnSimulate(cmd: string, args: string[]): never {
|
|
91
|
+
process.removeAllListeners('SIGINT');
|
|
92
|
+
process.removeAllListeners('SIGTERM');
|
|
93
|
+
const result = spawnSync(cmd, args, {
|
|
94
|
+
stdio: 'inherit',
|
|
95
|
+
windowsHide: true,
|
|
96
|
+
env: {
|
|
97
|
+
...process.env,
|
|
98
|
+
NEVER_UNSHARE: 'true',
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
if (result.signal) {
|
|
102
|
+
process.kill(process.pid, result.signal);
|
|
103
|
+
throw new Error('self kill not quit');
|
|
104
|
+
}
|
|
105
|
+
process.exit(result.status || 0);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function execLinux(cmds: string[]): never {
|
|
109
|
+
const args = [...unshareArgs, '--wd=' + process.cwd(), ...cmds];
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
process.env.NEVER_UNSHARE = 'true';
|
|
113
|
+
const require = createRequire(import.meta.url);
|
|
114
|
+
const kexec = require('@gongt/kexec');
|
|
115
|
+
|
|
116
|
+
process.removeAllListeners('SIGINT');
|
|
117
|
+
process.removeAllListeners('SIGTERM');
|
|
118
|
+
kexec(unshare, args);
|
|
119
|
+
console.error('[Linux] kexec failed.');
|
|
120
|
+
} catch (err: any) {
|
|
121
|
+
if (
|
|
122
|
+
err.code === 'MODULE_NOT_FOUND' ||
|
|
123
|
+
err.code === 'ERR_MODULE_NOT_FOUND' ||
|
|
124
|
+
err.code === 'UNDECLARED_DEPENDENCY'
|
|
125
|
+
) {
|
|
126
|
+
spawnSimulate(unshare, args);
|
|
127
|
+
} else {
|
|
128
|
+
console.error('[Linux] <%s> kexec failed:', err.code, err);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PathArray } from '@idlebox/common';
|
|
2
|
+
import { resolve } from 'path';
|
|
3
|
+
import { existsSync } from '../fs/exists';
|
|
4
|
+
import { PathEnvironment } from './pathEnvironment';
|
|
5
|
+
|
|
6
|
+
export function findBinary(what: string, pathvar: PathArray = new PathEnvironment(), cwd = process.cwd()) {
|
|
7
|
+
for (const path of pathvar.values()) {
|
|
8
|
+
if (existsSync(path + '/' + what)) {
|
|
9
|
+
return resolve(cwd, path, what);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return '';
|
|
13
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export interface IEnvironmentResult {
|
|
2
|
+
value: string | undefined;
|
|
3
|
+
name: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export function getEnvironment(name: string, env = process.env): IEnvironmentResult {
|
|
7
|
+
if (env.hasOwnProperty(name)) {
|
|
8
|
+
return {
|
|
9
|
+
value: env[name],
|
|
10
|
+
name: name,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
name = name.toLowerCase();
|
|
14
|
+
for (const item of Object.keys(env)) {
|
|
15
|
+
if (item.toLowerCase() === name) {
|
|
16
|
+
return {
|
|
17
|
+
value: env[item],
|
|
18
|
+
name: item,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
value: undefined,
|
|
25
|
+
name,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function deleteEnvironment(name: string, env = process.env) {
|
|
30
|
+
for (const item of Object.keys(env)) {
|
|
31
|
+
if (item.toLowerCase() === name) {
|
|
32
|
+
delete env[item];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function cleanupEnvironment(name: string, env = process.env) {
|
|
38
|
+
if (env.hasOwnProperty(name)) {
|
|
39
|
+
for (const item of Object.keys(env)) {
|
|
40
|
+
if (item.toLowerCase() === name && name !== item) {
|
|
41
|
+
delete env[item];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
} else {
|
|
45
|
+
let first = true;
|
|
46
|
+
for (const item of Object.keys(env)) {
|
|
47
|
+
if (item.toLowerCase() === name) {
|
|
48
|
+
if (first) {
|
|
49
|
+
first = false;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
delete env[item];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { linux_case } from '@idlebox/common';
|
|
2
|
+
import { dirname } from 'path';
|
|
3
|
+
import { spawnGetOutput } from '../child_process/execa';
|
|
4
|
+
|
|
5
|
+
export async function getNpmConfigValue(field: string): Promise<string> {
|
|
6
|
+
const env_name = 'npm_config_' + linux_case(field);
|
|
7
|
+
if (typeof process.env[env_name] === 'string') {
|
|
8
|
+
return process.env[env_name]!;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return await spawnGetOutput({
|
|
12
|
+
exec: ['npm', 'config', 'get', field],
|
|
13
|
+
addonPath: [dirname(process.argv0)],
|
|
14
|
+
}).catch(() => '');
|
|
15
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { PathArray } from '@idlebox/common';
|
|
2
|
+
import { platform } from 'os';
|
|
3
|
+
import { cleanupEnvironment, getEnvironment } from './getEnvironment';
|
|
4
|
+
|
|
5
|
+
export const PATH_SEPARATOR = platform() === 'win32' ? ';' : ':';
|
|
6
|
+
export class PathEnvironment extends PathArray {
|
|
7
|
+
private readonly name: string;
|
|
8
|
+
private readonly env: NodeJS.ProcessEnv;
|
|
9
|
+
|
|
10
|
+
constructor(varName = platform() === 'win32' ? 'Path' : 'PATH', env: NodeJS.ProcessEnv = process.env) {
|
|
11
|
+
const { name, value } = getEnvironment(varName, env);
|
|
12
|
+
super('', PATH_SEPARATOR);
|
|
13
|
+
|
|
14
|
+
this.name = name;
|
|
15
|
+
this.env = env;
|
|
16
|
+
|
|
17
|
+
if (value) super.add(value);
|
|
18
|
+
cleanupEnvironment(varName);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
add(p: string) {
|
|
22
|
+
const pSize = this.size;
|
|
23
|
+
super.add(p);
|
|
24
|
+
if (pSize !== this.size) {
|
|
25
|
+
this.save();
|
|
26
|
+
}
|
|
27
|
+
return this;
|
|
28
|
+
}
|
|
29
|
+
clear() {
|
|
30
|
+
const change = this.size > 0;
|
|
31
|
+
super.clear();
|
|
32
|
+
if (change) this.save();
|
|
33
|
+
}
|
|
34
|
+
delete(p: string) {
|
|
35
|
+
if (super.delete(p)) {
|
|
36
|
+
this.save();
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
save() {
|
|
43
|
+
this.env[this.name] = this.toString();
|
|
44
|
+
}
|
|
45
|
+
}
|