target-run 0.1.0
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/README.md +70 -0
- package/dist/bin/target-run.d.ts +3 -0
- package/dist/bin/target-run.d.ts.map +1 -0
- package/dist/bin/target-run.js +52 -0
- package/dist/bin/target-run.js.map +1 -0
- package/dist/src/detector.d.ts +21 -0
- package/dist/src/detector.d.ts.map +1 -0
- package/dist/src/detector.js +18 -0
- package/dist/src/detector.js.map +1 -0
- package/dist/src/dispatcher.d.ts +33 -0
- package/dist/src/dispatcher.d.ts.map +1 -0
- package/dist/src/dispatcher.js +110 -0
- package/dist/src/dispatcher.js.map +1 -0
- package/dist/src/errors.d.ts +41 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.js +63 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +6 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/resolver.d.ts +38 -0
- package/dist/src/resolver.d.ts.map +1 -0
- package/dist/src/resolver.js +34 -0
- package/dist/src/resolver.js.map +1 -0
- package/dist/src/runner.d.ts +20 -0
- package/dist/src/runner.d.ts.map +1 -0
- package/dist/src/runner.js +52 -0
- package/dist/src/runner.js.map +1 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# target-run
|
|
2
|
+
|
|
3
|
+
OS & architecture-aware script dispatcher. Define platform-specific scripts
|
|
4
|
+
in `package.json` and let `target-run` pick the right one at runtime.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
npm install --save-dev target-run
|
|
10
|
+
# or
|
|
11
|
+
pnpm add -D target-run
|
|
12
|
+
# or
|
|
13
|
+
yarn add -D target-run
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## How it works
|
|
17
|
+
|
|
18
|
+
Replace any script body with `target-run`, then add variants using the naming convention:
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
<script>:<platform>:<arch>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
`target-run` tries candidates in this order and runs the first match:
|
|
25
|
+
|
|
26
|
+
1. `<script>:<platform>:<arch>`: exact (e.g. `test:linux:x64`)
|
|
27
|
+
2. `<script>:<platform>`: OS-only (e.g. `test:darwin`)
|
|
28
|
+
3. `<script>:<arch>`: arch-only (e.g. `test:arm64`)
|
|
29
|
+
4. `<script>:default`: explicit fallback
|
|
30
|
+
|
|
31
|
+
Platform values come from `os.platform()` (`win32`, `darwin`, `linux`, etc) and
|
|
32
|
+
arch values from `os.arch()` (`x64`, `arm64`, `ia32`, etc).
|
|
33
|
+
|
|
34
|
+
## Example
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"scripts": {
|
|
39
|
+
"test": "target-run",
|
|
40
|
+
"test:darwin:arm64": "jest --config jest.apple-silicon.config.ts",
|
|
41
|
+
"test:linux:x64": "jest --config jest.linux.config.ts",
|
|
42
|
+
"test:default": "jest"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Running `npm test` (or `pnpm test`, `yarn test`, `bun run test`) dispatches
|
|
48
|
+
to the variant that matches the current machine.
|
|
49
|
+
|
|
50
|
+
## CLI options
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
Usage: target-run [options]
|
|
54
|
+
|
|
55
|
+
Options:
|
|
56
|
+
--help, -h Print this help message
|
|
57
|
+
--version, -v Print the package version
|
|
58
|
+
--dry-run Resolve and print the target script key without executing
|
|
59
|
+
--verbose Print platform, arch, resolved key, and runner details
|
|
60
|
+
--optional Exit 0 silently when no matching script is found
|
|
61
|
+
--required Exit 1 when no matching script is found (overrides lifecycle hook skip)
|
|
62
|
+
--script <name> Override the base script name (bypasses npm_lifecycle_event)
|
|
63
|
+
--cwd <path> Set the working directory for package.json lookup
|
|
64
|
+
|
|
65
|
+
Naming convention:
|
|
66
|
+
<script>:<platform>:<arch> Exact match (e.g. test:linux:x64)
|
|
67
|
+
<script>:<platform> OS-only fallback (e.g. test:linux)
|
|
68
|
+
<script>:<arch> Arch-only fallback (e.g. test:x64)
|
|
69
|
+
<script>:default Explicit default
|
|
70
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"target-run.d.ts","sourceRoot":"","sources":["../../bin/target-run.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { dispatch } from "../src/dispatcher.js";
|
|
6
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const args = process.argv.slice(2);
|
|
8
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
9
|
+
console.log(`target-run — OS & architecture-aware script dispatcher
|
|
10
|
+
|
|
11
|
+
Usage: target-run [options]
|
|
12
|
+
|
|
13
|
+
Options:
|
|
14
|
+
--help, -h Print this help message
|
|
15
|
+
--version, -v Print the package version
|
|
16
|
+
--dry-run Resolve and print the target script key without executing
|
|
17
|
+
--verbose Print platform, arch, resolved key, and runner details
|
|
18
|
+
--optional Exit 0 silently when no matching script is found instead of
|
|
19
|
+
erroring — useful for hooks that only apply to some platforms
|
|
20
|
+
--required Exit 1 when no matching script is found, even for lifecycle hooks
|
|
21
|
+
(e.g. preinstall) whose missing variant would normally be skipped
|
|
22
|
+
silently — use this to enforce that every platform has a variant
|
|
23
|
+
--script <name> Override the base script name (bypasses npm_lifecycle_event)
|
|
24
|
+
--cwd <path> Set the working directory for package.json lookup
|
|
25
|
+
|
|
26
|
+
Naming convention:
|
|
27
|
+
<script>:<platform>:<arch> Exact match (e.g. test:linux:x64)
|
|
28
|
+
<script>:<platform> OS-only fallback (e.g. test:linux)
|
|
29
|
+
<script>:<arch> Arch-only fallback (e.g. test:x64)
|
|
30
|
+
<script>:default Explicit default
|
|
31
|
+
`);
|
|
32
|
+
process.exit(0);
|
|
33
|
+
}
|
|
34
|
+
if (args.includes("--version") || args.includes("-v")) {
|
|
35
|
+
const pkgPath = path.join(__dirname, "../package.json");
|
|
36
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
37
|
+
console.log(pkg.version);
|
|
38
|
+
process.exit(0);
|
|
39
|
+
}
|
|
40
|
+
const getArg = (flag) => {
|
|
41
|
+
const idx = args.indexOf(flag);
|
|
42
|
+
return idx !== -1 ? args[idx + 1] : undefined;
|
|
43
|
+
};
|
|
44
|
+
dispatch({
|
|
45
|
+
dryRun: args.includes("--dry-run"),
|
|
46
|
+
verbose: args.includes("--verbose"),
|
|
47
|
+
optional: args.includes("--optional"),
|
|
48
|
+
required: args.includes("--required"),
|
|
49
|
+
baseScript: getArg("--script"),
|
|
50
|
+
cwd: getArg("--cwd"),
|
|
51
|
+
});
|
|
52
|
+
//# sourceMappingURL=target-run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"target-run.js","sourceRoot":"","sources":["../../bin/target-run.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;IACpD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;CAsBZ,CAAC,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACjB,CAAC;AAED,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;IACvD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;IACxD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAEtD,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACjB,CAAC;AAED,MAAM,MAAM,GAAG,CAAC,IAAY,EAAsB,EAAE;IACnD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/C,CAAC,CAAC;AAEF,QAAQ,CAAC;IACR,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;IAClC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;IACnC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC;IACrC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC;IACrC,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;IAC9B,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC;CACpB,CAAC,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import os from "node:os";
|
|
2
|
+
export type Detector = {
|
|
3
|
+
getPlatform: () => string;
|
|
4
|
+
getArch: () => string;
|
|
5
|
+
};
|
|
6
|
+
type OsModule = Pick<typeof os, "platform" | "arch">;
|
|
7
|
+
/**
|
|
8
|
+
* Creates a Detector from any object that exposes platform() and arch().
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* // production
|
|
12
|
+
* import { defaultDetector } from "./detect.js";
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // test
|
|
16
|
+
* const detector = createDetector({ platform: () => "win32", arch: () => "x64" });
|
|
17
|
+
*/
|
|
18
|
+
export declare const createDetector: (osModule: OsModule) => Detector;
|
|
19
|
+
export declare const defaultDetector: Detector;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../../src/detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,MAAM,MAAM,QAAQ,GAAG;IACtB,WAAW,EAAE,MAAM,MAAM,CAAC;IAC1B,OAAO,EAAE,MAAM,MAAM,CAAC;CACtB,CAAC;AAEF,KAAK,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,GAAG,MAAM,CAAC,CAAC;AAErD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,GAAI,UAAU,QAAQ,KAAG,QAGlD,CAAC;AAEH,eAAO,MAAM,eAAe,EAAE,QAA6B,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import os from "node:os";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a Detector from any object that exposes platform() and arch().
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* // production
|
|
7
|
+
* import { defaultDetector } from "./detect.js";
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* // test
|
|
11
|
+
* const detector = createDetector({ platform: () => "win32", arch: () => "x64" });
|
|
12
|
+
*/
|
|
13
|
+
export const createDetector = (osModule) => ({
|
|
14
|
+
getPlatform: () => osModule.platform(),
|
|
15
|
+
getArch: () => osModule.arch(),
|
|
16
|
+
});
|
|
17
|
+
export const defaultDetector = createDetector(os);
|
|
18
|
+
//# sourceMappingURL=detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detector.js","sourceRoot":"","sources":["../../src/detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AASzB;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAkB,EAAY,EAAE,CAAC,CAAC;IAChE,WAAW,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE;IACtC,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE;CAC9B,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,eAAe,GAAa,cAAc,CAAC,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type Detector } from "./detector.js";
|
|
2
|
+
export type DispatcherOptions = {
|
|
3
|
+
/** Resolve and print the script key without executing anything. */
|
|
4
|
+
dryRun?: boolean;
|
|
5
|
+
/** Print platform, arch, resolved key, and runner details to stderr. */
|
|
6
|
+
verbose?: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Exit 0 silently when no matching script is found instead of erroring.
|
|
9
|
+
* Useful for hooks that only apply to some platforms.
|
|
10
|
+
*/
|
|
11
|
+
optional?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Exit 1 when no matching script is found, even for lifecycle hooks (e.g.
|
|
14
|
+
* `preinstall`) whose missing platform variant would normally be skipped
|
|
15
|
+
* silently. Use this to enforce that every target platform has a variant.
|
|
16
|
+
*/
|
|
17
|
+
required?: boolean;
|
|
18
|
+
/** Working directory used to locate package.json. Defaults to process.cwd(). */
|
|
19
|
+
cwd?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Override the base script name instead of reading npm_lifecycle_event.
|
|
22
|
+
* Useful when invoking the dispatcher programmatically or from --script flag.
|
|
23
|
+
*/
|
|
24
|
+
baseScript?: string;
|
|
25
|
+
/** Injectable OS detector — supply a stub in unit tests. */
|
|
26
|
+
detector?: Detector;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Main entry point. Resolves the correct platform/arch script and runs it.
|
|
30
|
+
* All errors are caught, printed to stderr, and result in exit code 1.
|
|
31
|
+
*/
|
|
32
|
+
export declare const dispatch: (options?: DispatcherOptions) => void;
|
|
33
|
+
//# sourceMappingURL=dispatcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/dispatcher.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,QAAQ,EAAmB,MAAM,eAAe,CAAC;AAS/D,MAAM,MAAM,iBAAiB,GAAG;IAC/B,mEAAmE;IACnE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,wEAAwE;IACxE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gFAAgF;IAChF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACpB,CAAC;AAgCF;;;GAGG;AACH,eAAO,MAAM,QAAQ,GAAI,UAAS,iBAAsB,KAAG,IA8F1D,CAAC"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { defaultDetector } from "./detector.js";
|
|
4
|
+
import { LifecycleEventError, PackageJsonError, ScriptNotFoundError, } from "./errors.js";
|
|
5
|
+
import { resolveScript } from "./resolver.js";
|
|
6
|
+
import { run } from "./runner.js";
|
|
7
|
+
/**
|
|
8
|
+
* Walks up the directory tree from startDir until it finds a package.json.
|
|
9
|
+
*/
|
|
10
|
+
const findPackageJson = (startDir) => {
|
|
11
|
+
let dir = startDir;
|
|
12
|
+
while (true) {
|
|
13
|
+
const candidate = path.join(dir, "package.json");
|
|
14
|
+
if (fs.existsSync(candidate))
|
|
15
|
+
return candidate;
|
|
16
|
+
const parent = path.dirname(dir);
|
|
17
|
+
if (parent === dir)
|
|
18
|
+
break;
|
|
19
|
+
dir = parent;
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Reads and returns the `scripts` field from a package.json file.
|
|
25
|
+
* @throws {PackageJsonError} on read or parse failures.
|
|
26
|
+
*/
|
|
27
|
+
const readScripts = (pkgPath) => {
|
|
28
|
+
try {
|
|
29
|
+
const content = fs.readFileSync(pkgPath, "utf8");
|
|
30
|
+
const pkg = JSON.parse(content);
|
|
31
|
+
return pkg.scripts ?? {};
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
35
|
+
throw new PackageJsonError(`Failed to read/parse ${pkgPath}: ${msg}`);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Main entry point. Resolves the correct platform/arch script and runs it.
|
|
40
|
+
* All errors are caught, printed to stderr, and result in exit code 1.
|
|
41
|
+
*/
|
|
42
|
+
export const dispatch = (options = {}) => {
|
|
43
|
+
try {
|
|
44
|
+
const cwd = options.cwd ?? process.cwd();
|
|
45
|
+
const detector = options.detector ?? defaultDetector;
|
|
46
|
+
const pkgPath = findPackageJson(cwd);
|
|
47
|
+
if (!pkgPath) {
|
|
48
|
+
throw new PackageJsonError(`No package.json found searching upward from: ${cwd}`);
|
|
49
|
+
}
|
|
50
|
+
const scripts = readScripts(pkgPath);
|
|
51
|
+
if (Object.keys(scripts).length === 0) {
|
|
52
|
+
process.exit(0);
|
|
53
|
+
}
|
|
54
|
+
const baseScript = options.baseScript ?? process.env["npm_lifecycle_event"];
|
|
55
|
+
if (!baseScript) {
|
|
56
|
+
throw new LifecycleEventError();
|
|
57
|
+
}
|
|
58
|
+
const platform = detector.getPlatform();
|
|
59
|
+
const arch = detector.getArch();
|
|
60
|
+
if (options.verbose) {
|
|
61
|
+
console.error(`[target-run] Script : ${baseScript}`);
|
|
62
|
+
console.error(`[target-run] Platform : ${platform}`);
|
|
63
|
+
console.error(`[target-run] Architecture : ${arch}`);
|
|
64
|
+
}
|
|
65
|
+
const result = resolveScript({ base: baseScript, platform, arch, scripts });
|
|
66
|
+
if (result.key === null) {
|
|
67
|
+
// Level 5 — lifecycle hook self-reference, no platform variant found.
|
|
68
|
+
if (result.skipped && !options.required) {
|
|
69
|
+
if (options.verbose) {
|
|
70
|
+
console.error(`[target-run] No platform variant for '${baseScript}', skipping silently (self-reference).`);
|
|
71
|
+
}
|
|
72
|
+
process.exit(0);
|
|
73
|
+
}
|
|
74
|
+
// Level 6 — genuinely no match (or --required forces hard failure on level 5).
|
|
75
|
+
if (options.optional) {
|
|
76
|
+
if (options.verbose) {
|
|
77
|
+
console.error(`[target-run] No matching script found, exiting 0 (--optional).`);
|
|
78
|
+
}
|
|
79
|
+
process.exit(0);
|
|
80
|
+
}
|
|
81
|
+
const available = Object.keys(scripts).filter((k) => k.startsWith(`${baseScript}:`));
|
|
82
|
+
throw new ScriptNotFoundError(`No matching script for '${baseScript}' on ${platform}/${arch}`, baseScript, platform, arch, result.tried, available);
|
|
83
|
+
}
|
|
84
|
+
if (options.verbose) {
|
|
85
|
+
console.error(`[target-run] Resolved : ${result.key}`);
|
|
86
|
+
}
|
|
87
|
+
const exitCode = run({
|
|
88
|
+
scriptKey: result.key,
|
|
89
|
+
command: result.command,
|
|
90
|
+
dryRun: options.dryRun,
|
|
91
|
+
verbose: options.verbose,
|
|
92
|
+
});
|
|
93
|
+
process.exit(exitCode);
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
if (err instanceof ScriptNotFoundError) {
|
|
97
|
+
console.error("[target-run] ERROR: No matching script found.");
|
|
98
|
+
console.error(` Calling script : ${err.baseScript}`);
|
|
99
|
+
console.error(` Platform : ${err.platform}`);
|
|
100
|
+
console.error(` Architecture : ${err.arch}`);
|
|
101
|
+
console.error(` Tried keys : ${err.tried.join(", ")}`);
|
|
102
|
+
console.error(` Available : ${err.available.join(", ") || "(none)"}`);
|
|
103
|
+
}
|
|
104
|
+
else if (err instanceof Error) {
|
|
105
|
+
console.error(`[target-run] ERROR: ${err.message}`);
|
|
106
|
+
}
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
//# sourceMappingURL=dispatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/dispatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base error class for all target-run errors.
|
|
3
|
+
*/
|
|
4
|
+
export declare class DispatcherError extends Error {
|
|
5
|
+
constructor(message: string);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Thrown when package.json cannot be found or parsed.
|
|
9
|
+
*/
|
|
10
|
+
export declare class PackageJsonError extends DispatcherError {
|
|
11
|
+
constructor(message: string);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Thrown when no matching script is found and the invocation is not optional.
|
|
15
|
+
* Carries diagnostic metadata for a human-readable error message.
|
|
16
|
+
*/
|
|
17
|
+
export declare class ScriptNotFoundError extends DispatcherError {
|
|
18
|
+
readonly baseScript: string;
|
|
19
|
+
readonly platform: string;
|
|
20
|
+
readonly arch: string;
|
|
21
|
+
readonly tried: string[];
|
|
22
|
+
readonly available: string[];
|
|
23
|
+
constructor(message: string, baseScript: string, platform: string, arch: string, tried: string[], available: string[]);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Thrown when npm_lifecycle_event is not set, meaning the tool was not
|
|
27
|
+
* invoked through a package manager script.
|
|
28
|
+
*/
|
|
29
|
+
export declare class LifecycleEventError extends DispatcherError {
|
|
30
|
+
constructor();
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Thrown when a resolved platform-specific script command would invoke
|
|
34
|
+
* target-run again, creating an infinite subprocess loop.
|
|
35
|
+
*/
|
|
36
|
+
export declare class CircularDispatchError extends DispatcherError {
|
|
37
|
+
readonly scriptKey: string;
|
|
38
|
+
readonly command: string;
|
|
39
|
+
constructor(scriptKey: string, command: string);
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,eAAgB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI3B;AAED;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,eAAe;gBACxC,OAAO,EAAE,MAAM;CAI3B;AAED;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,eAAe;aAGtC,UAAU,EAAE,MAAM;aAClB,QAAQ,EAAE,MAAM;aAChB,IAAI,EAAE,MAAM;aACZ,KAAK,EAAE,MAAM,EAAE;aACf,SAAS,EAAE,MAAM,EAAE;gBALnC,OAAO,EAAE,MAAM,EACC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EAAE,EACf,SAAS,EAAE,MAAM,EAAE;CAKpC;AAED;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,eAAe;;CAOvD;AAED;;;GAGG;AACH,qBAAa,qBAAsB,SAAQ,eAAe;aAExC,SAAS,EAAE,MAAM;aACjB,OAAO,EAAE,MAAM;gBADf,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM;CAOhC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base error class for all target-run errors.
|
|
3
|
+
*/
|
|
4
|
+
export class DispatcherError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "DispatcherError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Thrown when package.json cannot be found or parsed.
|
|
12
|
+
*/
|
|
13
|
+
export class PackageJsonError extends DispatcherError {
|
|
14
|
+
constructor(message) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = "PackageJsonError";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Thrown when no matching script is found and the invocation is not optional.
|
|
21
|
+
* Carries diagnostic metadata for a human-readable error message.
|
|
22
|
+
*/
|
|
23
|
+
export class ScriptNotFoundError extends DispatcherError {
|
|
24
|
+
baseScript;
|
|
25
|
+
platform;
|
|
26
|
+
arch;
|
|
27
|
+
tried;
|
|
28
|
+
available;
|
|
29
|
+
constructor(message, baseScript, platform, arch, tried, available) {
|
|
30
|
+
super(message);
|
|
31
|
+
this.baseScript = baseScript;
|
|
32
|
+
this.platform = platform;
|
|
33
|
+
this.arch = arch;
|
|
34
|
+
this.tried = tried;
|
|
35
|
+
this.available = available;
|
|
36
|
+
this.name = "ScriptNotFoundError";
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Thrown when npm_lifecycle_event is not set, meaning the tool was not
|
|
41
|
+
* invoked through a package manager script.
|
|
42
|
+
*/
|
|
43
|
+
export class LifecycleEventError extends DispatcherError {
|
|
44
|
+
constructor() {
|
|
45
|
+
super("npm_lifecycle_event is not set. target-run must be invoked via a package manager script.");
|
|
46
|
+
this.name = "LifecycleEventError";
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Thrown when a resolved platform-specific script command would invoke
|
|
51
|
+
* target-run again, creating an infinite subprocess loop.
|
|
52
|
+
*/
|
|
53
|
+
export class CircularDispatchError extends DispatcherError {
|
|
54
|
+
scriptKey;
|
|
55
|
+
command;
|
|
56
|
+
constructor(scriptKey, command) {
|
|
57
|
+
super(`Circular dispatch detected: '${scriptKey}' resolves to '${command}', which would invoke target-run again.`);
|
|
58
|
+
this.scriptKey = scriptKey;
|
|
59
|
+
this.command = command;
|
|
60
|
+
this.name = "CircularDispatchError";
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACzC,YAAY,OAAe;QAC1B,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAC/B,CAAC;CACD;AAED;;GAEG;AACH,MAAM,OAAO,gBAAiB,SAAQ,eAAe;IACpD,YAAY,OAAe;QAC1B,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IAChC,CAAC;CACD;AAED;;;GAGG;AACH,MAAM,OAAO,mBAAoB,SAAQ,eAAe;IAGtC;IACA;IACA;IACA;IACA;IANjB,YACC,OAAe,EACC,UAAkB,EAClB,QAAgB,EAChB,IAAY,EACZ,KAAe,EACf,SAAmB;QAEnC,KAAK,CAAC,OAAO,CAAC,CAAC;QANC,eAAU,GAAV,UAAU,CAAQ;QAClB,aAAQ,GAAR,QAAQ,CAAQ;QAChB,SAAI,GAAJ,IAAI,CAAQ;QACZ,UAAK,GAAL,KAAK,CAAU;QACf,cAAS,GAAT,SAAS,CAAU;QAGnC,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACnC,CAAC;CACD;AAED;;;GAGG;AACH,MAAM,OAAO,mBAAoB,SAAQ,eAAe;IACvD;QACC,KAAK,CACJ,0FAA0F,CAC1F,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACnC,CAAC;CACD;AAED;;;GAGG;AACH,MAAM,OAAO,qBAAsB,SAAQ,eAAe;IAExC;IACA;IAFjB,YACiB,SAAiB,EACjB,OAAe;QAE/B,KAAK,CACJ,gCAAgC,SAAS,kBAAkB,OAAO,yCAAyC,CAC3G,CAAC;QALc,cAAS,GAAT,SAAS,CAAQ;QACjB,YAAO,GAAP,OAAO,CAAQ;QAK/B,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACrC,CAAC;CACD"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createDetector, type Detector, defaultDetector } from "./detector.js";
|
|
2
|
+
export { type DispatcherOptions, dispatch } from "./dispatcher.js";
|
|
3
|
+
export { CircularDispatchError, DispatcherError, LifecycleEventError, PackageJsonError, ScriptNotFoundError, } from "./errors.js";
|
|
4
|
+
export { type ResolveScriptParams, type ResolveScriptResult, resolveScript, } from "./resolver.js";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC/E,OAAO,EAAE,KAAK,iBAAiB,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EACN,qBAAqB,EACrB,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,aAAa,GACb,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Public programmatic API
|
|
2
|
+
export { createDetector, defaultDetector } from "./detector.js";
|
|
3
|
+
export { dispatch } from "./dispatcher.js";
|
|
4
|
+
export { CircularDispatchError, DispatcherError, LifecycleEventError, PackageJsonError, ScriptNotFoundError, } from "./errors.js";
|
|
5
|
+
export { resolveScript, } from "./resolver.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAE1B,OAAO,EAAE,cAAc,EAAiB,eAAe,EAAE,MAAM,eAAe,CAAC;AAC/E,OAAO,EAA0B,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EACN,qBAAqB,EACrB,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAGN,aAAa,GACb,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export type ResolveScriptParams = {
|
|
2
|
+
base: string;
|
|
3
|
+
platform: string;
|
|
4
|
+
arch: string;
|
|
5
|
+
scripts: Record<string, string>;
|
|
6
|
+
};
|
|
7
|
+
/** A script was found — key and command are both guaranteed non-null. */
|
|
8
|
+
type ResolveScriptFound = {
|
|
9
|
+
key: string;
|
|
10
|
+
command: string;
|
|
11
|
+
tried: string[];
|
|
12
|
+
skipped?: never;
|
|
13
|
+
};
|
|
14
|
+
/** No script matched — key/command are null; skipped signals a silent skip. */
|
|
15
|
+
type ResolveScriptMissed = {
|
|
16
|
+
key: null;
|
|
17
|
+
command: null;
|
|
18
|
+
tried: string[];
|
|
19
|
+
/** True when the base script is `target-run` itself and no platform variant
|
|
20
|
+
* was found — the canonical signal for a silent lifecycle-hook skip. */
|
|
21
|
+
skipped?: boolean;
|
|
22
|
+
};
|
|
23
|
+
export type ResolveScriptResult = ResolveScriptFound | ResolveScriptMissed;
|
|
24
|
+
/**
|
|
25
|
+
* Resolves the correct script key using the fallback chain:
|
|
26
|
+
*
|
|
27
|
+
* 1. `<base>:<platform>:<arch>` — exact match
|
|
28
|
+
* 2. `<base>:<platform>` — OS-only match
|
|
29
|
+
* 3. `<base>:<arch>` — arch-only match
|
|
30
|
+
* 4. `<base>:default` — explicit default
|
|
31
|
+
* 5. Self-reference skip — if base script value is "target-run", skipped=true
|
|
32
|
+
*
|
|
33
|
+
* Returns `{ key: null, command: null, tried }` (with optional `skipped`)
|
|
34
|
+
* when nothing matches.
|
|
35
|
+
*/
|
|
36
|
+
export declare const resolveScript: (params: ResolveScriptParams) => ResolveScriptResult;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/resolver.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,mBAAmB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC,CAAC;AAEF,yEAAyE;AACzE,KAAK,kBAAkB,GAAG;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,CAAC,EAAE,KAAK,CAAC;CAChB,CAAC;AAEF,+EAA+E;AAC/E,KAAK,mBAAmB,GAAG;IAC1B,GAAG,EAAE,IAAI,CAAC;IACV,OAAO,EAAE,IAAI,CAAC;IACd,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;6EACyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,kBAAkB,GAAG,mBAAmB,CAAC;AAE3E;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,GACzB,QAAQ,mBAAmB,KACzB,mBAwBF,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves the correct script key using the fallback chain:
|
|
3
|
+
*
|
|
4
|
+
* 1. `<base>:<platform>:<arch>` — exact match
|
|
5
|
+
* 2. `<base>:<platform>` — OS-only match
|
|
6
|
+
* 3. `<base>:<arch>` — arch-only match
|
|
7
|
+
* 4. `<base>:default` — explicit default
|
|
8
|
+
* 5. Self-reference skip — if base script value is "target-run", skipped=true
|
|
9
|
+
*
|
|
10
|
+
* Returns `{ key: null, command: null, tried }` (with optional `skipped`)
|
|
11
|
+
* when nothing matches.
|
|
12
|
+
*/
|
|
13
|
+
export const resolveScript = (params) => {
|
|
14
|
+
const { base, platform, arch, scripts } = params;
|
|
15
|
+
const tried = [];
|
|
16
|
+
const candidates = [
|
|
17
|
+
`${base}:${platform}:${arch}`,
|
|
18
|
+
`${base}:${platform}`,
|
|
19
|
+
`${base}:${arch}`,
|
|
20
|
+
`${base}:default`,
|
|
21
|
+
];
|
|
22
|
+
for (const key of candidates) {
|
|
23
|
+
tried.push(key);
|
|
24
|
+
if (scripts[key]) {
|
|
25
|
+
return { key, command: scripts[key], tried };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// Level 5: self-reference skip for optional lifecycle hooks.
|
|
29
|
+
if (scripts[base] === "target-run") {
|
|
30
|
+
return { key: null, command: null, tried, skipped: true };
|
|
31
|
+
}
|
|
32
|
+
return { key: null, command: null, tried };
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/resolver.ts"],"names":[],"mappings":"AA2BA;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAC5B,MAA2B,EACL,EAAE;IACxB,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IACjD,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,MAAM,UAAU,GAAG;QAClB,GAAG,IAAI,IAAI,QAAQ,IAAI,IAAI,EAAE;QAC7B,GAAG,IAAI,IAAI,QAAQ,EAAE;QACrB,GAAG,IAAI,IAAI,IAAI,EAAE;QACjB,GAAG,IAAI,UAAU;KACjB,CAAC;IAEF,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChB,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAClB,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAW,EAAE,KAAK,EAAE,CAAC;QACxD,CAAC;IACF,CAAC;IAED,6DAA6D;IAC7D,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,YAAY,EAAE,CAAC;QACpC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3D,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AAC5C,CAAC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Infers the package manager by inspecting npm_execpath, which all major
|
|
3
|
+
* package managers (npm, pnpm, yarn, bun) set automatically when running scripts.
|
|
4
|
+
*/
|
|
5
|
+
export declare const detectPackageManager: () => string;
|
|
6
|
+
export type RunnerOptions = {
|
|
7
|
+
scriptKey: string;
|
|
8
|
+
command: string;
|
|
9
|
+
dryRun?: boolean;
|
|
10
|
+
verbose?: boolean;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Spawns the resolved script via the detected package manager.
|
|
14
|
+
* Returns the exit code of the child process.
|
|
15
|
+
*
|
|
16
|
+
* @throws {CircularDispatchError} If the resolved command would invoke target-run again.
|
|
17
|
+
* @throws {Error} If the spawned process fails to start.
|
|
18
|
+
*/
|
|
19
|
+
export declare const run: (options: RunnerOptions) => number;
|
|
20
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/runner.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,eAAO,MAAM,oBAAoB,QAAO,MAQvC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,GAAG,GAAI,SAAS,aAAa,KAAG,MAiC5C,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { CircularDispatchError } from "./errors.js";
|
|
3
|
+
/**
|
|
4
|
+
* Infers the package manager by inspecting npm_execpath, which all major
|
|
5
|
+
* package managers (npm, pnpm, yarn, bun) set automatically when running scripts.
|
|
6
|
+
*/
|
|
7
|
+
export const detectPackageManager = () => {
|
|
8
|
+
const execPath = process.env["npm_execpath"];
|
|
9
|
+
if (!execPath)
|
|
10
|
+
return "npm";
|
|
11
|
+
const normalized = execPath.toLowerCase().replace(/\\/g, "/");
|
|
12
|
+
if (normalized.includes("pnpm"))
|
|
13
|
+
return "pnpm";
|
|
14
|
+
if (normalized.includes("yarn"))
|
|
15
|
+
return "yarn";
|
|
16
|
+
if (normalized.includes("bun"))
|
|
17
|
+
return "bun";
|
|
18
|
+
return "npm";
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Spawns the resolved script via the detected package manager.
|
|
22
|
+
* Returns the exit code of the child process.
|
|
23
|
+
*
|
|
24
|
+
* @throws {CircularDispatchError} If the resolved command would invoke target-run again.
|
|
25
|
+
* @throws {Error} If the spawned process fails to start.
|
|
26
|
+
*/
|
|
27
|
+
export const run = (options) => {
|
|
28
|
+
const { scriptKey, command, dryRun, verbose } = options;
|
|
29
|
+
// Guard against circular dispatch before spawning anything.
|
|
30
|
+
const trimmed = command.trim();
|
|
31
|
+
if (trimmed === "target-run" || trimmed.startsWith("target-run ")) {
|
|
32
|
+
throw new CircularDispatchError(scriptKey, command);
|
|
33
|
+
}
|
|
34
|
+
const packageManager = detectPackageManager();
|
|
35
|
+
if (verbose) {
|
|
36
|
+
console.error(`[target-run] Package manager : ${packageManager}`);
|
|
37
|
+
console.error(`[target-run] Running : ${packageManager} run ${scriptKey}`);
|
|
38
|
+
}
|
|
39
|
+
if (dryRun) {
|
|
40
|
+
console.log(`[target-run] Would run: ${packageManager} run ${scriptKey}`);
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
const result = spawnSync(packageManager, ["run", scriptKey], {
|
|
44
|
+
stdio: "inherit",
|
|
45
|
+
shell: false,
|
|
46
|
+
});
|
|
47
|
+
if (result.error) {
|
|
48
|
+
throw result.error;
|
|
49
|
+
}
|
|
50
|
+
return result.status ?? 1;
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEpD;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAW,EAAE;IAChD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC7C,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5B,MAAM,UAAU,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC9D,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IAC/C,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IAC/C,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7C,OAAO,KAAK,CAAC;AACd,CAAC,CAAC;AASF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,OAAsB,EAAU,EAAE;IACrD,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAExD,4DAA4D;IAC5D,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAC/B,IAAI,OAAO,KAAK,YAAY,IAAI,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QACnE,MAAM,IAAI,qBAAqB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,cAAc,GAAG,oBAAoB,EAAE,CAAC;IAE9C,IAAI,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,kCAAkC,cAAc,EAAE,CAAC,CAAC;QAClE,OAAO,CAAC,KAAK,CACZ,kCAAkC,cAAc,QAAQ,SAAS,EAAE,CACnE,CAAC;IACH,CAAC;IAED,IAAI,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,2BAA2B,cAAc,QAAQ,SAAS,EAAE,CAAC,CAAC;QAC1E,OAAO,CAAC,CAAC;IACV,CAAC;IAED,MAAM,MAAM,GAAG,SAAS,CAAC,cAAc,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE;QAC5D,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,KAAK;KACZ,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,MAAM,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;AAC3B,CAAC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "target-run",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "OS & architecture-aware script dispatcher",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"author": "Carlos Menezes",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"engines": {
|
|
9
|
+
"node": ">=24.0.0"
|
|
10
|
+
},
|
|
11
|
+
"bin": {
|
|
12
|
+
"target-run": "dist/bin/target-run.js"
|
|
13
|
+
},
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"import": "./dist/src/index.js",
|
|
17
|
+
"types": "./dist/src/index.d.ts"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist/"
|
|
22
|
+
],
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@biomejs/biome": "2.4.7",
|
|
25
|
+
"@changesets/cli": "^2.30.0",
|
|
26
|
+
"@types/node": "^22.0.0",
|
|
27
|
+
"tsx": "^4.19.3",
|
|
28
|
+
"typescript": "^5.9.3",
|
|
29
|
+
"vitest": "^3.1.1"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsc",
|
|
33
|
+
"test": "vitest run",
|
|
34
|
+
"test:watch": "vitest",
|
|
35
|
+
"lint": "biome lint .",
|
|
36
|
+
"format": "biome format .",
|
|
37
|
+
"check": "biome check .",
|
|
38
|
+
"changeset": "changeset",
|
|
39
|
+
"version": "changeset version",
|
|
40
|
+
"release": "pnpm build && pnpm publish --access public"
|
|
41
|
+
}
|
|
42
|
+
}
|