@gjsify/cli 0.36.0 → 0.38.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/dist/cli.gjs.mjs +169 -169
- package/lib/actions/build.d.ts +7 -0
- package/lib/actions/build.js +18 -3
- package/lib/bundler-pick.js +61 -87
- package/lib/cli-fail.d.ts +4 -7
- package/lib/cli-fail.js +29 -55
- package/lib/commands/affected.js +161 -286
- package/lib/commands/install.d.ts +63 -66
- package/lib/commands/install.js +372 -536
- package/lib/config.d.ts +14 -0
- package/lib/config.js +18 -1
- package/lib/templates/install.mjs.tmpl +164 -75
- package/lib/types/cli-build-options.d.ts +33 -67
- package/lib/types/command.d.ts +9 -12
- package/lib/types/config-data.d.ts +137 -221
- package/lib/utils/auth-npmrc.d.ts +5 -10
- package/lib/utils/auth-npmrc.js +11 -21
- package/lib/utils/bin-shim.d.ts +40 -25
- package/lib/utils/bin-shim.js +51 -26
- package/lib/utils/clear-targets.d.ts +8 -11
- package/lib/utils/clear-targets.js +22 -29
- package/lib/utils/copy-targets.d.ts +13 -19
- package/lib/utils/copy-targets.js +31 -44
- package/lib/utils/dep-aggregation.d.ts +7 -15
- package/lib/utils/dep-aggregation.js +9 -22
- package/lib/utils/detect-native-packages.d.ts +89 -122
- package/lib/utils/detect-native-packages.js +119 -169
- package/lib/utils/dir-link.d.ts +29 -48
- package/lib/utils/dir-link.js +33 -56
- package/lib/utils/discover-showcases.d.ts +6 -7
- package/lib/utils/discover-showcases.js +11 -15
- package/lib/utils/dlx-cache.d.ts +29 -38
- package/lib/utils/dlx-cache.js +53 -63
- package/lib/utils/force-exit.d.ts +0 -3
- package/lib/utils/force-exit.js +13 -24
- package/lib/utils/gi-search-path.d.ts +16 -24
- package/lib/utils/gi-search-path.js +54 -82
- package/lib/utils/gjs-bundle-guard.d.ts +5 -13
- package/lib/utils/gjs-bundle-guard.js +35 -57
- package/lib/utils/gjs-source-escape.d.ts +2 -2
- package/lib/utils/gjs-source-escape.js +21 -39
- package/lib/utils/gjsify-shim.d.ts +17 -20
- package/lib/utils/gjsify-shim.js +80 -120
- package/lib/utils/html-entry.d.ts +8 -12
- package/lib/utils/html-entry.js +19 -28
- package/lib/utils/install-backend-native.d.ts +123 -161
- package/lib/utils/install-backend-native.js +536 -737
- package/lib/utils/install-backend.d.ts +42 -57
- package/lib/utils/install-backend.js +16 -21
- package/lib/utils/install-cache-fs.d.ts +10 -15
- package/lib/utils/install-cache-fs.js +18 -26
- package/lib/utils/install-lock.d.ts +5 -6
- package/lib/utils/install-lock.js +46 -65
- package/lib/utils/install-packument-cache.d.ts +27 -33
- package/lib/utils/install-packument-cache.js +44 -57
- package/lib/utils/install-progress.d.ts +2 -9
- package/lib/utils/install-progress.js +14 -39
- package/lib/utils/install-tarball-cache.d.ts +14 -20
- package/lib/utils/install-tarball-cache.js +41 -59
- package/lib/utils/library-output.d.ts +9 -22
- package/lib/utils/library-output.js +19 -37
- package/lib/utils/load-npmrc.d.ts +5 -6
- package/lib/utils/load-npmrc.js +18 -27
- package/lib/utils/node-bundle-guard.d.ts +4 -8
- package/lib/utils/node-bundle-guard.js +21 -35
- package/lib/utils/node-script.js +40 -53
- package/lib/utils/node-version.d.ts +5 -14
- package/lib/utils/node-version.js +15 -24
- package/lib/utils/normalize-bundler-options.d.ts +7 -11
- package/lib/utils/normalize-bundler-options.js +24 -42
- package/lib/utils/npm-oidc.d.ts +23 -37
- package/lib/utils/npm-oidc.js +28 -53
- package/lib/utils/npm-otp-cache.d.ts +4 -4
- package/lib/utils/npm-otp-cache.js +20 -25
- package/lib/utils/npm-otp.d.ts +20 -30
- package/lib/utils/npm-otp.js +32 -51
- package/lib/utils/onboard-probe.d.ts +7 -13
- package/lib/utils/onboard-probe.js +16 -27
- package/lib/utils/parse-spec.d.ts +3 -3
- package/lib/utils/parse-spec.js +4 -5
- package/lib/utils/pkg-json-edit.d.ts +7 -12
- package/lib/utils/pkg-json-edit.js +13 -26
- package/lib/utils/pkg-json.d.ts +11 -18
- package/lib/utils/pkg-json.js +19 -28
- package/lib/utils/prefixed-output.d.ts +3 -4
- package/lib/utils/prefixed-output.js +13 -19
- package/lib/utils/prompt.d.ts +3 -4
- package/lib/utils/prompt.js +14 -18
- package/lib/utils/publish-diagnose.d.ts +11 -16
- package/lib/utils/publish-diagnose.js +15 -28
- package/lib/utils/publish-headers.d.ts +7 -11
- package/lib/utils/publish-headers.js +36 -65
- package/lib/utils/publishable-packages.d.ts +4 -6
- package/lib/utils/publishable-packages.js +14 -18
- package/lib/utils/resolve-gjs-entry.d.ts +5 -8
- package/lib/utils/resolve-gjs-entry.js +10 -27
- package/lib/utils/resolve-npm-package.d.ts +6 -11
- package/lib/utils/resolve-npm-package.js +29 -63
- package/lib/utils/resolve-plugin-by-name.d.ts +11 -19
- package/lib/utils/resolve-plugin-by-name.js +9 -14
- package/lib/utils/run-gjs.d.ts +16 -21
- package/lib/utils/run-gjs.js +31 -56
- package/lib/utils/run-lifecycle-script.d.ts +5 -9
- package/lib/utils/run-lifecycle-script.js +23 -42
- package/lib/utils/run-node.d.ts +21 -33
- package/lib/utils/run-node.js +43 -64
- package/lib/utils/runtimes.d.ts +25 -35
- package/lib/utils/runtimes.js +34 -46
- package/lib/utils/spawn.d.ts +32 -48
- package/lib/utils/spawn.js +51 -84
- package/lib/utils/stdin.d.ts +2 -2
- package/lib/utils/stdin.js +10 -25
- package/lib/utils/suggest.d.ts +6 -7
- package/lib/utils/suggest.js +8 -10
- package/lib/utils/system-gi.d.ts +36 -27
- package/lib/utils/system-gi.js +85 -114
- package/lib/utils/trust-registry.d.ts +4 -8
- package/lib/utils/trust-registry.js +7 -15
- package/lib/utils/win32-command.d.ts +8 -14
- package/lib/utils/win32-command.js +29 -43
- package/lib/utils/workspace-root.js +7 -12
- package/package.json +18 -18
package/lib/actions/build.d.ts
CHANGED
|
@@ -159,6 +159,13 @@ export declare class BuildAction {
|
|
|
159
159
|
* wrapper does not apply here.
|
|
160
160
|
*/
|
|
161
161
|
preserveDefaultExport?: boolean;
|
|
162
|
+
/**
|
|
163
|
+
* The globals policy for this bundle, when the caller has one
|
|
164
|
+
* (`Config.forNodeScript`). Unset keeps `--globals auto`, which is what
|
|
165
|
+
* the plugin and config loaders want.
|
|
166
|
+
*/
|
|
167
|
+
globals?: string;
|
|
168
|
+
excludeGlobals?: string[];
|
|
162
169
|
}): Promise<string>;
|
|
163
170
|
/** Application mode */
|
|
164
171
|
buildApp(app?: App, opts?: {
|
package/lib/actions/build.js
CHANGED
|
@@ -4,7 +4,7 @@ import { isGjs } from '@gjsify/rolldown-plugin-gjsify/runtime';
|
|
|
4
4
|
import { resolveUserPlugins } from '../utils/resolve-plugin-by-name.js';
|
|
5
5
|
import { resolveGlobalsList, writeRegisterInjectFile, detectAutoGlobals, detectNodeGiGlobals, } from '@gjsify/rolldown-plugin-gjsify/globals';
|
|
6
6
|
import { pnpPlugin } from '@gjsify/rolldown-plugin-pnp';
|
|
7
|
-
import { dirname, extname, join, resolve } from 'node:path';
|
|
7
|
+
import { basename, dirname, extname, join, resolve } from 'node:path';
|
|
8
8
|
import { pathToFileURL } from 'node:url';
|
|
9
9
|
import { chmod, mkdir, readdir, readFile, stat, writeFile } from 'node:fs/promises';
|
|
10
10
|
import { normalizeBundlerOptions, mergeBundlerOptions } from '../utils/normalize-bundler-options.js';
|
|
@@ -467,7 +467,20 @@ export class BuildAction {
|
|
|
467
467
|
const cwd = process.cwd();
|
|
468
468
|
const cacheDir = join(cwd, 'node_modules', '.cache', 'gjsify', opts.cacheSubdir);
|
|
469
469
|
const safeName = opts.label.replace(/[^a-zA-Z0-9._-]/g, '_');
|
|
470
|
-
|
|
470
|
+
// The policy belongs in the cache KEY, not only in the build: one file under two
|
|
471
|
+
// policies is two artifacts, and the freshness check below (entry mtime + lockfile)
|
|
472
|
+
// cannot see the `package.json` edit that changed one. Callers without a policy keep
|
|
473
|
+
// their existing cache filenames.
|
|
474
|
+
const cacheKey = opts.globals === undefined && opts.excludeGlobals === undefined
|
|
475
|
+
? inputPath
|
|
476
|
+
: `${inputPath} ${JSON.stringify([opts.globals ?? null, opts.excludeGlobals ?? null])}`;
|
|
477
|
+
// THE HASH GOES IN THE DIRECTORY, THE FILE KEEPS THE SOURCE'S NAME. As
|
|
478
|
+
// `<name>-<hash>.mjs` it broke every script guarding its body with the standard
|
|
479
|
+
// is-entry test: `audit-runtimes.mjs` asks whether `process.argv[1]` ENDS WITH its
|
|
480
|
+
// own name, so `--node-script` ran it, printed NOTHING and exited 0. Same cause the
|
|
481
|
+
// `import.meta.url` define exists for — the bundle does not live where the source
|
|
482
|
+
// does — and a name is cheaper to keep right than an argv to rewrite.
|
|
483
|
+
const outfile = join(cacheDir, `${safeName}-${shortHash(cacheKey)}`, `${basename(inputPath).replace(/\.[cm]?[jt]sx?$/i, '')}.mjs`);
|
|
471
484
|
const cacheDisabled = opts.cache === false || (opts.noCacheEnv ? isTruthyEnv(process.env[opts.noCacheEnv]) : false);
|
|
472
485
|
if (!cacheDisabled && (await isBundleFresh(outfile, inputPath, cwd))) {
|
|
473
486
|
if (opts.verbose)
|
|
@@ -476,9 +489,11 @@ export class BuildAction {
|
|
|
476
489
|
}
|
|
477
490
|
if (opts.verbose)
|
|
478
491
|
console.debug(`[gjsify] bundling ${inputPath} for GJS → ${outfile}`);
|
|
479
|
-
await mkdir(
|
|
492
|
+
await mkdir(dirname(outfile), { recursive: true });
|
|
480
493
|
await new BuildAction({
|
|
481
494
|
verbose: opts.verbose,
|
|
495
|
+
...(opts.globals !== undefined ? { globals: opts.globals } : {}),
|
|
496
|
+
...(opts.excludeGlobals !== undefined ? { excludeGlobals: opts.excludeGlobals } : {}),
|
|
482
497
|
bundler: {
|
|
483
498
|
input: inputPath,
|
|
484
499
|
output: { file: outfile },
|
package/lib/bundler-pick.js
CHANGED
|
@@ -1,65 +1,51 @@
|
|
|
1
|
-
// Runtime bundler pick (
|
|
1
|
+
// Runtime bundler pick. `shouldUseNative()` chooses per host runtime: Node gets
|
|
2
|
+
// npm `rolldown(opts).write(opts.output)`; GJS gets `@gjsify/rolldown-native` (the
|
|
3
|
+
// Vala/Rust prebuild) via `bundleWithPlugins()`, with `runNativeBundle` replicating
|
|
4
|
+
// npm rolldown's `.write()` including nested chunk/asset subdirectories. The native
|
|
5
|
+
// engine is the GJS DEFAULT with no env var, because npm `rolldown` is a Rust N-API
|
|
6
|
+
// addon that cannot load under GJS at all.
|
|
2
7
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// `bundleWithPlugins()`. npm `rolldown` is a Rust N-API addon
|
|
7
|
-
// that CANNOT load under GJS, so the native engine is the GJS
|
|
8
|
-
// DEFAULT — no env var needed (this is the Node-free build
|
|
9
|
-
// chain's bundler). This writes the BundleOutput to disk
|
|
10
|
-
// (`runNativeBundle`), replicating npm rolldown's `.write()`
|
|
11
|
-
// incl. nested chunk/asset subdirectories.
|
|
8
|
+
// `GJSIFY_BUNDLER=native|npm` overrides that: `native` throws when the prebuild is
|
|
9
|
+
// not loadable for the running architecture instead of silently switching engines;
|
|
10
|
+
// `npm` forces the npm crate (Node only).
|
|
12
11
|
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
12
|
+
// Plugin hooks arrive either as bare functions (`load(id)`) or as
|
|
13
|
+
// `{filter, handler}` objects; both are translated to `NativePlugin` form, with
|
|
14
|
+
// `filter.id` regex/string sources becoming `idFilter.<hook>` regex strings on the
|
|
15
|
+
// Rust side, and `this.resolve()` / `this.warn()` / `this.error()` routing through
|
|
16
|
+
// the nested protocol.
|
|
17
17
|
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
// Rust side. `this.resolve()` / `this.warn()` / `this.error()` calls
|
|
23
|
-
// inside hook handlers route through the B.3 nested protocol.
|
|
24
|
-
//
|
|
25
|
-
// Plugins that depend on rolldown context methods we don't implement
|
|
26
|
-
// (`this.parse`, `this.emitFile`, `this.getModuleInfo`, …) will fail
|
|
27
|
-
// at hook-call time. The current gjsify plugin set doesn't use any
|
|
28
|
-
// of those, so we don't gate on it; future incompatibilities surface
|
|
29
|
-
// as build errors rather than silent wrong behavior.
|
|
18
|
+
// Plugins using rolldown context methods this bridge does not implement
|
|
19
|
+
// (`this.parse`, `this.emitFile`, `this.getModuleInfo`, …) fail at hook-call time.
|
|
20
|
+
// Deliberately not gated: the current gjsify plugin set uses none of them, and a
|
|
21
|
+
// future incompatibility surfaces as a build error rather than silent wrong output.
|
|
30
22
|
import { promises as fs, existsSync } from 'node:fs';
|
|
31
23
|
import * as path from 'node:path';
|
|
32
24
|
import { createRequire } from 'node:module';
|
|
33
25
|
import { pathToFileURL } from 'node:url';
|
|
34
26
|
import { resolveNpmPackage } from './utils/resolve-npm-package.js';
|
|
35
|
-
// Static, not dynamic: `diagnoseNativeEngine()` is synchronous and
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
// bundle via `commands/install.ts`.
|
|
27
|
+
// Static, not dynamic: `diagnoseNativeEngine()` is synchronous and called inside a
|
|
28
|
+
// `throw` expression. Safe because check-system-deps imports only `node:` builtins,
|
|
29
|
+
// all of which the GJS bundle already carries via `commands/install.ts`.
|
|
39
30
|
import { buildInstallCommand, detectPackageManager, missingSystemDepsFor } from './utils/check-system-deps.js';
|
|
40
31
|
import { activateNativePrebuilds } from './utils/gi-search-path.js';
|
|
41
32
|
import { isGjs } from '@gjsify/rolldown-plugin-gjsify/runtime';
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
// where the createRequire polyfill rejects synchronous builtin loads.
|
|
46
|
-
// Dynamic import keeps it off the GJS code path entirely; the native
|
|
47
|
-
// branch (`@gjsify/rolldown-native`) handles bundling there.
|
|
33
|
+
// Loaded lazily: eager module-init loading of the npm crate pulls musl-detection
|
|
34
|
+
// code that calls `require('node:fs')` synchronously — fine on Node, fatal under
|
|
35
|
+
// GJS, where the createRequire polyfill rejects synchronous builtin loads.
|
|
48
36
|
async function loadNpmRolldown() {
|
|
49
|
-
// Under GJS the npm crate can NEVER run (its JS wrapper
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
// `@gjsify/rolldown-native`'s lib/ is not built yet, issue #497).
|
|
55
|
-
// Fail with the actionable diagnosis instead.
|
|
37
|
+
// Under GJS the npm crate can NEVER run (its JS wrapper needs a napi binary), so
|
|
38
|
+
// reaching this loader there means the native probe failed. That used to surface
|
|
39
|
+
// as an opaque `ImportError: Unsupported URI scheme for importing: node` from deep
|
|
40
|
+
// inside the crate's wrapper (#497, on a cold workspace where the native engine's
|
|
41
|
+
// lib/ was not built yet). Fail with the actionable diagnosis instead.
|
|
56
42
|
if (isGjs()) {
|
|
57
43
|
throw new Error('gjsify build: no usable bundler engine under GJS — `@gjsify/rolldown-native` is not loadable, ' +
|
|
58
44
|
'and the npm `rolldown` engine is a Rust napi crate that cannot run under GJS.\n' +
|
|
59
45
|
diagnoseNativeEngine());
|
|
60
46
|
}
|
|
61
|
-
// Indirect specifier so Rolldown's static
|
|
62
|
-
//
|
|
47
|
+
// Indirect specifier so Rolldown's static analysis does not try to bundle the npm
|
|
48
|
+
// crate into a GJS target build.
|
|
63
49
|
const specifier = 'rolldown';
|
|
64
50
|
const target = resolveImportTargetForGjs(specifier);
|
|
65
51
|
const mod = (await import(/* @vite-ignore */ target));
|
|
@@ -69,24 +55,19 @@ async function loadNpmRolldown() {
|
|
|
69
55
|
* Say WHY the native engine could not be loaded, read off disk rather than
|
|
70
56
|
* guessed.
|
|
71
57
|
*
|
|
72
|
-
* The causes need different fixes,
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* env-var problem that does not exist. `scripts/verify-committed-bundles.mjs`
|
|
79
|
-
* hit exactly that and it blocked releases. ADR 0021 then removed the bypassed
|
|
80
|
-
* launcher as a CAUSE outright, so it is no longer among the candidates at all.
|
|
58
|
+
* The causes need different fixes, so never name the rarest as "most likely": this
|
|
59
|
+
* message used to lead with a bypassed `gjsify` launcher, which on the by-far most
|
|
60
|
+
* common case — a fresh clone where the engine's JS facade has never been built —
|
|
61
|
+
* sent readers after an env-var problem that did not exist, and blocked releases via
|
|
62
|
+
* `scripts/verify-committed-bundles.mjs`. ADR 0021 has since removed the bypassed
|
|
63
|
+
* launcher as a cause outright.
|
|
81
64
|
*
|
|
82
65
|
* NOTHING here may throw or recurse into the failure being explained. Branches 1
|
|
83
|
-
* and 2 are `existsSync`-only
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
* property when editing: a probe that dies here replaces the diagnosis with its
|
|
89
|
-
* own stack.
|
|
66
|
+
* and 2 are `existsSync`-only. Branch 3 also asks `missingSystemDepsFor()` and reads
|
|
67
|
+
* the memoized `activateNativePrebuilds()` result — safe by construction rather than
|
|
68
|
+
* by a catch: the former routes every probe through `tryExecFile`, which returns
|
|
69
|
+
* null on any failure, and the latter is an array the failed load already computed.
|
|
70
|
+
* Keep that property: a probe that dies here replaces the diagnosis with its stack.
|
|
90
71
|
*/
|
|
91
72
|
function diagnoseNativeEngine() {
|
|
92
73
|
let pkgDir = null;
|
|
@@ -122,29 +103,23 @@ function diagnoseNativeEngine() {
|
|
|
122
103
|
'of failing. That is fixed in `@gjsify/module`, so a `gjsify` OLDER than the fix still stops here — ' +
|
|
123
104
|
'update it (`gjs -m install.mjs`), or seed `lib/` from the published package, which ships it.');
|
|
124
105
|
}
|
|
125
|
-
// Branch 3: installed AND built, so the typelib/prebuild LOOKUP failed.
|
|
126
|
-
//
|
|
127
|
-
//
|
|
128
|
-
//
|
|
129
|
-
//
|
|
130
|
-
//
|
|
131
|
-
// committed linux-x64 prebuild on a consumer-baseline host, a missing
|
|
132
|
-
// `libjson-glib-1.0.so.0` is at least as common, and it is what ts-for-gir#437
|
|
133
|
-
// actually hit — with this message on screen.
|
|
134
|
-
//
|
|
135
|
-
// So both candidates are now MEASURED, cheaply and without any call that can
|
|
136
|
-
// throw while explaining a failure, and the measured one is printed first.
|
|
106
|
+
// Branch 3: installed AND built, so the typelib/prebuild LOOKUP failed. Both
|
|
107
|
+
// remaining candidates are MEASURED, cheaply and without any call that can throw
|
|
108
|
+
// while explaining a failure, and the measured one prints first: #994 ran `ldd`
|
|
109
|
+
// over every committed linux-x64 prebuild on a consumer-baseline host and found a
|
|
110
|
+
// missing `libjson-glib-1.0.so.0` at least as common as the alternative — it is
|
|
111
|
+
// what ts-for-gir#437 hit, with this message on screen.
|
|
137
112
|
//
|
|
138
|
-
// ADR 0021 RETIRED
|
|
139
|
-
//
|
|
140
|
-
//
|
|
141
|
-
//
|
|
142
|
-
//
|
|
143
|
-
//
|
|
144
|
-
//
|
|
145
|
-
//
|
|
113
|
+
// ADR 0021 RETIRED A THIRD CANDIDATE: "the launcher was bypassed, export these
|
|
114
|
+
// two variables yourself" is no longer a cause at all, because `tryLoadNative()`
|
|
115
|
+
// calls `activateNativePrebuilds()` before the engine loads, putting every
|
|
116
|
+
// detected prebuild dir on girepository's typelib AND library search paths
|
|
117
|
+
// in-process. Do not reintroduce it — besides being false, the path it printed
|
|
118
|
+
// (`<facade>/prebuilds/<target>`) has been wrong since ADR 0017 moved every
|
|
119
|
+
// artifact into a per-target SIBLING package, so it named a directory that does
|
|
120
|
+
// not exist.
|
|
146
121
|
const parts = ['The JS facade is built, so this is the typelib/prebuild lookup failing.'];
|
|
147
|
-
// (1) A declared system library
|
|
122
|
+
// (1) A declared system library missing from this host. `missingSystemDepsFor`
|
|
148
123
|
// reads the same tables `gjsify system-check` does, so the answer cannot drift
|
|
149
124
|
// from the declaration.
|
|
150
125
|
const missing = missingSystemDepsFor('@gjsify/rolldown-native');
|
|
@@ -160,11 +135,10 @@ function diagnoseNativeEngine() {
|
|
|
160
135
|
else
|
|
161
136
|
parts.push(`Install ${names} with your system package manager (this host's manager was not recognised, so no command is suggested rather than a wrong one).`);
|
|
162
137
|
}
|
|
163
|
-
// (2)
|
|
164
|
-
//
|
|
165
|
-
//
|
|
166
|
-
//
|
|
167
|
-
// per-target sibling package that really holds the artifact.
|
|
138
|
+
// (2) No prebuild for this architecture — last because it is least actionable.
|
|
139
|
+
// Read off the set `activateNativePrebuilds()` ACTUALLY put on the search paths:
|
|
140
|
+
// a memoized cached-array read that cannot throw, and it names the per-target
|
|
141
|
+
// sibling package really holding the artifact.
|
|
168
142
|
if (missing.length === 0) {
|
|
169
143
|
const engine = activateNativePrebuilds().find((p) => p.name.startsWith('@gjsify/rolldown-native'));
|
|
170
144
|
parts.push(engine
|
package/lib/cli-fail.d.ts
CHANGED
|
@@ -11,12 +11,9 @@ export type CliFailure =
|
|
|
11
11
|
};
|
|
12
12
|
/**
|
|
13
13
|
* Classify a yargs `fail(msg, err)` callback into the two cases that need
|
|
14
|
-
* different output.
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* yargs-side half (which call site passes `null`) against a real instance, so a
|
|
19
|
-
* yargs upgrade that changes the routing fails a test instead of silently
|
|
20
|
-
* turning every runtime error back into a help dump.
|
|
14
|
+
* different output. Kept pure so the rule is testable without driving a process
|
|
15
|
+
* to its death; `cli-fail.spec.ts` pins the yargs-side half against a real
|
|
16
|
+
* instance, so a yargs upgrade that reroutes `fail` fails a test instead of
|
|
17
|
+
* silently turning every runtime error back into a help dump.
|
|
21
18
|
*/
|
|
22
19
|
export declare function classifyCliFailure(msg: string | null | undefined, _err: unknown): CliFailure;
|
package/lib/cli-fail.js
CHANGED
|
@@ -1,66 +1,40 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
// error (help is noise that buries the answer).
|
|
1
|
+
// The one place that decides whether a CLI failure is a USAGE error (help is the
|
|
2
|
+
// right output) or a RUNTIME error (help buries the answer).
|
|
4
3
|
//
|
|
5
|
-
//
|
|
6
|
-
// under GJS without `@gjsify/rolldown-native`
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
// and exits 1. In a CI log the actionable line scrolls out of view and the
|
|
10
|
-
// visible artifact is a help dump, which reads as "bad arguments". That is what
|
|
11
|
-
// ts-for-gir's `test-e2e` leg looked like (#1005). A missing engine is not a
|
|
12
|
-
// usage error and must not leave through the usage path.
|
|
4
|
+
// A missing native engine must not leave through the usage path: `gjsify build`
|
|
5
|
+
// under GJS without `@gjsify/rolldown-native` printed an actionable diagnosis
|
|
6
|
+
// naming the package and the install command, and then ~60 lines of yargs help on
|
|
7
|
+
// top of it, so the CI log read as "bad arguments" (#1005).
|
|
13
8
|
//
|
|
14
|
-
// Four
|
|
15
|
-
//
|
|
16
|
-
// one major behind, so the types lie in one place — see below):
|
|
9
|
+
// Four yargs behaviours shape this module, measured against the pinned yargs 18
|
|
10
|
+
// (`@types/yargs` is still 17, so the types understate `fail`):
|
|
17
11
|
//
|
|
18
|
-
// 1. `.fail()` IS reached for an async handler rejection
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
12
|
+
// 1. `.fail()` IS reached for an async handler rejection, because `cli-app.ts`
|
|
13
|
+
// calls `parseAsync()` with no callback. No try/catch around it is needed.
|
|
14
|
+
// 2. `msg` is the discriminator, NOT `err`: every usage/validation/parse site
|
|
15
|
+
// passes a string, and only the handler rejection passes `null`. Branching on
|
|
16
|
+
// `err` would suppress help for genuine parser errors — exactly backwards.
|
|
17
|
+
// 3. Registering a handler removes yargs' own `showHelp` + `exit(1)`, so the
|
|
18
|
+
// usage branch must terminate itself. `throw` rather than relying on
|
|
19
|
+
// `showHelp()` setting `hasOutput`, which only holds while the chain is
|
|
20
|
+
// synchronous and would break under a future async builder or middleware.
|
|
21
|
+
// 4. Never re-throw the incoming `YError` — yargs routes that class back into
|
|
22
|
+
// `usage.fail()` and prints help twice. Throw a plain `Error` with `cause`.
|
|
23
23
|
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
// Only `command.js:257` — the handler rejection — passes `null`. Branching on
|
|
29
|
-
// `err` instead would suppress help for genuine parser errors, which is
|
|
30
|
-
// exactly backwards.
|
|
31
|
-
//
|
|
32
|
-
// 3. REGISTERING A HANDLER REMOVES YARGS' OWN EXIT. With no `.fail()` yargs does
|
|
33
|
-
// `showHelp('error')` + `logger.error(msg || err)` + `exit(1)` itself
|
|
34
|
-
// (`usage.js:27-70`). With one, it does none of that — so the usage branch has
|
|
35
|
-
// to terminate on its own. `showHelp()` happens to set `hasOutput`
|
|
36
|
-
// (`yargs-factory.js:834`), which blocks the handler while the chain is still
|
|
37
|
-
// synchronous, but that is a side effect, not a guarantee: `throw` is what
|
|
38
|
-
// survives a future async builder or middleware.
|
|
39
|
-
//
|
|
40
|
-
// 4. NEVER RE-THROW THE INCOMING `YError`. `yargs-factory.js:1471-1475` routes
|
|
41
|
-
// that class back into `usage.fail()`, so re-throwing it prints the help a
|
|
42
|
-
// second time. The usage branch throws a plain `Error` with the original
|
|
43
|
-
// attached as `cause`.
|
|
44
|
-
//
|
|
45
|
-
// The runtime branch deliberately prints NOTHING and exits NOTHING: the rejection
|
|
46
|
-
// propagates out of `parseAsync()` on its own, and `index.ts` is the single
|
|
47
|
-
// printer (it also handles `GJSIFY_DEBUG` stacks and the GJS-side `gjsExit(1)`,
|
|
48
|
-
// which a second printer here would duplicate). Suppressing yargs'
|
|
49
|
-
// help-and-exit IS this branch's whole job — it only looks like a no-op.
|
|
24
|
+
// The runtime branch prints and exits NOTHING on purpose: the rejection
|
|
25
|
+
// propagates out of `parseAsync()` and `index.ts` is the single printer (it owns
|
|
26
|
+
// `GJSIFY_DEBUG` stacks and the GJS-side `gjsExit(1)`). Suppressing yargs'
|
|
27
|
+
// help-and-exit is this branch's whole job — it only looks like a no-op.
|
|
50
28
|
/**
|
|
51
29
|
* Classify a yargs `fail(msg, err)` callback into the two cases that need
|
|
52
|
-
* different output.
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* yargs-side half (which call site passes `null`) against a real instance, so a
|
|
57
|
-
* yargs upgrade that changes the routing fails a test instead of silently
|
|
58
|
-
* turning every runtime error back into a help dump.
|
|
30
|
+
* different output. Kept pure so the rule is testable without driving a process
|
|
31
|
+
* to its death; `cli-fail.spec.ts` pins the yargs-side half against a real
|
|
32
|
+
* instance, so a yargs upgrade that reroutes `fail` fails a test instead of
|
|
33
|
+
* silently turning every runtime error back into a help dump.
|
|
59
34
|
*/
|
|
60
35
|
export function classifyCliFailure(msg, _err) {
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
// nothing to print, and printing help with no reason is the worst of both.
|
|
36
|
+
// An empty string counts as "no message", not as an empty usage error: it has
|
|
37
|
+
// nothing to print, and help with no reason is the worst of both.
|
|
64
38
|
if (typeof msg === 'string' && msg.length > 0)
|
|
65
39
|
return { kind: 'usage', message: msg };
|
|
66
40
|
return { kind: 'runtime' };
|