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 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,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=target-run.d.ts.map
@@ -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
+ }