@gjsify/cli 0.36.0 → 0.37.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.
Files changed (116) hide show
  1. package/dist/cli.gjs.mjs +3 -3
  2. package/lib/bundler-pick.js +61 -87
  3. package/lib/cli-fail.d.ts +4 -7
  4. package/lib/cli-fail.js +29 -55
  5. package/lib/commands/affected.js +161 -286
  6. package/lib/commands/install.d.ts +63 -66
  7. package/lib/commands/install.js +372 -536
  8. package/lib/templates/install.mjs.tmpl +38 -68
  9. package/lib/types/cli-build-options.d.ts +33 -67
  10. package/lib/types/command.d.ts +9 -12
  11. package/lib/types/config-data.d.ts +125 -221
  12. package/lib/utils/auth-npmrc.d.ts +5 -10
  13. package/lib/utils/auth-npmrc.js +11 -21
  14. package/lib/utils/clear-targets.d.ts +8 -11
  15. package/lib/utils/clear-targets.js +22 -29
  16. package/lib/utils/copy-targets.d.ts +13 -19
  17. package/lib/utils/copy-targets.js +31 -44
  18. package/lib/utils/dep-aggregation.d.ts +7 -15
  19. package/lib/utils/dep-aggregation.js +9 -22
  20. package/lib/utils/detect-native-packages.d.ts +83 -116
  21. package/lib/utils/detect-native-packages.js +111 -149
  22. package/lib/utils/dir-link.d.ts +29 -48
  23. package/lib/utils/dir-link.js +33 -56
  24. package/lib/utils/discover-showcases.d.ts +6 -7
  25. package/lib/utils/discover-showcases.js +11 -15
  26. package/lib/utils/dlx-cache.d.ts +29 -38
  27. package/lib/utils/dlx-cache.js +53 -63
  28. package/lib/utils/force-exit.d.ts +0 -3
  29. package/lib/utils/force-exit.js +13 -24
  30. package/lib/utils/gi-search-path.d.ts +16 -24
  31. package/lib/utils/gi-search-path.js +54 -82
  32. package/lib/utils/gjs-bundle-guard.d.ts +5 -13
  33. package/lib/utils/gjs-bundle-guard.js +35 -57
  34. package/lib/utils/gjs-source-escape.d.ts +2 -2
  35. package/lib/utils/gjs-source-escape.js +21 -39
  36. package/lib/utils/gjsify-shim.d.ts +17 -20
  37. package/lib/utils/gjsify-shim.js +80 -120
  38. package/lib/utils/html-entry.d.ts +8 -12
  39. package/lib/utils/html-entry.js +19 -28
  40. package/lib/utils/install-backend-native.d.ts +123 -161
  41. package/lib/utils/install-backend-native.js +536 -737
  42. package/lib/utils/install-backend.d.ts +42 -57
  43. package/lib/utils/install-backend.js +16 -21
  44. package/lib/utils/install-cache-fs.d.ts +10 -15
  45. package/lib/utils/install-cache-fs.js +18 -26
  46. package/lib/utils/install-lock.d.ts +5 -6
  47. package/lib/utils/install-lock.js +46 -65
  48. package/lib/utils/install-packument-cache.d.ts +27 -33
  49. package/lib/utils/install-packument-cache.js +44 -57
  50. package/lib/utils/install-progress.d.ts +2 -9
  51. package/lib/utils/install-progress.js +14 -39
  52. package/lib/utils/install-tarball-cache.d.ts +14 -20
  53. package/lib/utils/install-tarball-cache.js +41 -59
  54. package/lib/utils/library-output.d.ts +9 -22
  55. package/lib/utils/library-output.js +19 -37
  56. package/lib/utils/load-npmrc.d.ts +5 -6
  57. package/lib/utils/load-npmrc.js +18 -27
  58. package/lib/utils/node-bundle-guard.d.ts +4 -8
  59. package/lib/utils/node-bundle-guard.js +21 -35
  60. package/lib/utils/node-script.js +33 -54
  61. package/lib/utils/node-version.d.ts +5 -14
  62. package/lib/utils/node-version.js +15 -24
  63. package/lib/utils/normalize-bundler-options.d.ts +7 -11
  64. package/lib/utils/normalize-bundler-options.js +24 -42
  65. package/lib/utils/npm-oidc.d.ts +23 -37
  66. package/lib/utils/npm-oidc.js +28 -53
  67. package/lib/utils/npm-otp-cache.d.ts +4 -4
  68. package/lib/utils/npm-otp-cache.js +20 -25
  69. package/lib/utils/npm-otp.d.ts +20 -30
  70. package/lib/utils/npm-otp.js +32 -51
  71. package/lib/utils/onboard-probe.d.ts +7 -13
  72. package/lib/utils/onboard-probe.js +16 -27
  73. package/lib/utils/parse-spec.d.ts +3 -3
  74. package/lib/utils/parse-spec.js +4 -5
  75. package/lib/utils/pkg-json-edit.d.ts +7 -12
  76. package/lib/utils/pkg-json-edit.js +13 -26
  77. package/lib/utils/pkg-json.d.ts +11 -18
  78. package/lib/utils/pkg-json.js +19 -28
  79. package/lib/utils/prefixed-output.d.ts +3 -4
  80. package/lib/utils/prefixed-output.js +13 -19
  81. package/lib/utils/prompt.d.ts +3 -4
  82. package/lib/utils/prompt.js +14 -18
  83. package/lib/utils/publish-diagnose.d.ts +11 -16
  84. package/lib/utils/publish-diagnose.js +15 -28
  85. package/lib/utils/publish-headers.d.ts +7 -11
  86. package/lib/utils/publish-headers.js +36 -65
  87. package/lib/utils/publishable-packages.d.ts +4 -6
  88. package/lib/utils/publishable-packages.js +14 -18
  89. package/lib/utils/resolve-gjs-entry.d.ts +5 -8
  90. package/lib/utils/resolve-gjs-entry.js +10 -27
  91. package/lib/utils/resolve-npm-package.d.ts +6 -11
  92. package/lib/utils/resolve-npm-package.js +29 -63
  93. package/lib/utils/resolve-plugin-by-name.d.ts +11 -19
  94. package/lib/utils/resolve-plugin-by-name.js +9 -14
  95. package/lib/utils/run-gjs.d.ts +16 -21
  96. package/lib/utils/run-gjs.js +31 -56
  97. package/lib/utils/run-lifecycle-script.d.ts +5 -9
  98. package/lib/utils/run-lifecycle-script.js +23 -42
  99. package/lib/utils/run-node.d.ts +21 -33
  100. package/lib/utils/run-node.js +43 -64
  101. package/lib/utils/runtimes.d.ts +25 -35
  102. package/lib/utils/runtimes.js +34 -46
  103. package/lib/utils/spawn.d.ts +32 -48
  104. package/lib/utils/spawn.js +51 -84
  105. package/lib/utils/stdin.d.ts +2 -2
  106. package/lib/utils/stdin.js +10 -25
  107. package/lib/utils/suggest.d.ts +6 -7
  108. package/lib/utils/suggest.js +8 -10
  109. package/lib/utils/system-gi.d.ts +18 -27
  110. package/lib/utils/system-gi.js +60 -114
  111. package/lib/utils/trust-registry.d.ts +4 -8
  112. package/lib/utils/trust-registry.js +7 -15
  113. package/lib/utils/win32-command.d.ts +8 -14
  114. package/lib/utils/win32-command.js +29 -43
  115. package/lib/utils/workspace-root.js +7 -12
  116. package/package.json +18 -18
@@ -1,25 +1,19 @@
1
1
  import { type ExampleRuntime } from './runtimes.js';
2
2
  /**
3
- * Walk up from `startDir` looking for `<node_modules>/@gjsify/node-gi`. Returns
4
- * the package directory, or null when it is not installed anywhere on the chain.
5
- * A plain fs walk (works identically on Node and GJS) — Node's own resolver is
6
- * not available under the GJS-bundled CLI.
3
+ * Walk up from `startDir` for `<node_modules>/@gjsify/node-gi`, returning its package directory
4
+ * or null. A plain fs walk because Node's own resolver is not available under the GJS-bundled CLI.
7
5
  */
8
6
  export declare function resolveNodeGi(startDir: string): string | null;
9
7
  /**
10
- * Resolve `@gjsify/node-gi` for a bundle we are about to launch: from the
11
- * BUNDLE's own directory first, then from `cwd`.
8
+ * Resolve `@gjsify/node-gi` for a bundle about to launch: the BUNDLE's own directory first, then
9
+ * `cwd`.
12
10
  *
13
- * The bundle's directory is the correct base and cwd is the fallback, for the
14
- * same reason {@link computeNativeEnvForBundle} walks both: `@gjsify/node-gi` is
15
- * kept EXTERNAL, so what has to be satisfiable is the RUNTIME's resolution of a
16
- * bare specifier from inside the bundle — which Node performs relative to the
17
- * importing file, never relative to cwd. A dlx-cache layout
18
- * (`~/.cache/gjsify/dlx/<sha>/node_modules/<pkg>/dist/bundle.mjs`) has node-gi
19
- * sitting right beside the bundle and nothing at all under the user's cwd, so a
20
- * cwd-only probe rejected a run that would have worked. The cwd probe is kept
21
- * because a project-local `node_modules` legitimately satisfies a bundle built
22
- * into a `dist/` outside it (a `--outfile /tmp/…` build from a project root).
11
+ * The bundle's directory is the correct base for the same reason {@link computeNativeEnvForBundle}
12
+ * walks both: node-gi is kept EXTERNAL, so what must be satisfiable is the RUNTIME's resolution
13
+ * of a bare specifier from inside the bundle, which Node performs relative to the importing file,
14
+ * never to cwd. A dlx-cache layout has node-gi beside the bundle and nothing under the user's
15
+ * cwd, so a cwd-only probe rejected a run that would have worked. The cwd probe stays because a
16
+ * project-local `node_modules` legitimately satisfies a bundle built into a `dist/` outside it.
23
17
  */
24
18
  export declare function resolveNodeGiForBundle(bundlePath: string, cwd: string): string | null;
25
19
  /** Pick the node executable: the current one when on Node, else PATH `node`. */
@@ -31,29 +25,23 @@ export interface RunNodeBundleOptions {
31
25
  quiet?: boolean;
32
26
  }
33
27
  /**
34
- * Run a `--app node` bundle on Node.js, auto-setting LD_LIBRARY_PATH and
35
- * GI_TYPELIB_PATH for any installed native gjsify packages (same detection as
36
- * {@link runGjsBundle}). Verifies `@gjsify/node-gi` is resolvable first and
37
- * throws a clear, actionable error otherwise.
28
+ * Run a `--app node` bundle on Node.js with the native typelib env set (same detection as
29
+ * {@link runGjsBundle}). Throws when `@gjsify/node-gi` is not resolvable.
38
30
  */
39
31
  export declare function runNodeBundle(bundlePath: string, extraArgs?: string[], options?: RunNodeBundleOptions): Promise<void>;
40
32
  /**
41
- * Whether a `--app node` bundle actually consumes `@gjsify/node-gi` (the gi://
42
- * reverse bridge is kept EXTERNAL, so a bundle that uses gi:// imports the shim
43
- * by name). A plain Node app (express, a pure `node:*` program) does NOT, and
44
- * must run on node/bun/deno WITHOUT node-gi installed — so the node-gi check is
45
- * conditional on this, not unconditional like the storybook path.
33
+ * Whether a `--app node` bundle actually consumes `@gjsify/node-gi` — kept EXTERNAL, so a bundle
34
+ * using gi:// imports the shim by name. A plain Node app does NOT, and must run on node/bun/deno
35
+ * WITHOUT node-gi installed, which is why the check is conditional here and not unconditional
36
+ * like the storybook path.
46
37
  */
47
38
  export declare function bundleRequiresNodeGi(bundlePath: string): boolean;
48
39
  /**
49
- * Run a built bundle on a non-gjs runtime (node / bun / deno). All three consume
50
- * the SAME `--app node` bundle (Node-API is their common ABI), so this is the
51
- * shared launcher `gjsify run --runtime` and `gjsify showcase --runtime` use for
52
- * node/bun/deno. The native typelib env is wired exactly like {@link runGjsBundle}
53
- * (so a bundle pulling an `@gjsify/*` Vala bridge resolves its prebuild), and
54
- * `@gjsify/node-gi` is required ONLY when the bundle actually uses gi://.
40
+ * Run a built bundle on a non-gjs runtime (node / bun / deno). All three consume the SAME
41
+ * `--app node` bundle — Node-API is their common ABI — so this is the shared launcher for
42
+ * `gjsify run --runtime` and `gjsify showcase --runtime`. Native typelib env is wired as in
43
+ * {@link runGjsBundle}; `@gjsify/node-gi` is required ONLY when the bundle actually uses gi://.
55
44
  *
56
- * `gjs` is intentionally NOT handled here — the caller dispatches it to
57
- * {@link runGjsBundle}.
45
+ * `gjs` is intentionally NOT handled here — the caller dispatches it to {@link runGjsBundle}.
58
46
  */
59
47
  export declare function runRuntimeBundle(runtime: Exclude<ExampleRuntime, 'gjs'>, bundlePath: string, extraArgs?: string[], options?: RunNodeBundleOptions): Promise<void>;
@@ -1,26 +1,20 @@
1
1
  // Shared utility for running a `--app node` bundle on Node.js with the native
2
2
  // typelib env wired the same way `runGjsBundle` does.
3
3
  //
4
- // A `gjsify build --app node` bundle of a `gi://` source runs the GObject stack
5
- // through `@gjsify/node-gi` (the Axis-5 reverse bridge). Two things have to be
6
- // true at runtime:
4
+ // A `--app node` bundle of a `gi://` source runs the GObject stack through `@gjsify/node-gi`
5
+ // (the Axis-5 reverse bridge). Two things must hold at runtime:
7
6
  //
8
- // 1. `@gjsify/node-gi` must resolve FROM THE BUNDLE — it is kept EXTERNAL by
9
- // the bundler (a native addon), so it has to physically exist in a
10
- // node_modules the bundle's own directory can reach (that is where Node
11
- // will look), with the CWD as a fallback. We verify this up front and emit
12
- // a clear hint instead of letting Node throw `ERR_MODULE_NOT_FOUND` deep in
13
- // the bundle. See `resolveNodeGiForBundle`.
14
- // 2. `gi://Gtk` / `gi://Adw` etc. must resolve. System typelibs come from the
15
- // default GI search path, but any `@gjsify/*` Vala bridge a story pulls in
16
- // ships its typelib in `prebuilds/` — so we reuse the SAME
17
- // `computeNativeEnvForBundle()` walker `runGjsBundle` uses to prepend
18
- // `GI_TYPELIB_PATH` / `LD_LIBRARY_PATH`. It is a no-op when no native
19
- // gjsify packages are present (the storybook's common case).
7
+ // 1. `@gjsify/node-gi` must resolve FROM THE BUNDLE — the bundler keeps it EXTERNAL (native
8
+ // addon), so it has to physically exist in a node_modules the bundle's own directory can
9
+ // reach, with the CWD as a fallback. Checked up front so the failure is a clear hint
10
+ // rather than an `ERR_MODULE_NOT_FOUND` deep in the bundle (`resolveNodeGiForBundle`).
11
+ // 2. `gi://Gtk` / `gi://Adw` must resolve. System typelibs come from the default GI search
12
+ // path, but an `@gjsify/*` Vala bridge ships its typelib in `prebuilds/`, so the SAME
13
+ // `computeNativeEnvForBundle()` walker `runGjsBundle` uses prepends `GI_TYPELIB_PATH` /
14
+ // `LD_LIBRARY_PATH`. A no-op when no native gjsify packages are present.
20
15
  //
21
- // The node binary is `process.execPath` when the CLI itself runs under Node, and
22
- // the PATH `node` otherwise (under the committed GJS bundle `process.execPath` is
23
- // `gjs`, which cannot run a `--app node` bundle).
16
+ // The node binary is `process.execPath` when the CLI runs under Node, else PATH `node` — under
17
+ // the GJS bundle `process.execPath` is `gjs`, which cannot run a `--app node` bundle.
24
18
  import { spawn } from 'node:child_process';
25
19
  import { existsSync, readFileSync } from 'node:fs';
26
20
  import { dirname, join, resolve } from 'node:path';
@@ -28,10 +22,8 @@ import { isNode } from '@gjsify/rolldown-plugin-gjsify/runtime';
28
22
  import { computeNativeEnvForBundle } from './run-gjs.js';
29
23
  import { RUNTIMES } from './runtimes.js';
30
24
  /**
31
- * Walk up from `startDir` looking for `<node_modules>/@gjsify/node-gi`. Returns
32
- * the package directory, or null when it is not installed anywhere on the chain.
33
- * A plain fs walk (works identically on Node and GJS) — Node's own resolver is
34
- * not available under the GJS-bundled CLI.
25
+ * Walk up from `startDir` for `<node_modules>/@gjsify/node-gi`, returning its package directory
26
+ * or null. A plain fs walk because Node's own resolver is not available under the GJS-bundled CLI.
35
27
  */
36
28
  export function resolveNodeGi(startDir) {
37
29
  let dir = resolve(startDir);
@@ -46,19 +38,15 @@ export function resolveNodeGi(startDir) {
46
38
  }
47
39
  }
48
40
  /**
49
- * Resolve `@gjsify/node-gi` for a bundle we are about to launch: from the
50
- * BUNDLE's own directory first, then from `cwd`.
41
+ * Resolve `@gjsify/node-gi` for a bundle about to launch: the BUNDLE's own directory first, then
42
+ * `cwd`.
51
43
  *
52
- * The bundle's directory is the correct base and cwd is the fallback, for the
53
- * same reason {@link computeNativeEnvForBundle} walks both: `@gjsify/node-gi` is
54
- * kept EXTERNAL, so what has to be satisfiable is the RUNTIME's resolution of a
55
- * bare specifier from inside the bundle — which Node performs relative to the
56
- * importing file, never relative to cwd. A dlx-cache layout
57
- * (`~/.cache/gjsify/dlx/<sha>/node_modules/<pkg>/dist/bundle.mjs`) has node-gi
58
- * sitting right beside the bundle and nothing at all under the user's cwd, so a
59
- * cwd-only probe rejected a run that would have worked. The cwd probe is kept
60
- * because a project-local `node_modules` legitimately satisfies a bundle built
61
- * into a `dist/` outside it (a `--outfile /tmp/…` build from a project root).
44
+ * The bundle's directory is the correct base for the same reason {@link computeNativeEnvForBundle}
45
+ * walks both: node-gi is kept EXTERNAL, so what must be satisfiable is the RUNTIME's resolution
46
+ * of a bare specifier from inside the bundle, which Node performs relative to the importing file,
47
+ * never to cwd. A dlx-cache layout has node-gi beside the bundle and nothing under the user's
48
+ * cwd, so a cwd-only probe rejected a run that would have worked. The cwd probe stays because a
49
+ * project-local `node_modules` legitimately satisfies a bundle built into a `dist/` outside it.
62
50
  */
63
51
  export function resolveNodeGiForBundle(bundlePath, cwd) {
64
52
  const resolvedBundle = resolve(bundlePath);
@@ -69,10 +57,8 @@ export function nodeBinary() {
69
57
  return isNode() && process.execPath ? process.execPath : 'node';
70
58
  }
71
59
  /**
72
- * Run a `--app node` bundle on Node.js, auto-setting LD_LIBRARY_PATH and
73
- * GI_TYPELIB_PATH for any installed native gjsify packages (same detection as
74
- * {@link runGjsBundle}). Verifies `@gjsify/node-gi` is resolvable first and
75
- * throws a clear, actionable error otherwise.
60
+ * Run a `--app node` bundle on Node.js with the native typelib env set (same detection as
61
+ * {@link runGjsBundle}). Throws when `@gjsify/node-gi` is not resolvable.
76
62
  */
77
63
  export async function runNodeBundle(bundlePath, extraArgs = [], options = {}) {
78
64
  const cwd = process.cwd();
@@ -85,8 +71,7 @@ export async function runNodeBundle(bundlePath, extraArgs = [], options = {}) {
85
71
  const env = { ...process.env, ...nativeEnv };
86
72
  const nodeBin = nodeBinary();
87
73
  const nodeArgs = [bundlePath, ...extraArgs];
88
- // Echo the exact command (stderr, so a child speaking a protocol on stdout
89
- // stays uncontaminated) so users can reproduce the run without the wrapper.
74
+ // Echo on stderr, so a child speaking a protocol on stdout stays uncontaminated.
90
75
  const cmd = [nodeBin, ...nodeArgs.map((a) => (a.includes(' ') ? `"${a}"` : a))].join(' ');
91
76
  console.error(`$ ${envPrefix ? `${envPrefix} ` : ''}${cmd}`);
92
77
  const child = spawn(nodeBin, nodeArgs, { env, stdio: 'inherit' });
@@ -106,11 +91,10 @@ export async function runNodeBundle(bundlePath, extraArgs = [], options = {}) {
106
91
  process.exit(0);
107
92
  }
108
93
  /**
109
- * Whether a `--app node` bundle actually consumes `@gjsify/node-gi` (the gi://
110
- * reverse bridge is kept EXTERNAL, so a bundle that uses gi:// imports the shim
111
- * by name). A plain Node app (express, a pure `node:*` program) does NOT, and
112
- * must run on node/bun/deno WITHOUT node-gi installed — so the node-gi check is
113
- * conditional on this, not unconditional like the storybook path.
94
+ * Whether a `--app node` bundle actually consumes `@gjsify/node-gi` — kept EXTERNAL, so a bundle
95
+ * using gi:// imports the shim by name. A plain Node app does NOT, and must run on node/bun/deno
96
+ * WITHOUT node-gi installed, which is why the check is conditional here and not unconditional
97
+ * like the storybook path.
114
98
  */
115
99
  export function bundleRequiresNodeGi(bundlePath) {
116
100
  try {
@@ -121,15 +105,12 @@ export function bundleRequiresNodeGi(bundlePath) {
121
105
  }
122
106
  }
123
107
  /**
124
- * Run a built bundle on a non-gjs runtime (node / bun / deno). All three consume
125
- * the SAME `--app node` bundle (Node-API is their common ABI), so this is the
126
- * shared launcher `gjsify run --runtime` and `gjsify showcase --runtime` use for
127
- * node/bun/deno. The native typelib env is wired exactly like {@link runGjsBundle}
128
- * (so a bundle pulling an `@gjsify/*` Vala bridge resolves its prebuild), and
129
- * `@gjsify/node-gi` is required ONLY when the bundle actually uses gi://.
108
+ * Run a built bundle on a non-gjs runtime (node / bun / deno). All three consume the SAME
109
+ * `--app node` bundle — Node-API is their common ABI — so this is the shared launcher for
110
+ * `gjsify run --runtime` and `gjsify showcase --runtime`. Native typelib env is wired as in
111
+ * {@link runGjsBundle}; `@gjsify/node-gi` is required ONLY when the bundle actually uses gi://.
130
112
  *
131
- * `gjs` is intentionally NOT handled here — the caller dispatches it to
132
- * {@link runGjsBundle}.
113
+ * `gjs` is intentionally NOT handled here — the caller dispatches it to {@link runGjsBundle}.
133
114
  */
134
115
  export async function runRuntimeBundle(runtime, bundlePath, extraArgs = [], options = {}) {
135
116
  const cwd = process.cwd();
@@ -141,9 +122,9 @@ export async function runRuntimeBundle(runtime, bundlePath, extraArgs = [], opti
141
122
  }
142
123
  const { env: nativeEnv, envPrefix } = computeNativeEnvForBundle(resolvedBundle, cwd);
143
124
  const env = { ...process.env, ...nativeEnv };
144
- // Reuse the shared RUNTIMES launch spec for the argv (deno's
145
- // `--node-modules-dir=manual`, etc.), substituting the resolved node binary
146
- // for the `node` runtime (under a GJS-hosted CLI `process.execPath` is gjs).
125
+ // The shared RUNTIMES launch spec supplies the argv (deno's `--node-modules-dir=manual`
126
+ // etc.); the `node` runtime substitutes the resolved binary, since under a GJS-hosted CLI
127
+ // `process.execPath` is gjs.
147
128
  const [, launchArgs] = RUNTIMES[runtime].launch(resolvedBundle, extraArgs);
148
129
  const cmd = runtime === 'node' ? nodeBinary() : RUNTIMES[runtime].probe;
149
130
  // Echo on stderr so a child speaking a protocol on stdout stays clean.
@@ -151,9 +132,9 @@ export async function runRuntimeBundle(runtime, bundlePath, extraArgs = [], opti
151
132
  if (!options.quiet)
152
133
  console.error(`$ ${envPrefix ? `${envPrefix} ` : ''}${shown}`);
153
134
  const child = spawn(cmd, launchArgs, { env, stdio: 'inherit' });
154
- // Re-raise the CHILD's own code rather than a blanket 1 — same reason as
155
- // `runGjsBundle`: a script run through `--node-script` reports its status
156
- // through this path, and a caller that reads `$?` needs the real one.
135
+ // Re-raise the CHILD's own code rather than a blanket 1 — a script run through
136
+ // `--node-script` reports its status through this path, and a caller reading `$?` needs
137
+ // the real one.
157
138
  let failed = false;
158
139
  let childCode = 1;
159
140
  await new Promise((resolvePromise, reject) => {
@@ -170,11 +151,9 @@ export async function runRuntimeBundle(runtime, bundlePath, extraArgs = [], opti
170
151
  console.error(err.message);
171
152
  failed = true;
172
153
  });
173
- // `return process.exit(…)`, and the flag rather than an exit inside the
174
- // `catch`: under GJS `process.exit()` is deferred and RETURNS, so a bare
175
- // call in the catch fell through to the `exitOnSuccess` line below and
176
- // scheduled a second exit — the same fall-through `runGjsBundle` and
177
- // `commands/run.ts` already carry this shape for.
154
+ // `return process.exit(…)`, and a flag rather than an exit inside the `catch`: under GJS
155
+ // `process.exit()` is deferred and RETURNS, so a bare call in the catch fell through to the
156
+ // `exitOnSuccess` line below and scheduled a second exit.
178
157
  if (failed) {
179
158
  process.exitCode = childCode;
180
159
  return process.exit(childCode);
@@ -16,10 +16,9 @@ export interface RuntimeSpec {
16
16
  readonly launch: (entry: string, extraArgs?: readonly string[]) => [string, string[]];
17
17
  }
18
18
  /**
19
- * The runtime map — the generalization of the node-gi harness's `RUNTIMES`.
20
19
  * `deno` uses `--node-modules-dir=manual`: `auto` would re-resolve the example's
21
- * heavy build-time dep tree (`@gjsify/cli` + platform binaries) and hang, when
22
- * the app only needs the already-linked runtime dep `@gjsify/node-gi`.
20
+ * heavy build-time dep tree (`@gjsify/cli` + platform binaries) and hang, when the
21
+ * app only needs the already-linked runtime dep `@gjsify/node-gi`.
23
22
  */
24
23
  export declare const RUNTIMES: Record<ExampleRuntime, RuntimeSpec>;
25
24
  /** Type guard: is `value` one of the four known runtimes? */
@@ -34,22 +33,18 @@ export declare function buildAppForRuntime(runtime: ExampleRuntime): 'gjs' | 'no
34
33
  * `--app gjs` bundle" and "needs a gjs interpreter" are the same fact, and a
35
34
  * hand-written second list drifts the first time a runtime is added.
36
35
  *
37
- * The caller must resolve the runtime BEFORE gating on it. `gjsify showcase`
38
- * called `runMinimalChecks()` — which marks `gjs` `required` — three statements
39
- * ABOVE the line resolving `args.runtime`, so `--runtime node` aborted with
40
- * "Missing system dependencies: ✗ GJS" before reaching the `runtime !== 'gjs'`
41
- * branch that never touches gjs. Every showcase was unreachable on a host
42
- * without gjs (Windows, plain Node/bun/deno) — including the default path,
43
- * since `defaultExampleRuntime()` falls back to the host runtime for exactly
44
- * those hosts.
36
+ * The caller must resolve the runtime BEFORE gating on it. Calling
37
+ * `runMinimalChecks()` (which marks `gjs` `required`) above the line that resolves
38
+ * `args.runtime` made every showcase unreachable on a host without gjs — `--runtime
39
+ * node` aborted with "Missing system dependencies: ✗ GJS" before reaching the
40
+ * branch that never touches gjs, the default path included.
45
41
  */
46
42
  export declare function requiresGjsSystemDeps(runtime: ExampleRuntime): boolean;
47
43
  /** Whether `<probe> --version` succeeds (i.e. the runtime binary is on PATH). */
48
44
  export declare function isRuntimeOnPath(probe: string): boolean;
49
45
  /**
50
- * Whether a specific runtime is runnable here. The HOST runtime (the one the
51
- * CLI itself executes in — gjs / node / bun / deno) is always available: we are
52
- * running on it, so no PATH probe is needed. Every other runtime is probed via
46
+ * Whether a specific runtime is runnable here. The HOST runtime needs no PATH probe
47
+ * — the CLI is executing on it; every other runtime is probed via
53
48
  * `<binary> --version`.
54
49
  */
55
50
  export declare function isRuntimeAvailable(runtime: ExampleRuntime): boolean;
@@ -59,20 +54,17 @@ export declare function availableRuntimes(): ExampleRuntime[];
59
54
  * The default `--runtime` for running a prebuilt EXAMPLE/SHOWCASE: `gjs`
60
55
  * whenever gjs is runnable here, else the host runtime.
61
56
  *
62
- * This is deliberately NOT a plain `hostRuntime()`. A showcase's canonical
63
- * artifact is its `--app gjs` bundle (`gjsify.main`) — that is what every
64
- * showcase ships, what the `gjs` path installs via `gjsify dlx`, and what the
65
- * docs call the default. Following the host instead means `npx @gjsify/cli
66
- * showcase <name>` (host = node) silently asks for the `--app node` bundle,
67
- * which most showcases do not ship and which additionally needs
68
- * `@gjsify/node-gi` in the consumer's project — so the FIRST-RUN experience of
69
- * the primary documented entry point failed on a missing file.
57
+ * Deliberately NOT a plain `hostRuntime()`. A showcase's canonical artifact is its
58
+ * `--app gjs` bundle (`gjsify.main`) — what every showcase ships and what `gjsify
59
+ * dlx` installs. Following the host instead makes `npx @gjsify/cli showcase <name>`
60
+ * (host = node) ask for the `--app node` bundle, which most showcases do not ship
61
+ * and which also needs `@gjsify/node-gi` in the consumer's project, so the
62
+ * first-run experience of the primary documented entry point failed on a missing
63
+ * file.
70
64
  *
71
- * Same rule `gjsify run` already applies in its bare-file path, where a
72
- * `--app gjs` bundle stays on gjs regardless of host (`isLikelyGjsBundle`);
73
- * here the "is it a gjs artifact" question is answered by the command instead
74
- * of by sniffing the file. `--runtime` still overrides explicitly, and a host
75
- * WITHOUT gjs (a plain Node/bun/deno box) keeps following the host so the
65
+ * Same rule `gjsify run` applies in its bare-file path (`isLikelyGjsBundle`), with
66
+ * "is it a gjs artifact" answered by the command rather than by sniffing the file.
67
+ * `--runtime` still overrides, and a host WITHOUT gjs keeps following the host so
76
68
  * node-capable showcases stay runnable there.
77
69
  */
78
70
  export declare function defaultExampleRuntime(): ExampleRuntime;
@@ -82,10 +74,9 @@ interface ExampleGjsifyField {
82
74
  };
83
75
  }
84
76
  /**
85
- * Read a package's declared example runtimes. Returns the (validated) list, or
86
- * `null` when the package declares none — the "unconstrained / permissive" case.
87
- * Unknown entries in the list are dropped (so a future runtime name doesn't hard
88
- * error against an older CLI).
77
+ * A package's declared example runtimes, or `null` when it declares none (the
78
+ * permissive case). Unknown entries are dropped so a future runtime name does not
79
+ * hard-error against an older CLI.
89
80
  */
90
81
  export declare function readDeclaredRuntimes(pkg: {
91
82
  gjsify?: ExampleGjsifyField;
@@ -96,10 +87,9 @@ export interface RuntimeSupportResult {
96
87
  message?: string;
97
88
  }
98
89
  /**
99
- * Validate a requested runtime against a package's declaration. A `null`
100
- * declaration is permissive (always ok). When the runtime is not in the
101
- * declared set, returns a clear, actionable error message (never throws) so
102
- * callers can print it and exit cleanly.
90
+ * Validate a requested runtime against a package's declaration; a `null`
91
+ * declaration is permissive. Returns a message rather than throwing, so callers
92
+ * print it and exit cleanly.
103
93
  */
104
94
  export declare function checkRuntimeSupported(runtime: ExampleRuntime, declared: ExampleRuntime[] | null, name: string): RuntimeSupportResult;
105
95
  export {};
@@ -1,27 +1,24 @@
1
1
  // Shared runtime-selector tooling for running gjsify examples/showcases across
2
2
  // the FOUR runtimes gjsify targets: gjs, node, bun, deno.
3
3
  //
4
- // This is the single source of truth generalized from the node-gi quad-runtime
5
- // example's `harness.mjs`. Both the CLI (`gjsify run`/`gjsify showcase
6
- // --runtime`) and the examples (the node-gi `harness.mjs`) consume it — so the
7
- // RUNTIMES map, the runtime→build-target mapping and `availableRuntimes()` live
8
- // in ONE place instead of a per-example copy.
4
+ // Both the CLI (`gjsify run` / `gjsify showcase --runtime`) and the examples (the
5
+ // node-gi `harness.mjs`) consume this, so the RUNTIMES map, the
6
+ // runtime→build-target mapping and `availableRuntimes()` live in ONE place instead
7
+ // of a per-example copy.
9
8
  //
10
- // The module is intentionally PURE (only `node:child_process` and the pure,
11
- // side-effect-free `@gjsify/rolldown-plugin-gjsify/runtime` host detector, no
12
- // `gi://` / native imports) so an external example can deep-import it from the
13
- // installed CLI (`@gjsify/cli/lib/utils/runtimes.js`) without pulling the whole
14
- // bundler in. Mirrors the existing `@gjsify/cli/lib/utils/run-gjs.js`
15
- // deep-import precedent used by the dlx e2e suites.
9
+ // Intentionally PURE (only `node:child_process` and the side-effect-free
10
+ // `@gjsify/rolldown-plugin-gjsify/runtime` host detector, no `gi://` or native
11
+ // imports) so an external example can deep-import it from the installed CLI
12
+ // (`@gjsify/cli/lib/utils/runtimes.js`) without pulling in the whole bundler — the
13
+ // same deep-import precedent as `@gjsify/cli/lib/utils/run-gjs.js`.
16
14
  import { execFileSync } from 'node:child_process';
17
15
  import { hostRuntime } from '@gjsify/rolldown-plugin-gjsify/runtime';
18
16
  /** All runtimes, in canonical order (gjs first — it is the reference). */
19
17
  export const EXAMPLE_RUNTIMES = ['gjs', 'node', 'bun', 'deno'];
20
18
  /**
21
- * The runtime map — the generalization of the node-gi harness's `RUNTIMES`.
22
19
  * `deno` uses `--node-modules-dir=manual`: `auto` would re-resolve the example's
23
- * heavy build-time dep tree (`@gjsify/cli` + platform binaries) and hang, when
24
- * the app only needs the already-linked runtime dep `@gjsify/node-gi`.
20
+ * heavy build-time dep tree (`@gjsify/cli` + platform binaries) and hang, when the
21
+ * app only needs the already-linked runtime dep `@gjsify/node-gi`.
25
22
  */
26
23
  export const RUNTIMES = {
27
24
  gjs: { probe: 'gjs', buildApp: 'gjs', launch: (e, a = []) => ['gjs', ['-m', e, ...a]] },
@@ -49,14 +46,11 @@ export function buildAppForRuntime(runtime) {
49
46
  * `--app gjs` bundle" and "needs a gjs interpreter" are the same fact, and a
50
47
  * hand-written second list drifts the first time a runtime is added.
51
48
  *
52
- * The caller must resolve the runtime BEFORE gating on it. `gjsify showcase`
53
- * called `runMinimalChecks()` — which marks `gjs` `required` — three statements
54
- * ABOVE the line resolving `args.runtime`, so `--runtime node` aborted with
55
- * "Missing system dependencies: ✗ GJS" before reaching the `runtime !== 'gjs'`
56
- * branch that never touches gjs. Every showcase was unreachable on a host
57
- * without gjs (Windows, plain Node/bun/deno) — including the default path,
58
- * since `defaultExampleRuntime()` falls back to the host runtime for exactly
59
- * those hosts.
49
+ * The caller must resolve the runtime BEFORE gating on it. Calling
50
+ * `runMinimalChecks()` (which marks `gjs` `required`) above the line that resolves
51
+ * `args.runtime` made every showcase unreachable on a host without gjs — `--runtime
52
+ * node` aborted with "Missing system dependencies: ✗ GJS" before reaching the
53
+ * branch that never touches gjs, the default path included.
60
54
  */
61
55
  export function requiresGjsSystemDeps(runtime) {
62
56
  return buildAppForRuntime(runtime) === 'gjs';
@@ -72,9 +66,8 @@ export function isRuntimeOnPath(probe) {
72
66
  }
73
67
  }
74
68
  /**
75
- * Whether a specific runtime is runnable here. The HOST runtime (the one the
76
- * CLI itself executes in — gjs / node / bun / deno) is always available: we are
77
- * running on it, so no PATH probe is needed. Every other runtime is probed via
69
+ * Whether a specific runtime is runnable here. The HOST runtime needs no PATH probe
70
+ * — the CLI is executing on it; every other runtime is probed via
78
71
  * `<binary> --version`.
79
72
  */
80
73
  export function isRuntimeAvailable(runtime) {
@@ -88,30 +81,26 @@ export function availableRuntimes() {
88
81
  * The default `--runtime` for running a prebuilt EXAMPLE/SHOWCASE: `gjs`
89
82
  * whenever gjs is runnable here, else the host runtime.
90
83
  *
91
- * This is deliberately NOT a plain `hostRuntime()`. A showcase's canonical
92
- * artifact is its `--app gjs` bundle (`gjsify.main`) — that is what every
93
- * showcase ships, what the `gjs` path installs via `gjsify dlx`, and what the
94
- * docs call the default. Following the host instead means `npx @gjsify/cli
95
- * showcase <name>` (host = node) silently asks for the `--app node` bundle,
96
- * which most showcases do not ship and which additionally needs
97
- * `@gjsify/node-gi` in the consumer's project — so the FIRST-RUN experience of
98
- * the primary documented entry point failed on a missing file.
84
+ * Deliberately NOT a plain `hostRuntime()`. A showcase's canonical artifact is its
85
+ * `--app gjs` bundle (`gjsify.main`) — what every showcase ships and what `gjsify
86
+ * dlx` installs. Following the host instead makes `npx @gjsify/cli showcase <name>`
87
+ * (host = node) ask for the `--app node` bundle, which most showcases do not ship
88
+ * and which also needs `@gjsify/node-gi` in the consumer's project, so the
89
+ * first-run experience of the primary documented entry point failed on a missing
90
+ * file.
99
91
  *
100
- * Same rule `gjsify run` already applies in its bare-file path, where a
101
- * `--app gjs` bundle stays on gjs regardless of host (`isLikelyGjsBundle`);
102
- * here the "is it a gjs artifact" question is answered by the command instead
103
- * of by sniffing the file. `--runtime` still overrides explicitly, and a host
104
- * WITHOUT gjs (a plain Node/bun/deno box) keeps following the host so the
92
+ * Same rule `gjsify run` applies in its bare-file path (`isLikelyGjsBundle`), with
93
+ * "is it a gjs artifact" answered by the command rather than by sniffing the file.
94
+ * `--runtime` still overrides, and a host WITHOUT gjs keeps following the host so
105
95
  * node-capable showcases stay runnable there.
106
96
  */
107
97
  export function defaultExampleRuntime() {
108
98
  return isRuntimeAvailable('gjs') ? 'gjs' : hostRuntime();
109
99
  }
110
100
  /**
111
- * Read a package's declared example runtimes. Returns the (validated) list, or
112
- * `null` when the package declares none — the "unconstrained / permissive" case.
113
- * Unknown entries in the list are dropped (so a future runtime name doesn't hard
114
- * error against an older CLI).
101
+ * A package's declared example runtimes, or `null` when it declares none (the
102
+ * permissive case). Unknown entries are dropped so a future runtime name does not
103
+ * hard-error against an older CLI.
115
104
  */
116
105
  export function readDeclaredRuntimes(pkg) {
117
106
  const list = pkg?.gjsify?.example?.runtimes;
@@ -120,10 +109,9 @@ export function readDeclaredRuntimes(pkg) {
120
109
  return list.filter((v) => typeof v === 'string' && isExampleRuntime(v));
121
110
  }
122
111
  /**
123
- * Validate a requested runtime against a package's declaration. A `null`
124
- * declaration is permissive (always ok). When the runtime is not in the
125
- * declared set, returns a clear, actionable error message (never throws) so
126
- * callers can print it and exit cleanly.
112
+ * Validate a requested runtime against a package's declaration; a `null`
113
+ * declaration is permissive. Returns a message rather than throwing, so callers
114
+ * print it and exit cleanly.
127
115
  */
128
116
  export function checkRuntimeSupported(runtime, declared, name) {
129
117
  if (declared === null)