@gjsify/resolve-npm 0.23.0 → 0.24.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.
- package/lib/index.mjs +136 -62
- package/package.json +1 -1
package/lib/index.mjs
CHANGED
|
@@ -19,25 +19,44 @@ import { getDerivedAliasesSync as _getDerivedAliasesSync } from './runtime-alias
|
|
|
19
19
|
*
|
|
20
20
|
* ## Why this exists (ADR 0014)
|
|
21
21
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
22
|
+
* A curated table maps a bare specifier (`os`, `node:os`) to `@gjsify/<X>`,
|
|
23
|
+
* while the derived per-runtimes-triplet map (`getDerivedAliasesSync`) maps
|
|
24
|
+
* `@gjsify/os` → `@gjsify/os/browser`. Applying the second to the values of
|
|
25
|
+
* the first is what makes ADR 0014's platform-entry routing reach a browser
|
|
26
|
+
* bundle at all: those bundles hit the packages through the bare/`node:` form,
|
|
27
|
+
* not by package name. (A direct `import … from '@gjsify/os'` routes on its own
|
|
28
|
+
* — it is a plain key hit in the merged map.)
|
|
26
29
|
*
|
|
27
|
-
*
|
|
28
|
-
* hit via `this.resolve(target, importer, { skipSelf: true })`, and `skipSelf`
|
|
29
|
-
* deliberately excludes the gjsify alias plugin from the nested resolution —
|
|
30
|
-
* so `os` → `@gjsify/os` lands on the package ROOT and the derived entry
|
|
31
|
-
* `@gjsify/os` → `@gjsify/os/browser` is never consulted. A direct
|
|
32
|
-
* `import … from '@gjsify/os'` in source DOES route (single hop, verified);
|
|
33
|
-
* a browser bundle importing bare `os` does not. Since every browser bundle
|
|
34
|
-
* reaches these packages through the bare/`node:` form, the platform-entry
|
|
35
|
-
* routing of ADR 0014 would have been inert without this.
|
|
30
|
+
* ## Why HERE and not as a second pass in `aliasPlugin`
|
|
36
31
|
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
32
|
+
* This looks like it wants to be a resolver chain — `os` → `@gjsify/os` →
|
|
33
|
+
* `@gjsify/os/browser` — but it must not be one. Slot routing may only be
|
|
34
|
+
* applied to values that CAME FROM a curated/derived table, and by the time
|
|
35
|
+
* `aliasPlugin` sees the map it has been merged flat across four tiers
|
|
36
|
+
* (derived → curated `ALIASES_*` → per-target overrides → user `--alias`,
|
|
37
|
+
* later wins — see `app/*.ts`). Tier information is gone, so a chain there
|
|
38
|
+
* would re-route USER aliases too:
|
|
39
|
+
*
|
|
40
|
+
* - `scripts/node-gi-consumer-harness.mjs` builds `--alias node:<x>=@gjsify/<x>`
|
|
41
|
+
* to put the POLYFILL under test behind a Node builtin. 34 of those
|
|
42
|
+
* polyfills declare `runtimes.node: "native"`, so a second hop hands back
|
|
43
|
+
* `@gjsify/<x>/globals` — Node's own builtin — and the suite measures
|
|
44
|
+
* nothing while reporting green.
|
|
45
|
+
* - Value-level chaining also has no notion of the documented KEY-level
|
|
46
|
+
* "curated wins over derived" precedence. Measured on the composed maps:
|
|
47
|
+
* `gjs` 0 of 114 entries would change, `node` 0 of 148 — and on
|
|
48
|
+
* `nativescript` the only 4 changes are regressions (`fs` →
|
|
49
|
+
* `@gjsify/native-fs-bridge` → `@gjsify/empty`, because a bridge package
|
|
50
|
+
* that IS the native implementation declares `nativescript: "native"`,
|
|
51
|
+
* which routes to a `globals.mjs` it does not ship).
|
|
52
|
+
*
|
|
53
|
+
* So composition happens at materialisation, where the tiers are still
|
|
54
|
+
* distinguishable, the curated table stays a pure bare-name → package
|
|
55
|
+
* statement (no slot policy duplicated into it), and `aliasPlugin` keeps its
|
|
56
|
+
* one-hop `skipSelf: true` contract. Composing a table is therefore an
|
|
57
|
+
* explicit, per-table decision; `ALIASES_NODE_FOR_NATIVESCRIPT` is
|
|
58
|
+
* deliberately NOT composed (see the STATUS.md TODO on the `native` slot's
|
|
59
|
+
* double meaning for the bridge packages).
|
|
41
60
|
*
|
|
42
61
|
* Evaluated LAZILY (on property read) and cached: `getDerivedAliasesSync` walks
|
|
43
62
|
* the workspace, and importing `@gjsify/resolve-npm` must not pay for a
|
|
@@ -249,45 +268,93 @@ export const ALIASES_NODE_FOR_GJS = {
|
|
|
249
268
|
* the routing in a second pass (`@gjsify/<X>` → `@gjsify/<X>/globals` or
|
|
250
269
|
* `@gjsify/empty` depending on the slot declaration).
|
|
251
270
|
*
|
|
252
|
-
* `none`-slot entries are deliberately hardcoded
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
*
|
|
271
|
+
* `none`-slot entries are deliberately hardcoded here rather than relying on the
|
|
272
|
+
* dynamic runtime layer — bare `fs` / `net` / ... do NOT start with `@gjsify/`
|
|
273
|
+
* and therefore never enter `getDerivedAliasesSync`. This table is the bridge.
|
|
274
|
+
*
|
|
275
|
+
* ## `@gjsify/empty` is a LAST resort, and every remaining one is classified
|
|
276
|
+
*
|
|
277
|
+
* A value of `@gjsify/empty` is an ANONYMOUS redirect: a shared
|
|
278
|
+
* `export default {}` that a dozen unrelated specifiers also resolve to. That
|
|
279
|
+
* makes it indistinguishable, in an emitted bundle, from an ACCIDENTAL alias —
|
|
280
|
+
* which is how `@gjsify/canvas2d`'s build could start emitting a stray
|
|
281
|
+
* `@gjsify/empty` import without anything noticing. It is also export-less, so
|
|
282
|
+
* `import { spawn } from 'child_process'` binds `undefined` and dies later at
|
|
283
|
+
* `spawn is not a function`, naming neither the module nor the platform.
|
|
284
|
+
*
|
|
285
|
+
* So a redirect is NAMED wherever a name exists, and each entry still pointing
|
|
286
|
+
* at `@gjsify/empty` carries an inline classification so the remaining work is
|
|
287
|
+
* visible rather than implied:
|
|
288
|
+
*
|
|
289
|
+
* (A) wireable now — the package declares a browser slot and ships the entry;
|
|
290
|
+
* the value names that entry. No `(A)` entries remain except
|
|
291
|
+
* `dns/promises`, which needs a `./browser/promises` subpath first.
|
|
292
|
+
* (A') native-available — the browser HAS the API (`fetch`, `WebSocket`); the
|
|
293
|
+
* honest target is a `/globals` re-export, not an empty module.
|
|
294
|
+
* (B) simulatable but unbuilt — a real Web analogue exists (`cluster` over
|
|
295
|
+
* Web Workers, `dgram` over WebRTC data channels, `v8.serialize` over
|
|
296
|
+
* `structuredClone`, `readline` over any stream). `@gjsify/empty` until
|
|
297
|
+
* someone builds it.
|
|
298
|
+
* (C) impossible — no Web API can ever back it. These get a NAMED throwing
|
|
299
|
+
* stub at `@gjsify/<X>/browser` (today: `child_process`, `net`, `tls`).
|
|
300
|
+
* `http2` / `inspector` are also `(C)` but not yet written; `repl` /
|
|
301
|
+
* `wasi` are `(C)` with no owning `@gjsify/*` package to host a stub.
|
|
302
|
+
*
|
|
303
|
+
* A `(C)` stub keeps its package's `runtimes.browser: "none"` declaration: the
|
|
304
|
+
* MODULE genuinely is not usable on the runtime. The stub does not make it
|
|
305
|
+
* usable, it makes the unusability legible — it exports the module's real named
|
|
306
|
+
* shape (so linking succeeds) and throws a structured `ENOTSUP` naming the
|
|
307
|
+
* module, the runtime and the calling site. Exports whose answer IS
|
|
308
|
+
* platform-independent (`net.isIP`, `tls.checkServerIdentity`) stay real; a
|
|
309
|
+
* blanket thrower would replace one lie with another.
|
|
256
310
|
*
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
311
|
+
* A `partial`-slot package names its `./browser` PLATFORM ENTRY here, not its
|
|
312
|
+
* package root. `withDerivedSlotRouting` only rewrites a value when the slot is
|
|
313
|
+
* `polyfill` (ADR 0014), so a curated value of `@gjsify/<X>` for a `partial`
|
|
314
|
+
* package would hand the bundler the GJS root body — whose `@girs/*` imports
|
|
315
|
+
* `gjsImportsEmptyPlugin` replaces with `{}`, producing the silent
|
|
316
|
+
* `GLib.Checksum is not a constructor` failure ADR 0014 exists to eliminate.
|
|
317
|
+
* `partial` must mean "degrades at call time", never "crashes at first use".
|
|
318
|
+
* Naming the subpath is safe precisely where the platform entry is already at
|
|
319
|
+
* VALUE-export parity with the root (else routing would trade a call-time
|
|
320
|
+
* degradation for a build-time MISSING_EXPORT) — which is why this is a
|
|
321
|
+
* per-package curated decision and NOT a blanket change to `resolveSlot`'s
|
|
322
|
+
* `partial` case. Machine-checked by `scripts/audit-runtimes.mjs`'
|
|
323
|
+
* `curated-alias-routing` invariant.
|
|
324
|
+
*
|
|
325
|
+
* WIRED. The browser-app orchestrator
|
|
326
|
+
* (`packages/infra/rolldown-plugin-gjsify/src/app/browser.ts`) spreads this map
|
|
327
|
+
* — plus a generated `node:*` prefix variant of every key — into its `aliasMap`
|
|
328
|
+
* between the derived slot routing and the per-target / user aliases. So every
|
|
329
|
+
* value here is a resolve target a `--app browser` build actually takes; a
|
|
330
|
+
* mistake in this table is a shipping bug, not a staged proposal. (The former
|
|
331
|
+
* "UNWIRED IN THIS PR" note dated from before that wiring landed and is what
|
|
332
|
+
* made the `crypto` / `zlib` root-body routing read as latent.)
|
|
266
333
|
*/
|
|
267
334
|
const ALIASES_NODE_FOR_BROWSER_TABLE = {
|
|
268
335
|
'assert': '@gjsify/assert',
|
|
269
336
|
'assert/strict': '@gjsify/assert/strict',
|
|
270
337
|
'async_hooks': '@gjsify/async_hooks',
|
|
271
338
|
'buffer': '@gjsify/buffer',
|
|
272
|
-
'child_process': '@gjsify/
|
|
273
|
-
'cluster': '@gjsify/empty',
|
|
339
|
+
'child_process': '@gjsify/child_process/browser', // none slot — NAMED throwing stub
|
|
340
|
+
'cluster': '@gjsify/empty', // (B) simulatable over Web Workers — unbuilt
|
|
274
341
|
'console': '@gjsify/console',
|
|
275
342
|
'constants': '@gjsify/constants',
|
|
276
|
-
'crypto': '@gjsify/crypto',
|
|
277
|
-
'dgram': '@gjsify/empty',
|
|
343
|
+
'crypto': '@gjsify/crypto/browser', // partial slot — name the platform entry
|
|
344
|
+
'dgram': '@gjsify/empty', // (B) simulatable over WebRTC data channels — unbuilt
|
|
278
345
|
'diagnostics_channel': '@gjsify/diagnostics_channel',
|
|
279
|
-
'dns': '@gjsify/
|
|
280
|
-
'dns/promises': '@gjsify/empty',
|
|
346
|
+
'dns': '@gjsify/dns/browser', // partial slot — name the platform entry
|
|
347
|
+
'dns/promises': '@gjsify/empty', // (A) blocked: no ./browser/promises subpath yet
|
|
281
348
|
'domain': '@gjsify/domain',
|
|
282
349
|
'events': '@gjsify/events',
|
|
283
|
-
'fs': '@gjsify/
|
|
284
|
-
'fs/promises': '@gjsify/
|
|
285
|
-
'http': '@gjsify/
|
|
286
|
-
'http2': '@gjsify/empty',
|
|
287
|
-
'https': '@gjsify/
|
|
288
|
-
'inspector': '@gjsify/empty',
|
|
289
|
-
'module': '@gjsify/
|
|
290
|
-
'net': '@gjsify/
|
|
350
|
+
'fs': '@gjsify/fs/browser', // partial slot — name the platform entry
|
|
351
|
+
'fs/promises': '@gjsify/fs/browser/promises',
|
|
352
|
+
'http': '@gjsify/http/browser', // partial slot — name the platform entry
|
|
353
|
+
'http2': '@gjsify/empty', // (C) impossible — needs a named throwing stub
|
|
354
|
+
'https': '@gjsify/https/browser', // partial slot — name the platform entry
|
|
355
|
+
'inspector': '@gjsify/empty', // (C) impossible — needs a named throwing stub
|
|
356
|
+
'module': '@gjsify/module/browser', // partial slot — name the platform entry
|
|
357
|
+
'net': '@gjsify/net/browser', // none slot — NAMED throwing stub
|
|
291
358
|
'os': '@gjsify/os',
|
|
292
359
|
'path': '@gjsify/path',
|
|
293
360
|
'path/posix': '@gjsify/path/posix',
|
|
@@ -296,9 +363,9 @@ const ALIASES_NODE_FOR_BROWSER_TABLE = {
|
|
|
296
363
|
'process': '@gjsify/process', // PR-D: flips today's `@gjsify/empty`
|
|
297
364
|
'punycode': '@gjsify/punycode',
|
|
298
365
|
'querystring': '@gjsify/querystring',
|
|
299
|
-
'readline': '@gjsify/empty',
|
|
300
|
-
'readline/promises': '@gjsify/empty',
|
|
301
|
-
'repl': '@gjsify/empty',
|
|
366
|
+
'readline': '@gjsify/empty', // (B) stream-generic; simulatable — unbuilt
|
|
367
|
+
'readline/promises': '@gjsify/empty', // (B) stream-generic; simulatable — unbuilt
|
|
368
|
+
'repl': '@gjsify/empty', // (C) impossible, and no @gjsify/repl package exists
|
|
302
369
|
'stream': '@gjsify/stream',
|
|
303
370
|
'stream/web': '@gjsify/stream/web',
|
|
304
371
|
'stream/consumers': '@gjsify/stream/consumers',
|
|
@@ -307,22 +374,22 @@ const ALIASES_NODE_FOR_BROWSER_TABLE = {
|
|
|
307
374
|
'sys': '@gjsify/sys',
|
|
308
375
|
'timers': '@gjsify/timers',
|
|
309
376
|
'timers/promises': '@gjsify/timers/promises',
|
|
310
|
-
'tls': '@gjsify/
|
|
311
|
-
'tty': '@gjsify/empty',
|
|
377
|
+
'tls': '@gjsify/tls/browser', // none slot — NAMED throwing stub
|
|
378
|
+
'tty': '@gjsify/empty', // (B) isatty()===false is honest — unbuilt
|
|
312
379
|
'url': '@gjsify/url',
|
|
313
380
|
'util': '@gjsify/util',
|
|
314
381
|
'util/types': '@gjsify/util/types',
|
|
315
|
-
'v8': '@gjsify/empty',
|
|
382
|
+
'v8': '@gjsify/empty', // (B) serialize/deserialize over structuredClone — unbuilt
|
|
316
383
|
'vm': '@gjsify/vm',
|
|
317
|
-
'wasi': '@gjsify/empty',
|
|
318
|
-
'sqlite': '@gjsify/
|
|
319
|
-
'worker_threads': '@gjsify/
|
|
320
|
-
'zlib': '@gjsify/zlib',
|
|
384
|
+
'wasi': '@gjsify/empty', // (C) impossible, and no @gjsify/wasi package exists
|
|
385
|
+
'sqlite': '@gjsify/sqlite/browser', // partial slot — name the platform entry
|
|
386
|
+
'worker_threads': '@gjsify/worker_threads/browser', // partial slot — name the platform entry
|
|
387
|
+
'zlib': '@gjsify/zlib/browser', // partial slot — name the platform entry
|
|
321
388
|
|
|
322
389
|
// Third-party
|
|
323
|
-
'node-fetch': '@gjsify/empty', //
|
|
324
|
-
'ws': '@gjsify/
|
|
325
|
-
'isomorphic-ws': '@gjsify/empty',
|
|
390
|
+
'node-fetch': '@gjsify/empty', // (A') native-available: wants @gjsify/fetch/globals
|
|
391
|
+
'ws': '@gjsify/ws/browser', // partial slot — name the platform entry
|
|
392
|
+
'isomorphic-ws': '@gjsify/empty', // (A') native-available: wants a WebSocket re-export
|
|
326
393
|
}
|
|
327
394
|
|
|
328
395
|
/**
|
|
@@ -351,11 +418,18 @@ export const ALIASES_NODE_FOR_BROWSER = withDerivedSlotRouting(
|
|
|
351
418
|
* - **Mobile-tractable Node built-ins → `@gjsify/<X>`.** `assert`,
|
|
352
419
|
* `async_hooks`, `buffer`, `crypto`, `events`, `fs`, `os`, `path`,
|
|
353
420
|
* `process`, `stream`, `string_decoder`, `url`, `util`, `querystring`
|
|
354
|
-
* route to their gjsify polyfills.
|
|
355
|
-
*
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
*
|
|
421
|
+
* route to their gjsify polyfills. NOTE: unlike `ALIASES_NODE_FOR_BROWSER`,
|
|
422
|
+
* this table is deliberately NOT wrapped in `withDerivedSlotRouting` — the
|
|
423
|
+
* VALUES here are taken as final. Composing it today would only change 4 of
|
|
424
|
+
* 122 entries and all four are regressions: `fs`/`fs/promises` point at
|
|
425
|
+
* `@gjsify/native-fs-bridge`, which declares `nativescript: "native"` meaning
|
|
426
|
+
* "this package IS the native implementation", while the slot vocabulary's
|
|
427
|
+
* `native` means "the RUNTIME provides it, route to `<pkg>/globals`" — a file
|
|
428
|
+
* the bridge does not ship, so the composed value degrades to
|
|
429
|
+
* `@gjsify/empty`. Settle the bridge packages' slot declarations first (see
|
|
430
|
+
* STATUS.md `Open TODOs`), then compose. An import by PACKAGE NAME does route
|
|
431
|
+
* per the declared slot (plain key hit in the merged map) — which is why the
|
|
432
|
+
* bridges are ALREADY emptied on that path today, same TODO.
|
|
359
433
|
* - **`ws` / `isomorphic-ws` → `@gjsify/empty`.** NS apps use `WebSocket`
|
|
360
434
|
* from the global runtime, not the `ws` package.
|
|
361
435
|
*
|