@vltpkg/run 0.0.0-0.1730239248325
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/LICENSE +15 -0
- package/README.md +62 -0
- package/dist/esm/index.d.ts +125 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +225 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/package.json +66 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Copyright (c) vlt technology, Inc.
|
|
2
|
+
|
|
3
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
4
|
+
|
|
5
|
+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
6
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
7
|
+
Subject to the terms and conditions of this license, each copyright holder and contributor hereby grants to those receiving rights under this license a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except for failure to satisfy the conditions of this license) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer this software, where such license applies only to those patent claims, already acquired or hereafter acquired, licensable by such copyright holder or contributor that are necessarily infringed by:
|
|
8
|
+
|
|
9
|
+
(a) their Contribution(s) (the licensed copyrights of copyright holders and non-copyrightable additions of contributors, in source or binary form) alone; or
|
|
10
|
+
(b) combination of their Contribution(s) with the work of authorship to which such Contribution(s) was added by such copyright holder or contributor, if, at the time the Contribution is added, such addition causes such combination to be necessarily infringed. The patent license shall not apply to any other combinations which include the Contribution.
|
|
11
|
+
Except as expressly stated above, no rights or licenses from any copyright holder or contributor is granted under this license, whether expressly, by implication, estoppel or otherwise.
|
|
12
|
+
|
|
13
|
+
DISCLAIMER
|
|
14
|
+
|
|
15
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# `@vltpkg/run`
|
|
2
|
+
|
|
3
|
+
Run a script defined in a `package.json` file (eg, `vlt run` and
|
|
4
|
+
lifecycle scripts), or an arbitrary command as if it was (eg,
|
|
5
|
+
`vlt exec`).
|
|
6
|
+
|
|
7
|
+
## USAGE
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
import { run, exec } from '@vltpkg/run'
|
|
11
|
+
|
|
12
|
+
const cwd = '/path/to/pkg'
|
|
13
|
+
|
|
14
|
+
// to run a script, as with `vlt run blah`
|
|
15
|
+
const runResult = await run({
|
|
16
|
+
// the name of the thing in package.json#scripts
|
|
17
|
+
event: 'build',
|
|
18
|
+
|
|
19
|
+
// the dir where the package.json lives
|
|
20
|
+
cwd,
|
|
21
|
+
|
|
22
|
+
// if the script is not defined in package.json#scripts, just
|
|
23
|
+
// ignore it and treat as success. Otherwise, treat as an
|
|
24
|
+
// error. Default false.
|
|
25
|
+
ignoreMissing: true,
|
|
26
|
+
|
|
27
|
+
// extra arguments to pass into the child process
|
|
28
|
+
args: ['some', 'arguments'],
|
|
29
|
+
|
|
30
|
+
// the environment variables to add, defaults to process.env.
|
|
31
|
+
// note that @vltpkg/run will add some of its own, as well:
|
|
32
|
+
// - npm_lifecycle_event: the event name
|
|
33
|
+
// - npm_lifecycle_script: the command in package.json#scripts
|
|
34
|
+
// - npm_package_json: path to the package.json file
|
|
35
|
+
// - VLT_* envs for all vlt configuration values that are set
|
|
36
|
+
env: process.env,
|
|
37
|
+
|
|
38
|
+
// set this to `true` to take over the terminal and run in the
|
|
39
|
+
// foreground, inheriting the parent process's stdio
|
|
40
|
+
// by default, the script runs in the background.
|
|
41
|
+
// Only one foreground:true script will be run in parallel!
|
|
42
|
+
foreground: true,
|
|
43
|
+
|
|
44
|
+
// the shell to run the script in. Defaults to `${SHELL}` env
|
|
45
|
+
// variable if set, otherwise the system specific shell,
|
|
46
|
+
// `cmd.exe` on windows, and `/bin/sh` on posix.
|
|
47
|
+
'script-shell': '/usr/bin/bash',
|
|
48
|
+
|
|
49
|
+
// pass in a @vltpkg/package-json.PackageJson instance, and
|
|
50
|
+
// it'll be used for reading the package.json file. Optional,
|
|
51
|
+
// may improve performance somewhat.
|
|
52
|
+
packageJson: new PackageJson(),
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
// to execute an arbitrary command, as with `vlt exec whatever`
|
|
56
|
+
const execResult = await exec({
|
|
57
|
+
// the command to execute.
|
|
58
|
+
command: 'do-something',
|
|
59
|
+
args: ['some', 'arguments'],
|
|
60
|
+
// other arguments all the same.
|
|
61
|
+
})
|
|
62
|
+
```
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { PackageJson } from '@vltpkg/package-json';
|
|
2
|
+
import { PromiseSpawnOptions, type SpawnResultNoStdio, type SpawnResultStdioStrings } from '@vltpkg/promise-spawn';
|
|
3
|
+
import { Manifest } from '@vltpkg/types';
|
|
4
|
+
/** options shared by run() and exec() */
|
|
5
|
+
export type SharedOptions = PromiseSpawnOptions & {
|
|
6
|
+
/** additional arguments to pass to the command */
|
|
7
|
+
args?: string[];
|
|
8
|
+
/** the root of the project, which we don't walk up past */
|
|
9
|
+
projectRoot: string;
|
|
10
|
+
/** the directory where the package.json lives and the script runs */
|
|
11
|
+
cwd: string;
|
|
12
|
+
/**
|
|
13
|
+
* environment variables to set. `process.env` is always included,
|
|
14
|
+
* to omit fields, set them explicitly to undefined.
|
|
15
|
+
*
|
|
16
|
+
* vlt will add some of its own, as well:
|
|
17
|
+
* - npm_lifecycle_event: the event name
|
|
18
|
+
* - npm_lifecycle_script: the command in package.json#scripts
|
|
19
|
+
* - npm_package_json: path to the package.json file
|
|
20
|
+
* - VLT_* envs for all vlt configuration values that are set
|
|
21
|
+
*/
|
|
22
|
+
env?: NodeJS.ProcessEnv;
|
|
23
|
+
/**
|
|
24
|
+
* the shell to run the script in. If not set, then the default
|
|
25
|
+
* platform-specific shell will be used.
|
|
26
|
+
*/
|
|
27
|
+
'script-shell'?: boolean | string;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Options for run() and runFG()
|
|
31
|
+
*/
|
|
32
|
+
export type RunOptions = SharedOptions & {
|
|
33
|
+
/** the name of the thing in package.json#scripts */
|
|
34
|
+
arg0: string;
|
|
35
|
+
/**
|
|
36
|
+
* pass in a @vltpkg/package-json.PackageJson instance, and
|
|
37
|
+
* it'll be used for reading the package.json file. Optional,
|
|
38
|
+
* may improve performance somewhat.
|
|
39
|
+
*/
|
|
40
|
+
packageJson?: PackageJson;
|
|
41
|
+
/**
|
|
42
|
+
* Pass in a manifest to avoid having to read it at all
|
|
43
|
+
*/
|
|
44
|
+
manifest?: Manifest;
|
|
45
|
+
/**
|
|
46
|
+
* if the script is not defined in package.json#scripts, just ignore it and
|
|
47
|
+
* treat as success. Otherwise, treat as an error. Default false.
|
|
48
|
+
*/
|
|
49
|
+
ignoreMissing?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* skip the pre/post commands, just run the one specified.
|
|
52
|
+
* This can be used to run JUST the specified script, without any
|
|
53
|
+
* pre/post commands.
|
|
54
|
+
*/
|
|
55
|
+
ignorePrePost?: boolean;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Options for exec() and execFG()
|
|
59
|
+
*/
|
|
60
|
+
export type ExecOptions = SharedOptions & {
|
|
61
|
+
/** the command to execute */
|
|
62
|
+
arg0: string;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Options for runExec() and runExecFG()
|
|
66
|
+
*/
|
|
67
|
+
export type RunExecOptions = SharedOptions & {
|
|
68
|
+
/**
|
|
69
|
+
* Either the command to be executed, or the event to be run
|
|
70
|
+
*/
|
|
71
|
+
arg0: string;
|
|
72
|
+
/**
|
|
73
|
+
* pass in a @vltpkg/package-json.PackageJson instance, and
|
|
74
|
+
* it'll be used for reading the package.json file. Optional,
|
|
75
|
+
* may improve performance somewhat.
|
|
76
|
+
*/
|
|
77
|
+
packageJson?: PackageJson;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Run a package.json#scripts event in the background
|
|
81
|
+
*/
|
|
82
|
+
export declare const run: (options: RunOptions) => Promise<RunResult>;
|
|
83
|
+
/**
|
|
84
|
+
* Run a package.json#scripts event in the foreground
|
|
85
|
+
*/
|
|
86
|
+
export declare const runFG: (options: RunOptions) => Promise<RunFGResult>;
|
|
87
|
+
/** Return type of {@link run} */
|
|
88
|
+
export type RunResult = SpawnResultStdioStrings & {
|
|
89
|
+
pre?: SpawnResultStdioStrings;
|
|
90
|
+
post?: SpawnResultStdioStrings;
|
|
91
|
+
};
|
|
92
|
+
/** Return type of {@link runFG} */
|
|
93
|
+
export type RunFGResult = SpawnResultNoStdio & {
|
|
94
|
+
pre?: SpawnResultNoStdio;
|
|
95
|
+
post?: SpawnResultNoStdio;
|
|
96
|
+
};
|
|
97
|
+
export declare const isRunResult: (v: unknown) => v is RunResult;
|
|
98
|
+
/**
|
|
99
|
+
* Return type of {@link run} or {@link runFG}, as determined by their base
|
|
100
|
+
* type
|
|
101
|
+
*
|
|
102
|
+
* @internal
|
|
103
|
+
*/
|
|
104
|
+
export type RunImplResult<R extends SpawnResultNoStdio | SpawnResultStdioStrings> = R & {
|
|
105
|
+
pre?: R;
|
|
106
|
+
post?: R;
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* Execute an arbitrary command in the background
|
|
110
|
+
*/
|
|
111
|
+
export declare const exec: (options: ExecOptions) => Promise<SpawnResultStdioStrings>;
|
|
112
|
+
/**
|
|
113
|
+
* Execute an arbitrary command in the foreground
|
|
114
|
+
*/
|
|
115
|
+
export declare const execFG: (options: ExecOptions) => Promise<SpawnResultNoStdio>;
|
|
116
|
+
/**
|
|
117
|
+
* If the arg0 is a defined package.json script, then run(), otherwise exec()
|
|
118
|
+
*/
|
|
119
|
+
export declare const runExec: (options: RunExecOptions) => Promise<RunResult | SpawnResultStdioStrings>;
|
|
120
|
+
/**
|
|
121
|
+
* If the arg0 is a defined package.json script, then runFG(), otherwise
|
|
122
|
+
* execFG()
|
|
123
|
+
*/
|
|
124
|
+
export declare const runExecFG: (options: RunExecOptions) => Promise<RunFGResult | SpawnResultNoStdio>;
|
|
125
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,EAEL,mBAAmB,EACnB,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC7B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAiDxC,yCAAyC;AACzC,MAAM,MAAM,aAAa,GAAG,mBAAmB,GAAG;IAChD,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,2DAA2D;IAC3D,WAAW,EAAE,MAAM,CAAA;IAEnB,qEAAqE;IACrE,GAAG,EAAE,MAAM,CAAA;IACX;;;;;;;;;OASG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IACvB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;CAClC,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG;IACvC,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,WAAW,CAAC,EAAE,WAAW,CAAA;IAEzB;;OAEG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAA;IAEnB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IAEvB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG;IACxC,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG;IAC3C;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,GAAG,YAAmB,UAAU,KAAG,OAAO,CAAC,SAAS,CACrC,CAAA;AAE5B;;GAEG;AACH,eAAO,MAAM,KAAK,YACP,UAAU,KAClB,OAAO,CAAC,WAAW,CAAmC,CAAA;AAEzD,iCAAiC;AACjC,MAAM,MAAM,SAAS,GAAG,uBAAuB,GAAG;IAChD,GAAG,CAAC,EAAE,uBAAuB,CAAA;IAC7B,IAAI,CAAC,EAAE,uBAAuB,CAAA;CAC/B,CAAA;AAED,mCAAmC;AACnC,MAAM,MAAM,WAAW,GAAG,kBAAkB,GAAG;IAC7C,GAAG,CAAC,EAAE,kBAAkB,CAAA;IACxB,IAAI,CAAC,EAAE,kBAAkB,CAAA;CAC1B,CAAA;AAED,eAAO,MAAM,WAAW,MAAO,OAAO,KAAG,CAAC,IAAI,SAO/B,CAAA;AAEf;;;;;GAKG;AACH,MAAM,MAAM,aAAa,CACvB,CAAC,SAAS,kBAAkB,GAAG,uBAAuB,IACpD,CAAC,GAAG;IAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IAAC,IAAI,CAAC,EAAE,CAAC,CAAA;CAAE,CAAA;AAkH7B;;GAEG;AACH,eAAO,MAAM,IAAI,YACN,WAAW,KACnB,OAAO,CAAC,uBAAuB,CAyBjC,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,MAAM,YACR,WAAW,KACnB,OAAO,CAAC,kBAAkB,CAsC5B,CAAA;AAoBD;;GAEG;AACH,eAAO,MAAM,OAAO,YACT,cAAc,KACtB,OAAO,CAAC,SAAS,GAAG,uBAAuB,CACY,CAAA;AAE1D;;;GAGG;AACH,eAAO,MAAM,SAAS,YACX,cAAc,KACtB,OAAO,CAAC,WAAW,GAAG,kBAAkB,CACc,CAAA"}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { error } from '@vltpkg/error-cause';
|
|
2
|
+
import { PackageJson } from '@vltpkg/package-json';
|
|
3
|
+
import { promiseSpawn, } from '@vltpkg/promise-spawn';
|
|
4
|
+
import { foregroundChild } from 'foreground-child';
|
|
5
|
+
import { proxySignals } from 'foreground-child/proxy-signals';
|
|
6
|
+
import { statSync } from 'node:fs';
|
|
7
|
+
import { delimiter, resolve } from 'node:path';
|
|
8
|
+
import { walkUp } from 'walk-up-path';
|
|
9
|
+
/** map of which node_modules/.bin folders exist */
|
|
10
|
+
const dotBins = new Map();
|
|
11
|
+
/** Check if a directory exists, and cache result */
|
|
12
|
+
const dirExists = (p) => {
|
|
13
|
+
const cached = dotBins.get(p);
|
|
14
|
+
if (cached !== undefined)
|
|
15
|
+
return cached;
|
|
16
|
+
try {
|
|
17
|
+
const isDir = statSync(p).isDirectory();
|
|
18
|
+
dotBins.set(p, isDir);
|
|
19
|
+
return isDir;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
dotBins.set(p, false);
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Add all exsting `node_modules/.bin` folders to the PATH that
|
|
28
|
+
* exist between the cwd and the projectRoot, so dependency bins
|
|
29
|
+
* are found, with closer paths higher priority.
|
|
30
|
+
*/
|
|
31
|
+
const addPaths = (projectRoot, cwd, env) => {
|
|
32
|
+
const { PATH = '' } = env;
|
|
33
|
+
const paths = new Set();
|
|
34
|
+
for (const p of walkUp(cwd)) {
|
|
35
|
+
const dotBin = resolve(p, 'node_modules/.bin');
|
|
36
|
+
if (dirExists(dotBin))
|
|
37
|
+
paths.add(dotBin);
|
|
38
|
+
if (p === projectRoot)
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
for (const p of PATH.split(delimiter)) {
|
|
42
|
+
/* c8 ignore next - pretty rare to have an empty entry */
|
|
43
|
+
if (p)
|
|
44
|
+
paths.add(p);
|
|
45
|
+
}
|
|
46
|
+
env.PATH = [...paths].join(delimiter);
|
|
47
|
+
return env;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Run a package.json#scripts event in the background
|
|
51
|
+
*/
|
|
52
|
+
export const run = async (options) => runImpl(options, exec, '');
|
|
53
|
+
/**
|
|
54
|
+
* Run a package.json#scripts event in the foreground
|
|
55
|
+
*/
|
|
56
|
+
export const runFG = async (options) => runImpl(options, execFG, null);
|
|
57
|
+
export const isRunResult = (v) => !!v &&
|
|
58
|
+
typeof v === 'object' &&
|
|
59
|
+
!Array.isArray(v) &&
|
|
60
|
+
'stdout' in v &&
|
|
61
|
+
'stderr' in v &&
|
|
62
|
+
'status' in v &&
|
|
63
|
+
'signal' in v;
|
|
64
|
+
/**
|
|
65
|
+
* Internal implementation of run() and runFG(), since they're mostly identical
|
|
66
|
+
*/
|
|
67
|
+
const runImpl = async (options, execImpl, empty) => {
|
|
68
|
+
const { arg0, packageJson = new PackageJson(), ignoreMissing = false, manifest, ...execArgs } = options;
|
|
69
|
+
const pjPath = resolve(options.cwd, 'package.json');
|
|
70
|
+
// npm adds a `"install": "node-gyp rebuild"` if a binding.gyp
|
|
71
|
+
// is present at the time of publish, EVEN IF it's not included
|
|
72
|
+
// in the package. So, we need to read the actual package.json
|
|
73
|
+
// in those cases.
|
|
74
|
+
const untrustworthy = !!(manifest?.gypfile &&
|
|
75
|
+
arg0 === 'install' &&
|
|
76
|
+
manifest.scripts?.install === 'node-gyp rebuild');
|
|
77
|
+
const pj = (untrustworthy ? undefined : manifest) ??
|
|
78
|
+
packageJson.read(options.cwd);
|
|
79
|
+
const { scripts } = pj;
|
|
80
|
+
const command = scripts?.[arg0];
|
|
81
|
+
if (!command) {
|
|
82
|
+
if (ignoreMissing) {
|
|
83
|
+
return {
|
|
84
|
+
command: '',
|
|
85
|
+
/* c8 ignore next */
|
|
86
|
+
args: execArgs.args ?? [],
|
|
87
|
+
cwd: options.cwd,
|
|
88
|
+
status: 0,
|
|
89
|
+
signal: null,
|
|
90
|
+
stdout: empty,
|
|
91
|
+
stderr: empty,
|
|
92
|
+
// `as` to workaround "could be instantiated with arbitrary type".
|
|
93
|
+
// it's private and used in 2 places, we know that it isn't.
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
throw error('Script not defined in package.json', {
|
|
97
|
+
name: arg0,
|
|
98
|
+
cwd: options.cwd,
|
|
99
|
+
args: options.args,
|
|
100
|
+
path: pjPath,
|
|
101
|
+
manifest: pj,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
const precommand = !options.ignorePrePost && scripts[`pre${arg0}`];
|
|
105
|
+
const pre = precommand ?
|
|
106
|
+
await execImpl({
|
|
107
|
+
arg0: precommand,
|
|
108
|
+
...execArgs,
|
|
109
|
+
args: [],
|
|
110
|
+
env: {
|
|
111
|
+
...execArgs.env,
|
|
112
|
+
npm_package_json: pjPath,
|
|
113
|
+
npm_lifecycle_event: `pre${arg0}`,
|
|
114
|
+
npm_lifecycle_script: precommand,
|
|
115
|
+
},
|
|
116
|
+
})
|
|
117
|
+
: undefined;
|
|
118
|
+
if (pre && (pre.status || pre.signal)) {
|
|
119
|
+
return pre;
|
|
120
|
+
}
|
|
121
|
+
const result = await execImpl({
|
|
122
|
+
arg0: command,
|
|
123
|
+
...execArgs,
|
|
124
|
+
env: {
|
|
125
|
+
...execArgs.env,
|
|
126
|
+
npm_package_json: pjPath,
|
|
127
|
+
npm_lifecycle_event: arg0,
|
|
128
|
+
npm_lifecycle_script: command,
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
result.pre = pre;
|
|
132
|
+
if (result.signal || result.status) {
|
|
133
|
+
return result;
|
|
134
|
+
}
|
|
135
|
+
const postcommand = !options.ignorePrePost && scripts[`post${arg0}`];
|
|
136
|
+
if (!postcommand)
|
|
137
|
+
return result;
|
|
138
|
+
const post = await execImpl({
|
|
139
|
+
arg0: postcommand,
|
|
140
|
+
...execArgs,
|
|
141
|
+
args: [],
|
|
142
|
+
env: {
|
|
143
|
+
...execArgs.env,
|
|
144
|
+
npm_package_json: pjPath,
|
|
145
|
+
npm_lifecycle_event: `post${arg0}`,
|
|
146
|
+
npm_lifecycle_script: postcommand,
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
if (post.status || post.signal) {
|
|
150
|
+
const { status, signal } = post;
|
|
151
|
+
return Object.assign(result, { post, status, signal });
|
|
152
|
+
}
|
|
153
|
+
result.post = post;
|
|
154
|
+
return result;
|
|
155
|
+
};
|
|
156
|
+
/**
|
|
157
|
+
* Execute an arbitrary command in the background
|
|
158
|
+
*/
|
|
159
|
+
export const exec = async (options) => {
|
|
160
|
+
const { arg0, args = [], cwd, env = {}, projectRoot, 'script-shell': shell = true, ...spawnOptions } = options;
|
|
161
|
+
const p = promiseSpawn(arg0, args, {
|
|
162
|
+
...spawnOptions,
|
|
163
|
+
shell,
|
|
164
|
+
stdio: 'pipe',
|
|
165
|
+
stdioString: true,
|
|
166
|
+
cwd,
|
|
167
|
+
env: addPaths(projectRoot, cwd, {
|
|
168
|
+
...process.env,
|
|
169
|
+
...env,
|
|
170
|
+
}),
|
|
171
|
+
windowsHide: true,
|
|
172
|
+
});
|
|
173
|
+
proxySignals(p.process);
|
|
174
|
+
return await p;
|
|
175
|
+
};
|
|
176
|
+
/**
|
|
177
|
+
* Execute an arbitrary command in the foreground
|
|
178
|
+
*/
|
|
179
|
+
export const execFG = async (options) => {
|
|
180
|
+
const { arg0, args = [], cwd, projectRoot, env = {}, 'script-shell': shell = true, ...spawnOptions } = options;
|
|
181
|
+
return new Promise(res => {
|
|
182
|
+
foregroundChild(arg0, args, {
|
|
183
|
+
...spawnOptions,
|
|
184
|
+
shell,
|
|
185
|
+
cwd,
|
|
186
|
+
env: addPaths(projectRoot, cwd, {
|
|
187
|
+
...process.env,
|
|
188
|
+
...env,
|
|
189
|
+
}),
|
|
190
|
+
}, (status, signal) => {
|
|
191
|
+
res({
|
|
192
|
+
command: arg0,
|
|
193
|
+
args,
|
|
194
|
+
cwd,
|
|
195
|
+
stdout: null,
|
|
196
|
+
stderr: null,
|
|
197
|
+
status,
|
|
198
|
+
signal,
|
|
199
|
+
});
|
|
200
|
+
return false;
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
};
|
|
204
|
+
const runExecImpl = async (options, runImpl, execImpl) => {
|
|
205
|
+
const { arg0, packageJson = new PackageJson(), ...args } = options;
|
|
206
|
+
const pj = packageJson.read(options.cwd);
|
|
207
|
+
const { scripts } = pj;
|
|
208
|
+
const command = scripts?.[arg0];
|
|
209
|
+
if (command) {
|
|
210
|
+
return runImpl({ ...args, packageJson, arg0 });
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
return execImpl({ ...args, arg0 });
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
/**
|
|
217
|
+
* If the arg0 is a defined package.json script, then run(), otherwise exec()
|
|
218
|
+
*/
|
|
219
|
+
export const runExec = async (options) => runExecImpl(options, run, exec);
|
|
220
|
+
/**
|
|
221
|
+
* If the arg0 is a defined package.json script, then runFG(), otherwise
|
|
222
|
+
* execFG()
|
|
223
|
+
*/
|
|
224
|
+
export const runExecFG = async (options) => runExecImpl(options, runFG, execFG);
|
|
225
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { error } from '@vltpkg/error-cause'\nimport { PackageJson } from '@vltpkg/package-json'\nimport {\n promiseSpawn,\n PromiseSpawnOptions,\n type SpawnResultNoStdio,\n type SpawnResultStdioStrings,\n} from '@vltpkg/promise-spawn'\nimport { Manifest } from '@vltpkg/types'\nimport { foregroundChild } from 'foreground-child'\nimport { proxySignals } from 'foreground-child/proxy-signals'\nimport { statSync } from 'node:fs'\nimport { delimiter, resolve } from 'node:path'\nimport { walkUp } from 'walk-up-path'\n\n/** map of which node_modules/.bin folders exist */\nconst dotBins = new Map<string, boolean>()\n\n/** Check if a directory exists, and cache result */\nconst dirExists = (p: string) => {\n const cached = dotBins.get(p)\n if (cached !== undefined) return cached\n try {\n const isDir = statSync(p).isDirectory()\n dotBins.set(p, isDir)\n return isDir\n } catch {\n dotBins.set(p, false)\n return false\n }\n}\n\n/**\n * Add all exsting `node_modules/.bin` folders to the PATH that\n * exist between the cwd and the projectRoot, so dependency bins\n * are found, with closer paths higher priority.\n */\nconst addPaths = (\n projectRoot: string,\n cwd: string,\n env: NodeJS.ProcessEnv,\n): NodeJS.ProcessEnv => {\n const { PATH = '' } = env\n const paths = new Set<string>()\n for (const p of walkUp(cwd)) {\n const dotBin = resolve(p, 'node_modules/.bin')\n if (dirExists(dotBin)) paths.add(dotBin)\n if (p === projectRoot) break\n }\n for (const p of PATH.split(delimiter)) {\n /* c8 ignore next - pretty rare to have an empty entry */\n if (p) paths.add(p)\n }\n env.PATH = [...paths].join(delimiter)\n return env\n}\n\n/** options shared by run() and exec() */\nexport type SharedOptions = PromiseSpawnOptions & {\n /** additional arguments to pass to the command */\n args?: string[]\n /** the root of the project, which we don't walk up past */\n projectRoot: string\n\n /** the directory where the package.json lives and the script runs */\n cwd: string\n /**\n * environment variables to set. `process.env` is always included,\n * to omit fields, set them explicitly to undefined.\n *\n * vlt will add some of its own, as well:\n * - npm_lifecycle_event: the event name\n * - npm_lifecycle_script: the command in package.json#scripts\n * - npm_package_json: path to the package.json file\n * - VLT_* envs for all vlt configuration values that are set\n */\n env?: NodeJS.ProcessEnv\n /**\n * the shell to run the script in. If not set, then the default\n * platform-specific shell will be used.\n */\n 'script-shell'?: boolean | string\n}\n\n/**\n * Options for run() and runFG()\n */\nexport type RunOptions = SharedOptions & {\n /** the name of the thing in package.json#scripts */\n arg0: string\n /**\n * pass in a @vltpkg/package-json.PackageJson instance, and\n * it'll be used for reading the package.json file. Optional,\n * may improve performance somewhat.\n */\n packageJson?: PackageJson\n\n /**\n * Pass in a manifest to avoid having to read it at all\n */\n manifest?: Manifest\n\n /**\n * if the script is not defined in package.json#scripts, just ignore it and\n * treat as success. Otherwise, treat as an error. Default false.\n */\n ignoreMissing?: boolean\n\n /**\n * skip the pre/post commands, just run the one specified.\n * This can be used to run JUST the specified script, without any\n * pre/post commands.\n */\n ignorePrePost?: boolean\n}\n\n/**\n * Options for exec() and execFG()\n */\nexport type ExecOptions = SharedOptions & {\n /** the command to execute */\n arg0: string\n}\n\n/**\n * Options for runExec() and runExecFG()\n */\nexport type RunExecOptions = SharedOptions & {\n /**\n * Either the command to be executed, or the event to be run\n */\n arg0: string\n /**\n * pass in a @vltpkg/package-json.PackageJson instance, and\n * it'll be used for reading the package.json file. Optional,\n * may improve performance somewhat.\n */\n packageJson?: PackageJson\n}\n\n/**\n * Run a package.json#scripts event in the background\n */\nexport const run = async (options: RunOptions): Promise<RunResult> =>\n runImpl(options, exec, '')\n\n/**\n * Run a package.json#scripts event in the foreground\n */\nexport const runFG = async (\n options: RunOptions,\n): Promise<RunFGResult> => runImpl(options, execFG, null)\n\n/** Return type of {@link run} */\nexport type RunResult = SpawnResultStdioStrings & {\n pre?: SpawnResultStdioStrings\n post?: SpawnResultStdioStrings\n}\n\n/** Return type of {@link runFG} */\nexport type RunFGResult = SpawnResultNoStdio & {\n pre?: SpawnResultNoStdio\n post?: SpawnResultNoStdio\n}\n\nexport const isRunResult = (v: unknown): v is RunResult =>\n !!v &&\n typeof v === 'object' &&\n !Array.isArray(v) &&\n 'stdout' in v &&\n 'stderr' in v &&\n 'status' in v &&\n 'signal' in v\n\n/**\n * Return type of {@link run} or {@link runFG}, as determined by their base\n * type\n *\n * @internal\n */\nexport type RunImplResult<\n R extends SpawnResultNoStdio | SpawnResultStdioStrings,\n> = R & { pre?: R; post?: R }\n\n/**\n * Internal implementation of run() and runFG(), since they're mostly identical\n */\nconst runImpl = async <\n R extends SpawnResultNoStdio | SpawnResultStdioStrings,\n>(\n options: RunOptions,\n execImpl: (options: ExecOptions) => Promise<R>,\n empty: R['stdout'],\n): Promise<RunImplResult<R>> => {\n const {\n arg0,\n packageJson = new PackageJson(),\n ignoreMissing = false,\n manifest,\n ...execArgs\n } = options\n const pjPath = resolve(options.cwd, 'package.json')\n // npm adds a `\"install\": \"node-gyp rebuild\"` if a binding.gyp\n // is present at the time of publish, EVEN IF it's not included\n // in the package. So, we need to read the actual package.json\n // in those cases.\n const untrustworthy = !!(\n manifest?.gypfile &&\n arg0 === 'install' &&\n manifest.scripts?.install === 'node-gyp rebuild'\n )\n const pj =\n (untrustworthy ? undefined : manifest) ??\n packageJson.read(options.cwd)\n const { scripts } = pj\n const command = scripts?.[arg0]\n if (!command) {\n if (ignoreMissing) {\n return {\n command: '',\n /* c8 ignore next */\n args: execArgs.args ?? [],\n cwd: options.cwd,\n status: 0,\n signal: null,\n stdout: empty,\n stderr: empty,\n // `as` to workaround \"could be instantiated with arbitrary type\".\n // it's private and used in 2 places, we know that it isn't.\n } as R\n }\n throw error('Script not defined in package.json', {\n name: arg0,\n cwd: options.cwd,\n args: options.args,\n path: pjPath,\n manifest: pj,\n })\n }\n\n const precommand = !options.ignorePrePost && scripts[`pre${arg0}`]\n const pre =\n precommand ?\n await execImpl({\n arg0: precommand,\n ...execArgs,\n args: [],\n env: {\n ...execArgs.env,\n npm_package_json: pjPath,\n npm_lifecycle_event: `pre${arg0}`,\n npm_lifecycle_script: precommand,\n },\n })\n : undefined\n if (pre && (pre.status || pre.signal)) {\n return pre as RunImplResult<R>\n }\n const result: RunImplResult<R> = await execImpl({\n arg0: command,\n ...execArgs,\n env: {\n ...execArgs.env,\n npm_package_json: pjPath,\n npm_lifecycle_event: arg0,\n npm_lifecycle_script: command,\n },\n })\n result.pre = pre\n if (result.signal || result.status) {\n return result\n }\n\n const postcommand = !options.ignorePrePost && scripts[`post${arg0}`]\n if (!postcommand) return result\n\n const post = await execImpl({\n arg0: postcommand,\n ...execArgs,\n args: [],\n env: {\n ...execArgs.env,\n npm_package_json: pjPath,\n npm_lifecycle_event: `post${arg0}`,\n npm_lifecycle_script: postcommand,\n },\n })\n\n if (post.status || post.signal) {\n const { status, signal } = post\n return Object.assign(result, { post, status, signal })\n }\n result.post = post\n return result\n}\n\n/**\n * Execute an arbitrary command in the background\n */\nexport const exec = async (\n options: ExecOptions,\n): Promise<SpawnResultStdioStrings> => {\n const {\n arg0,\n args = [],\n cwd,\n env = {},\n projectRoot,\n 'script-shell': shell = true,\n ...spawnOptions\n } = options\n\n const p = promiseSpawn(arg0, args, {\n ...spawnOptions,\n shell,\n stdio: 'pipe',\n stdioString: true,\n cwd,\n env: addPaths(projectRoot, cwd, {\n ...process.env,\n ...env,\n }),\n windowsHide: true,\n })\n proxySignals(p.process)\n return await p\n}\n\n/**\n * Execute an arbitrary command in the foreground\n */\nexport const execFG = async (\n options: ExecOptions,\n): Promise<SpawnResultNoStdio> => {\n const {\n arg0,\n args = [],\n cwd,\n projectRoot,\n env = {},\n 'script-shell': shell = true,\n ...spawnOptions\n } = options\n\n return new Promise<SpawnResultNoStdio>(res => {\n foregroundChild(\n arg0,\n args,\n {\n ...spawnOptions,\n shell,\n cwd,\n env: addPaths(projectRoot, cwd, {\n ...process.env,\n ...env,\n }),\n },\n (status, signal) => {\n res({\n command: arg0,\n args,\n cwd,\n stdout: null,\n stderr: null,\n status,\n signal,\n })\n return false\n },\n )\n })\n}\n\nconst runExecImpl = async <\n R extends SpawnResultNoStdio | SpawnResultStdioStrings,\n>(\n options: RunExecOptions,\n runImpl: (options: RunOptions) => Promise<RunImplResult<R>>,\n execImpl: (options: ExecOptions) => Promise<R>,\n): Promise<R | RunImplResult<R>> => {\n const { arg0, packageJson = new PackageJson(), ...args } = options\n const pj = packageJson.read(options.cwd)\n const { scripts } = pj\n const command = scripts?.[arg0]\n if (command) {\n return runImpl({ ...args, packageJson, arg0 })\n } else {\n return execImpl({ ...args, arg0 })\n }\n}\n\n/**\n * If the arg0 is a defined package.json script, then run(), otherwise exec()\n */\nexport const runExec = async (\n options: RunExecOptions,\n): Promise<RunResult | SpawnResultStdioStrings> =>\n runExecImpl<SpawnResultStdioStrings>(options, run, exec)\n\n/**\n * If the arg0 is a defined package.json script, then runFG(), otherwise\n * execFG()\n */\nexport const runExecFG = async (\n options: RunExecOptions,\n): Promise<RunFGResult | SpawnResultNoStdio> =>\n runExecImpl<SpawnResultNoStdio>(options, runFG, execFG)\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vltpkg/run",
|
|
3
|
+
"description": "Run package.json scripts and execute commands",
|
|
4
|
+
"version": "0.0.0-0.1730239248325",
|
|
5
|
+
"tshy": {
|
|
6
|
+
"selfLink": false,
|
|
7
|
+
"dialects": [
|
|
8
|
+
"esm"
|
|
9
|
+
],
|
|
10
|
+
"exports": {
|
|
11
|
+
"./package.json": "./package.json",
|
|
12
|
+
".": "./src/index.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"foreground-child": "^3.2.0",
|
|
17
|
+
"walk-up-path": "^4.0.0",
|
|
18
|
+
"@vltpkg/types": "0.0.0-0.1730239248325",
|
|
19
|
+
"@vltpkg/error-cause": "0.0.0-0.1730239248325",
|
|
20
|
+
"@vltpkg/promise-spawn": "0.0.0-0.1730239248325",
|
|
21
|
+
"@vltpkg/package-json": "0.0.0-0.1730239248325"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@eslint/js": "^9.8.0",
|
|
25
|
+
"@types/eslint__js": "^8.42.3",
|
|
26
|
+
"@types/node": "^22.4.1",
|
|
27
|
+
"eslint": "^9.8.0",
|
|
28
|
+
"prettier": "^3.3.2",
|
|
29
|
+
"tap": "^21.0.1",
|
|
30
|
+
"tshy": "^3.0.2",
|
|
31
|
+
"typescript": "^5.5.4",
|
|
32
|
+
"typescript-eslint": "^8.0.1"
|
|
33
|
+
},
|
|
34
|
+
"license": "BSD-2-Clause-Patent",
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": "20 || >=22"
|
|
37
|
+
},
|
|
38
|
+
"tap": {
|
|
39
|
+
"extends": "../../tap-config.yaml"
|
|
40
|
+
},
|
|
41
|
+
"prettier": "../../.prettierrc.js",
|
|
42
|
+
"module": "./dist/esm/index.js",
|
|
43
|
+
"type": "module",
|
|
44
|
+
"exports": {
|
|
45
|
+
"./package.json": "./package.json",
|
|
46
|
+
".": {
|
|
47
|
+
"import": {
|
|
48
|
+
"types": "./dist/esm/index.d.ts",
|
|
49
|
+
"default": "./dist/esm/index.js"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"files": [
|
|
54
|
+
"dist"
|
|
55
|
+
],
|
|
56
|
+
"scripts": {
|
|
57
|
+
"format": "prettier --write . --log-level warn --ignore-path ../../.prettierignore --cache",
|
|
58
|
+
"format:check": "prettier --check . --ignore-path ../../.prettierignore --cache",
|
|
59
|
+
"lint": "eslint . --fix",
|
|
60
|
+
"lint:check": "eslint .",
|
|
61
|
+
"presnap": "tshy",
|
|
62
|
+
"snap": "tap",
|
|
63
|
+
"pretest": "tshy",
|
|
64
|
+
"test": "tap"
|
|
65
|
+
}
|
|
66
|
+
}
|