@gjsify/cli 0.38.0 → 0.38.1

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.
@@ -7,18 +7,19 @@ import { ensurePkgDir } from './dlx.js';
7
7
  import { fetchPackument } from '@gjsify/npm-registry';
8
8
  import { loadNpmrc } from '../utils/load-npmrc.js';
9
9
  import { parseSpec } from '../utils/parse-spec.js';
10
+ import { cliVersion } from '../utils/publish-headers.js';
10
11
  import { resolveNodeEntry } from '../utils/resolve-gjs-entry.js';
11
12
  import { runRuntimeBundle } from '../utils/run-node.js';
12
13
  import { EXAMPLE_RUNTIMES, isExampleRuntime, readDeclaredRuntimes, checkRuntimeSupported, defaultExampleRuntime, requiresGjsSystemDeps, } from '../utils/runtimes.js';
14
+ /**
15
+ * This CLI's own version, or `undefined` when it genuinely cannot be told.
16
+ *
17
+ * The shared resolver, never a local fixed-depth manifest read — that misses from
18
+ * `dist/`, unpinning `dlxSpec`. Incident: `docs/code-anti-patterns.md`.
19
+ */
13
20
  function readCliVersion() {
14
- try {
15
- const pkgUrl = new URL('../../package.json', import.meta.url);
16
- const pkg = JSON.parse(readFileSync(pkgUrl, 'utf8'));
17
- return typeof pkg.version === 'string' ? pkg.version : undefined;
18
- }
19
- catch {
20
- return undefined;
21
- }
21
+ const version = cliVersion();
22
+ return version === 'unknown' ? undefined : version;
22
23
  }
23
24
  /**
24
25
  * `[gjsify <version>] ` for the banner — the CLI naming ITSELF.
@@ -20,9 +20,70 @@
20
20
 
21
21
  import GLib from 'gi://GLib';
22
22
  import Gio from 'gi://Gio';
23
- import Soup from 'gi://Soup?version=3.0';
24
23
  import system, { exit } from 'system';
25
24
 
25
+ /**
26
+ * Soup, loaded late and — on a macOS that cannot find it — through one re-exec.
27
+ *
28
+ * WHY THIS IS NOT A PLAIN IMPORT. GI resolves a typelib's shared library with a
29
+ * bare-leaf `dlopen("libsoup-3.0.0.dylib")`. Homebrew installs that dylib in
30
+ * `/usr/local/lib` (Intel) or `/opt/homebrew/lib` (arm64), and `gjs` carries an
31
+ * rpath only for glib's own directory, so on a stock Homebrew macOS dyld never
32
+ * looks where the library actually is. Measured 2026-08-13 on macOS 15.7.9:
33
+ *
34
+ * $ curl -fsSL .../install.mjs -o /tmp/g.mjs && gjs -m /tmp/g.mjs
35
+ * Failed to load shared library 'libsoup-3.0.0.dylib' referenced by the typelib
36
+ * JS ERROR: Error: Unsupported type void, deriving from fundamental void
37
+ *
38
+ * That is the DOCUMENTED install path for a platform this project advertises,
39
+ * and it fails before the first byte is downloaded — the bootstrap's own fetcher
40
+ * is Soup. `DYLD_FALLBACK_LIBRARY_PATH=/usr/local/lib` fixes it, but nothing can
41
+ * export that on the user's behalf from inside this process: the variable is
42
+ * read by dyld at image load, long before any JS runs. Hence a re-exec.
43
+ *
44
+ * Repaired ONLY when the load actually fails, so a healthy host (arm64 Homebrew,
45
+ * a distro-packaged gjs, anything with a working rpath) re-execs never.
46
+ *
47
+ * Note the probe touches `Session` rather than just importing the namespace:
48
+ * `imports.gi.Soup` SUCCEEDS on a broken host — the library is resolved lazily,
49
+ * when a type is first needed. A namespace-only check reports a healthy
50
+ * environment and is the reason this looked like a network bug for so long.
51
+ */
52
+ const DYLD_REEXEC_MARKER = 'GJSIFY_INSTALL_DYLD_REEXEC';
53
+
54
+ /** dyld's documented default fallback list, plus both Homebrew prefixes. */
55
+ function dyldFallbackDirs() {
56
+ const home = GLib.get_home_dir();
57
+ return [`${home}/lib`, '/usr/local/lib', '/opt/homebrew/lib', '/lib', '/usr/lib'].join(':');
58
+ }
59
+
60
+ async function loadSoup() {
61
+ const mod = await import('gi://Soup?version=3.0');
62
+ void mod.default.Session; // forces the dlopen; see above
63
+ return mod.default;
64
+ }
65
+
66
+ let Soup;
67
+ try {
68
+ Soup = await loadSoup();
69
+ } catch (error) {
70
+ const onMacos = GLib.file_test('/usr/lib/dyld', GLib.FileTest.EXISTS);
71
+ if (!onMacos || GLib.getenv(DYLD_REEXEC_MARKER)) throw error;
72
+
73
+ const self = GLib.filename_from_uri(import.meta.url)[0];
74
+ const gjs = GLib.find_program_in_path('gjs');
75
+ if (!gjs) throw error;
76
+
77
+ // SIP strips an INHERITED DYLD_* when a protected binary is exec'd, but a
78
+ // value this process sets itself survives into Homebrew's unprotected `gjs`.
79
+ const launcher = new Gio.SubprocessLauncher({ flags: Gio.SubprocessFlags.NONE });
80
+ launcher.setenv('DYLD_FALLBACK_LIBRARY_PATH', dyldFallbackDirs(), true);
81
+ launcher.setenv(DYLD_REEXEC_MARKER, '1', true);
82
+ const child = launcher.spawnv([gjs, '-m', self, ...(system?.programArgs ?? [])]);
83
+ child.wait(null);
84
+ exit(child.get_exit_status() === 0 ? 0 : 1);
85
+ }
86
+
26
87
  Gio._promisify(Soup.Session.prototype, 'send_and_read_async');
27
88
  Gio._promisify(Gio.Subprocess.prototype, 'wait_check_async');
28
89
 
@@ -38,3 +38,4 @@ export interface PublishHeaderOptions {
38
38
  * and a wildcard here misses the create route.
39
39
  */
40
40
  export declare function buildPublishHeaders(url: string, opts: PublishHeaderOptions): Record<string, string>;
41
+ export declare function cliVersion(): string;
@@ -82,9 +82,14 @@ export function buildPublishHeaders(url, opts) {
82
82
  * `lib/`, `dist/` and an installed `node_modules/@gjsify/cli/**` alike.
83
83
  *
84
84
  * `GJSIFY_CLI_PACKAGE_JSON` overrides both, matching `self-update.ts`.
85
+ *
86
+ * Exported because `showcase` needs the SAME answer rather than a fourth
87
+ * resolver: it PINS the showcase package to this version, so a version it cannot
88
+ * read is a showcase left unpinned and `dlx` serves a stale cached one
89
+ * (`docs/code-anti-patterns.md`). Returns `'unknown'`, never `undefined`.
85
90
  */
86
91
  let cachedCliVersion;
87
- function cliVersion() {
92
+ export function cliVersion() {
88
93
  if (cachedCliVersion !== undefined)
89
94
  return cachedCliVersion;
90
95
  cachedCliVersion =
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/cli",
3
- "version": "0.38.0",
3
+ "version": "0.38.1",
4
4
  "description": "CLI for Gjsify",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -134,20 +134,20 @@
134
134
  "cli"
135
135
  ],
136
136
  "dependencies": {
137
- "@gjsify/buffer": "^0.38.0",
138
- "@gjsify/create-app": "^0.38.0",
139
- "@gjsify/node-globals": "^0.38.0",
140
- "@gjsify/node-polyfills": "^0.38.0",
141
- "@gjsify/npm-registry": "^0.38.0",
142
- "@gjsify/resolve-npm": "^0.38.0",
143
- "@gjsify/rolldown-plugin-gjsify": "^0.38.0",
144
- "@gjsify/vite-plugin-blueprint": "^0.38.0",
145
- "@gjsify/rolldown-plugin-pnp": "^0.38.0",
146
- "@gjsify/semver": "^0.38.0",
147
- "@gjsify/tar": "^0.38.0",
148
- "@gjsify/tsc": "^0.38.0",
149
- "@gjsify/web-polyfills": "^0.38.0",
150
- "@gjsify/workspace": "^0.38.0",
137
+ "@gjsify/buffer": "^0.38.1",
138
+ "@gjsify/create-app": "^0.38.1",
139
+ "@gjsify/node-globals": "^0.38.1",
140
+ "@gjsify/node-polyfills": "^0.38.1",
141
+ "@gjsify/npm-registry": "^0.38.1",
142
+ "@gjsify/resolve-npm": "^0.38.1",
143
+ "@gjsify/rolldown-plugin-gjsify": "^0.38.1",
144
+ "@gjsify/vite-plugin-blueprint": "^0.38.1",
145
+ "@gjsify/rolldown-plugin-pnp": "^0.38.1",
146
+ "@gjsify/semver": "^0.38.1",
147
+ "@gjsify/tar": "^0.38.1",
148
+ "@gjsify/tsc": "^0.38.1",
149
+ "@gjsify/web-polyfills": "^0.38.1",
150
+ "@gjsify/workspace": "^0.38.1",
151
151
  "cosmiconfig": "^9.0.2",
152
152
  "get-tsconfig": "^4.14.0",
153
153
  "pkg-types": "^2.3.1",
@@ -155,13 +155,13 @@
155
155
  "yargs": "^18.0.0"
156
156
  },
157
157
  "devDependencies": {
158
- "@gjsify/unit": "^0.38.0",
158
+ "@gjsify/unit": "^0.38.1",
159
159
  "@types/yargs": "^17.0.35",
160
160
  "typescript": "^6.0.3"
161
161
  },
162
162
  "peerDependencies": {
163
- "@gjsify/oxfmt-native": "^0.38.0",
164
- "@gjsify/rolldown-native": "^0.38.0"
163
+ "@gjsify/oxfmt-native": "^0.38.1",
164
+ "@gjsify/rolldown-native": "^0.38.1"
165
165
  },
166
166
  "peerDependenciesMeta": {
167
167
  "@gjsify/oxfmt-native": {