@gjsify/rolldown-plugin-gjsify 0.51.1 → 0.53.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 (44) hide show
  1. package/README.md +11 -0
  2. package/lib/app/browser.js +28 -0
  3. package/lib/app/gjs.js +14 -2
  4. package/lib/app/nativescript.js +15 -3
  5. package/lib/app/node.d.ts +1 -1
  6. package/lib/app/node.js +26 -10
  7. package/lib/index.d.ts +4 -2
  8. package/lib/index.js +4 -2
  9. package/lib/plugins/console-assign.d.ts +13 -0
  10. package/lib/plugins/console-assign.js +125 -0
  11. package/lib/plugins/css-as-string.js +126 -44
  12. package/lib/plugins/gi-renderer.d.ts +1 -1
  13. package/lib/plugins/gi-renderer.js +1 -1
  14. package/lib/plugins/gi-runtime-paths.js +5 -2
  15. package/lib/plugins/napi-node-addon.d.ts +48 -4
  16. package/lib/plugins/napi-node-addon.js +261 -85
  17. package/lib/plugins/node-native-external.d.ts +20 -0
  18. package/lib/plugins/node-native-external.js +145 -0
  19. package/lib/plugins/platform-resolve.d.ts +95 -5
  20. package/lib/plugins/platform-resolve.js +132 -11
  21. package/lib/plugins/rewrite-node-modules-paths.d.ts +18 -1
  22. package/lib/plugins/rewrite-node-modules-paths.js +181 -25
  23. package/lib/plugins/unresolved-workspace-import.js +89 -68
  24. package/lib/shims/addon-resolve.d.ts +19 -0
  25. package/lib/shims/addon-resolve.js +193 -0
  26. package/lib/utils/addon-platform.d.ts +23 -0
  27. package/lib/utils/addon-platform.js +50 -0
  28. package/lib/utils/auto-globals.d.ts +6 -0
  29. package/lib/utils/auto-globals.js +92 -15
  30. package/lib/utils/declare-build-input.d.ts +13 -0
  31. package/lib/utils/declare-build-input.js +37 -0
  32. package/lib/utils/detect-free-globals.d.ts +3 -0
  33. package/lib/utils/detect-free-globals.js +1 -1
  34. package/lib/utils/entry-wrapper.js +6 -1
  35. package/lib/utils/index.d.ts +1 -0
  36. package/lib/utils/index.js +1 -0
  37. package/lib/utils/inline-static-reads.d.ts +15 -1
  38. package/lib/utils/inline-static-reads.js +16 -8
  39. package/lib/utils/runtime.js +1 -1
  40. package/lib/utils/scan-globals.d.ts +2 -2
  41. package/lib/utils/scan-globals.js +20 -14
  42. package/lib/utils/zip-path.d.ts +9 -0
  43. package/lib/utils/zip-path.js +12 -0
  44. package/package.json +13 -9
@@ -17,7 +17,7 @@
17
17
  // `@import`s are resolved + inlined in JS first (`flattenCssImports`, so bare
18
18
  // node_modules specifiers work — the native `bundle()` FileProvider can't walk
19
19
  // node_modules), then the flattened CSS goes through the native `transform()`
20
- // for lowering. Both use the same `cssBundleResolver`. The `--app gjs`
20
+ // for lowering. Both use the same resolver. The `--app gjs`
21
21
  // orchestrator passes `targets: { firefox: 60 << 16 }` so nesting + modern
22
22
  // selectors get flattened to GTK4-CSS-engine-compatible output. Targeting is
23
23
  // opt-in — a missing `targets` keeps the source pristine.
@@ -43,7 +43,10 @@ import { createRequire } from 'node:module';
43
43
  import { dirname, isAbsolute, resolve as resolvePath } from 'node:path';
44
44
  import { pathToFileURL } from 'node:url';
45
45
  import { isGjs } from '../utils/runtime.js';
46
+ import { declareBuildInput } from '../utils/declare-build-input.js';
46
47
  let _bundlerPromise = null;
48
+ /** Why the native bridge's library would not open, when `tryLoadNativeBundler()` measured it. */
49
+ let _nativeLoadError = null;
47
50
  async function pickBundler() {
48
51
  const forced = globalThis.process?.env
49
52
  ?.GJSIFY_CSS_BACKEND;
@@ -52,11 +55,22 @@ async function pickBundler() {
52
55
  if (forced === 'native') {
53
56
  const native = await tryLoadNativeBundler();
54
57
  if (!native)
55
- throw new Error('GJSIFY_CSS_BACKEND=native but @gjsify/lightningcss-native is not loadable');
58
+ throw new Error('GJSIFY_CSS_BACKEND=native but @gjsify/lightningcss-native is not loadable' +
59
+ (_nativeLoadError ? `\n${_nativeLoadError.message}` : ''));
56
60
  return native;
57
61
  }
58
62
  const native = await tryLoadNativeBundler();
59
- return native ?? loadNpmBundler();
63
+ if (native)
64
+ return native;
65
+ // The npm fallback is the right answer, and it is silent on purpose — a
66
+ // missing optional backend is not an error. But if we MEASURED why the
67
+ // native one would not load, that measurement is the only place the user
68
+ // ever hears it, so it goes to the same `console.debug` channel
69
+ // `loadOptionalNativeModule` uses rather than into nothing. A backend that
70
+ // cannot load is the reason someone reaches for this flag.
71
+ if (_nativeLoadError)
72
+ console.debug(_nativeLoadError.message);
73
+ return loadNpmBundler();
60
74
  }
61
75
  async function tryLoadNativeBundler() {
62
76
  // The native bridge only exists under GJS — `imports.gi` marker. Skip
@@ -79,14 +93,42 @@ async function tryLoadNativeBundler() {
79
93
  const mod = (await import(/* @vite-ignore */ pathToFileURL(resolved).href));
80
94
  if (!mod.hasNativeLightningcss())
81
95
  return null;
82
- return async (filename, targets) => {
96
+ // The typelib resolved; its library opens at the first class access. Open
97
+ // it now, beside that typelib: this module cannot leave it to the wrapper,
98
+ // whose `lib/` is imported by file URL where GJS resolves no bare
99
+ // specifier. A library that will not load then names its missing
100
+ // dependency and the npm fallback runs, instead of the nameless
101
+ // "Unsupported type void" inside `transform()`.
102
+ // The same resolve-then-import dance as above, for the probe itself: by
103
+ // the time a CSS transform asks for the native bundler, utils' `lib/esm`
104
+ // is long built, so the lazy edge costs nothing and the static one would
105
+ // have cost a bootable CLI. `./native-library` rather than `./core`:
106
+ // `core` re-exports `main-loop`, whose module-level singleton would then
107
+ // exist twice in a process that already has it inlined in the GJS bundle.
108
+ //
109
+ // Its own `try` because the outer one cannot tell this apart from "there
110
+ // is no native backend" — and reporting nothing is the one outcome this
111
+ // file must not produce: a missing measurement reads as a passing one.
112
+ let openNativeLibrary;
113
+ try {
114
+ const utilsHref = pathToFileURL(createRequire(import.meta.url).resolve('@gjsify/utils/native-library')).href;
115
+ ({ openNativeLibrary } = (await import(/* @vite-ignore */ utilsHref)));
116
+ }
117
+ catch (err) {
118
+ _nativeLoadError = err instanceof Error ? err : new Error(String(err));
119
+ return null;
120
+ }
121
+ _nativeLoadError = openNativeLibrary('GjsifyLightningcss');
122
+ if (_nativeLoadError)
123
+ return null;
124
+ return async (filename, targets, declare) => {
83
125
  // The native `@gjsify/lightningcss-native` `bundle()` resolves
84
126
  // `@import` chains through lightningcss's filesystem-backed
85
127
  // FileProvider, which walks relative + absolute paths but NOT
86
128
  // bare node_modules specifiers (`@import "@scope/pkg/x.css"`) —
87
129
  // a JS resolver callback can't cross the GI/Rust boundary. So we
88
130
  // do `@import` resolution in JS first, using the SAME
89
- // `cssBundleResolver` the npm `bundleAsync` path uses (npm-package
131
+ // resolver the npm `bundleAsync` path uses (npm-package
90
132
  // + `exports`-map aware), and hand the fully-flattened CSS to the
91
133
  // native `transform()` for the GTK4 nesting/modern-syntax lowering
92
134
  // (`targets`). The native shim accepts a browserslist string; the
@@ -94,7 +136,7 @@ async function tryLoadNativeBundler() {
94
136
  // (`firefox: 60 << 16` etc), so convert per browser key.
95
137
  let flattened;
96
138
  try {
97
- flattened = await flattenCssImports(filename);
139
+ flattened = await flattenCssImports(filename, declare);
98
140
  }
99
141
  catch (err) {
100
142
  // The native rolldown engine flattens a thrown plugin error to
@@ -147,13 +189,16 @@ async function loadNpmBundler() {
147
189
  // `dependency` of this package, so the runtime resolve finds it.
148
190
  const specifier = 'lightningcss';
149
191
  const { bundleAsync } = (await import(/* @vite-ignore */ specifier));
150
- return async (filename, targets) => {
192
+ return async (filename, targets, declare) => {
151
193
  const result = await bundleAsync({
152
194
  filename,
153
195
  targets,
154
196
  minify: false,
155
197
  errorRecovery: true,
156
- resolver: cssBundleResolver,
198
+ // Per call, not a module singleton: the resolver is where every
199
+ // `@import` target is resolved, so it is where the declaration has
200
+ // to happen — and it must carry THIS load's sink.
201
+ resolver: createCssBundleResolver(declare),
157
202
  });
158
203
  return { code: result.code };
159
204
  };
@@ -185,35 +230,50 @@ const ASSET_REF_RE = /\.(woff2?|ttf|otf|eot|svg|png|jpe?g|gif|webp|avif|ico)(\?|
185
230
  function isAssetReference(specifier) {
186
231
  return /^(data|https?|file):/i.test(specifier) || ASSET_REF_RE.test(specifier);
187
232
  }
188
- const cssBundleResolver = {
189
- resolve(specifier, from) {
190
- if (isAbsolute(specifier))
191
- return specifier;
192
- if (specifier.startsWith('./') || specifier.startsWith('../')) {
193
- return resolvePath(dirname(from), specifier);
194
- }
195
- // Bare specifier — walk node_modules and honor package.json exports.
196
- // `createRequire` takes a file URL or path; passing the importer
197
- // lets it scope its node_modules walk to the right starting point.
198
- const req = createRequire(pathToFileURL(from).href);
199
- try {
200
- return req.resolve(specifier);
201
- }
202
- catch (err) {
203
- // Not an installed module. If it's a `url()`/asset reference,
204
- // leave it verbatim so lightningcss keeps the `@font-face` /
205
- // `url()` rule intact (the consumer serves the asset) instead of
206
- // crashing the build. A genuine unresolvable CSS `@import`
207
- // re-throws with actionable context so the missing dependency
208
- // surfaces clearly on both backends (npm and native).
209
- if (isAssetReference(specifier))
233
+ function createCssBundleResolver(declare) {
234
+ return {
235
+ resolve(specifier, from) {
236
+ // A relative `@import` is resolved here, but lightningcss reads the
237
+ // target itself — so the resolver is the only place its name is known.
238
+ if (isAbsolute(specifier)) {
239
+ declare(stripQuery(specifier));
210
240
  return specifier;
211
- throw new Error(`cannot resolve @import "${specifier}" from ${from} (${err.message}). ` +
212
- 'If it is a workspace/npm package, ensure it is installed and exposes the CSS ' +
213
- 'file via its package.json "exports".');
214
- }
215
- },
216
- };
241
+ }
242
+ if (specifier.startsWith('./') || specifier.startsWith('../')) {
243
+ const resolved = resolvePath(dirname(from), specifier);
244
+ declare(resolved);
245
+ return resolved;
246
+ }
247
+ // Bare specifier — walk node_modules and honor package.json exports.
248
+ // `createRequire` takes a file URL or path; passing the importer
249
+ // lets it scope its node_modules walk to the right starting point.
250
+ const req = createRequire(pathToFileURL(from).href);
251
+ try {
252
+ const resolved = req.resolve(specifier);
253
+ declare(resolved);
254
+ return resolved;
255
+ }
256
+ catch (err) {
257
+ // Not an installed module. If it's a `url()`/asset reference,
258
+ // leave it verbatim so lightningcss keeps the `@font-face` /
259
+ // `url()` rule intact (the consumer serves the asset) instead of
260
+ // crashing the build. A genuine unresolvable CSS `@import`
261
+ // re-throws with actionable context so the missing dependency
262
+ // surfaces clearly on both backends (npm and native).
263
+ if (isAssetReference(specifier))
264
+ return specifier;
265
+ throw new Error(`cannot resolve @import "${specifier}" from ${from} (${err.message}). ` +
266
+ 'If it is a workspace/npm package, ensure it is installed and exposes the CSS ' +
267
+ 'file via its package.json "exports".');
268
+ }
269
+ },
270
+ };
271
+ }
272
+ /** `@scope/pkg/x.css?v=2` is a cache-busting convention; the file is the part before it. */
273
+ function stripQuery(specifier) {
274
+ const cut = specifier.search(/[?#]/);
275
+ return cut === -1 ? specifier : specifier.slice(0, cut);
276
+ }
217
277
  // Matches a CSS `@import` at-rule and captures the specifier + any trailing
218
278
  // condition tokens (media query / `layer()` / `supports()`) before the `;`.
219
279
  // Covers `@import "x";`, `@import 'x';`, and `@import url("x")` / `url(x)`.
@@ -236,7 +296,7 @@ async function replaceAllAsync(source, re, fn) {
236
296
  }
237
297
  /**
238
298
  * Recursively resolve + inline every bundleable `@import` in `entry`, using the
239
- * same {@link cssBundleResolver} the npm `bundleAsync` path uses. Returns a
299
+ * same resolver the npm `bundleAsync` path uses. Returns a
240
300
  * single flattened CSS string with no bundleable `@import` statements left — the
241
301
  * native `transform()` then applies GTK4 nesting/target lowering.
242
302
  *
@@ -249,20 +309,26 @@ async function replaceAllAsync(source, re, fn) {
249
309
  * URL) are kept verbatim (the resolver leaves them alone), matching the npm
250
310
  * path. A cycle inlines each file at most once.
251
311
  */
252
- async function flattenCssImports(entry) {
312
+ async function flattenCssImports(entry, declare) {
253
313
  const seen = new Set();
314
+ const resolver = createCssBundleResolver(declare);
254
315
  const inline = async (file, isRoot) => {
255
- const abs = isAbsolute(file) ? file : resolvePath(file);
316
+ const abs = isAbsolute(file) ? stripQuery(file) : resolvePath(file);
256
317
  if (seen.has(abs))
257
318
  return ''; // @import cycle — inline once
258
319
  seen.add(abs);
320
+ // Declared at the READ, not at the resolution: the root stylesheet, and
321
+ // any import a form the regex does not match, are still inputs of the
322
+ // output — and a resolution declares nothing if lightningcss then
323
+ // decides not to read it.
324
+ declare(abs);
259
325
  let source = await readFile(abs, 'utf8');
260
326
  // `@charset` is only valid as the very first token of a stylesheet;
261
327
  // an inlined sub-file's `@charset` mid-stream would be invalid CSS.
262
328
  if (!isRoot)
263
329
  source = source.replace(/@charset[^;]*;/gi, '');
264
330
  return replaceAllAsync(source, IMPORT_RE, async (match, spec, condition) => {
265
- const resolved = cssBundleResolver.resolve(spec, abs);
331
+ const resolved = resolver.resolve(spec, abs);
266
332
  // Asset-reference `@import` (rare): resolver returns it verbatim —
267
333
  // keep the at-rule intact.
268
334
  if (resolved === spec)
@@ -310,13 +376,29 @@ export function cssAsStringPlugin(options = {}) {
310
376
  // flattens nesting, so no further lightningcss lowering is needed).
311
377
  filter: { id: /\.(css|s[ac]ss)$/ },
312
378
  async handler(id) {
379
+ // Every file the backends read on our behalf, declared through
380
+ // the standard contract — `gjsify test`'s freshness check reads
381
+ // this list, and it is the only account of a stylesheet's
382
+ // `@import`/`@use` chain, which no module graph names. Why the
383
+ // call is feature-detected: `utils/declare-build-input.ts`.
384
+ const declare = (abs) => declareBuildInput(this, abs);
385
+ // The entry itself is read here in every branch, and a Sass
386
+ // file's PARTIALS are not: dart-sass resolves a relative
387
+ // `@use "./x"` through its own filesystem importer before any
388
+ // custom importer is consulted (measured 2026-09-29 with
389
+ // dart-sass 1.101: `importers[].findFileUrl` and
390
+ // `canonicalize` are called zero times for a relative load, and
391
+ // for a bare one only on the way to being declined, so the path
392
+ // is never ours to declare). Tracking that:
393
+ // status/open-todos/bundler.md.
394
+ declare(stripQuery(id));
313
395
  let code;
314
396
  if (/\.s[ac]ss$/.test(id)) {
315
397
  code = await compileSass(id);
316
398
  }
317
399
  else {
318
400
  code = bundle
319
- ? new TextDecoder('utf-8').decode(await loadAndBundleCss(id, targets))
401
+ ? new TextDecoder('utf-8').decode(await loadAndBundleCss(id, targets, declare))
320
402
  : await readFile(id, 'utf8');
321
403
  }
322
404
  return {
@@ -339,7 +421,7 @@ async function compileSass(filename) {
339
421
  // `import './x.scss'` fails with UNLOADABLE_DEPENDENCY. Resolving it to a file
340
422
  // first (`tryLoadNativeBundler`'s trick) does not help: `sass.default.js` then
341
423
  // imports a bare `immutable`. Only INLINING dart-sass works, and 3.6 MB minified
342
- // onto a 6.6 MB CLI bundle is a carrier-package decision — status/open-todos.md
424
+ // onto a 6.6 MB CLI bundle is a carrier-package decision — status/open-todos/README.md
343
425
  // (#1053). dart-sass DOES run under GJS: `adwaita-web`'s `build:scss` does.
344
426
  _sassPromise = import(/* @vite-ignore */ 'sass');
345
427
  }
@@ -352,10 +434,10 @@ async function compileSass(filename) {
352
434
  `Is the \`sass\` package installed? (${err.message})`);
353
435
  }
354
436
  }
355
- async function loadAndBundleCss(filename, targets) {
437
+ async function loadAndBundleCss(filename, targets, declare) {
356
438
  if (!_bundlerPromise)
357
439
  _bundlerPromise = pickBundler();
358
440
  const bundler = await _bundlerPromise;
359
- const { code } = await bundler(filename, targets);
441
+ const { code } = await bundler(filename, targets, declare);
360
442
  return code;
361
443
  }
@@ -29,7 +29,7 @@ export interface GiRendererOptions {
29
29
  * passes `--gi-renderer`, so the arm never composes there and this text cannot reach them
30
30
  * — measured, nothing under `tests/` names the flag but `gi-renderer-arms` itself. Making
31
31
  * that suite's two assertions import-shaped would retire this rule outright; the argument,
32
- * the other twelve sites and the retirement condition are in `status/open-todos.md`.
32
+ * the other twelve sites and the retirement condition are in `status/open-todos/README.md`.
33
33
  */
34
34
  export declare function giRendererShimSource(options: GiRendererOptions, namespace: string, version: string): string;
35
35
  export declare function giRendererPlugin(options: GiRendererOptions): Plugin;
@@ -90,7 +90,7 @@ const GI_RENDERER_VIRTUAL_PREFIX = `${GJSIFY_VIRTUAL_PREFIX}gi-renderer:`;
90
90
  * passes `--gi-renderer`, so the arm never composes there and this text cannot reach them
91
91
  * — measured, nothing under `tests/` names the flag but `gi-renderer-arms` itself. Making
92
92
  * that suite's two assertions import-shaped would retire this rule outright; the argument,
93
- * the other twelve sites and the retirement condition are in `status/open-todos.md`.
93
+ * the other twelve sites and the retirement condition are in `status/open-todos/README.md`.
94
94
  */
95
95
  export function giRendererShimSource(options, namespace, version) {
96
96
  return (`import { ${namespace} as namespace } from ${JSON.stringify(options.renderer)};\n` +
@@ -9,8 +9,11 @@
9
9
  // e2e): a banner is the entry chunk's BODY and ESM evaluates imports first, so a
10
10
  // STATIC `import … from 'gi://Ns'` has already loaded its typelib before this runs.
11
11
  // What is left is what loads LATER — `await import('gi://Soup')` and the other
12
- // optional namespaces. Reaching the static ones changes how a bundle acquires GI
13
- // namespaces at all; that is an ADR, filed in the same entry.
12
+ // optional namespaces. Confirmed on darwin-arm64 in the same shape (macOS 27 / M4 /
13
+ // Homebrew, the bundle loading Gtk through `await import` and failing through a
14
+ // static one). Reaching the static ones changes how a bundle acquires GI namespaces
15
+ // at all: ADR 0085 decides to lower them here, in `renderChunk`, to awaited dynamic
16
+ // imports placed after this prologue — proposed, not implemented.
14
17
  //
15
18
  // TWO KINDS OF DIRECTORY, split by WHOSE FACT each is. `dirs` describe the SHIPPED
16
19
  // TREE, so they are baked, relative to the program. `systemProbes` describe the host
@@ -12,11 +12,49 @@ export interface NapiNodeAddonPluginOptions {
12
12
  * `@gjsify/napi` is not resolvable in the consumer graph. Default `true`.
13
13
  */
14
14
  warnOnMissingNapi?: boolean;
15
+ /**
16
+ * Is the output an ESM single-file build, i.e. does it carry the
17
+ * bundle-URL banner the run-time resolver anchors on? Default `true`;
18
+ * `app/gjs.ts` passes the same `format === 'esm'` the node-modules path
19
+ * rewriter gates its own runtime resolution on.
20
+ *
21
+ * `false` DECLINES every rewrite, with one warning naming the reason. It is
22
+ * a decline and not the pre-ADR baked path because there is no correct baked
23
+ * path left: the whole point of ADR 0084 is that a path chosen at build time
24
+ * is what made the artifact unusable off the build machine, so emitting one
25
+ * again would reintroduce the defect for a mode that cannot anchor at run
26
+ * time anyway. A `--library cjs` build is a library for a consumer's own
27
+ * toolchain, which resolves its addons itself.
28
+ */
29
+ runtimeResolve?: boolean;
15
30
  }
16
31
  /** A native addon package root has no resolvable compiled `.node`. */
17
32
  export declare class AddonNotBuiltError extends Error {
18
33
  constructor(pkgRoot: string);
19
34
  }
35
+ /**
36
+ * Enumerate every `.node` an addon package ships, keyed by platform, as a
37
+ * `<package>/<subpath>` spec per entry. ADR 0084: the build ENUMERATES, it
38
+ * does not select — the bundle picks the right entry at RUN time from the
39
+ * host it finds itself on.
40
+ *
41
+ * The table has:
42
+ * - One entry per `prebuilds/<tuple>/` directory, keyed by the tuple's
43
+ * platform and EVERY architecture it declares, and per libc variant. Each
44
+ * entry is chosen by {@link selectPrebuildFile} — node-gyp-build's own
45
+ * algorithm, run for a synthetic host of that tuple — so the entry for the
46
+ * build host is exactly the binary Node would load, and a foreign platform's
47
+ * entry is the best one that host could load rather than the best-looking
48
+ * file in the directory.
49
+ * - One entry per `build/Release` and `build/Debug`, keyed by the BUILD host
50
+ * ({@link buildHostTarget}, deliberately not the `npm_config_*` override
51
+ * those files are not built for), overriding the prebuilds entry for the
52
+ * same key: node-gyp-build's order has build/Release winning.
53
+ *
54
+ * Returns an empty record when no `.node` exists anywhere — the caller then
55
+ * throws {@link AddonNotBuiltError} as a build-time gate.
56
+ */
57
+ export declare function enumerateAddonTargets(pkgRoot: string, pkg: AddonPackageJson): Record<string, string>;
20
58
  /**
21
59
  * Locate the compiled `.node` for an addon package root, matching node-gyp-build's
22
60
  * probe order: `build/Release` → `build/Debug` →
@@ -28,14 +66,19 @@ export declare function resolveAddonPath(pkgRoot: string, opts?: {
28
66
  }): string;
29
67
  /** Nearest ancestor directory of `importerFile` holding a `package.json`. */
30
68
  export declare function nearestPackageRoot(importerFile: string): string | null;
69
+ /**
70
+ * The addon table as a JSON string — the platform-key → `<pkg>/<subpath>`
71
+ * map the runtime resolver (`__gjsifyAddonResolve`) picks from. ADR 0084.
72
+ */
73
+ type AddonTable = string;
31
74
  /** Direct `.node` import → the addon's exports (ESM default). */
32
- export declare function directNodeShim(addonPath: string): string;
75
+ export declare function directNodeShim(addonTable: AddonTable): string;
33
76
  /** `node-gyp-build` replacement — a callable `load(dir)` carrying `.path()`. */
34
- export declare function nodeGypBuildShim(addonPath: string): string;
77
+ export declare function nodeGypBuildShim(addonTable: AddonTable): string;
35
78
  /** `bindings` replacement — a callable `bindings(name)` returning the addon. */
36
- export declare function bindingsShim(addonPath: string): string;
79
+ export declare function bindingsShim(addonTable: AddonTable): string;
37
80
  /** napi-rs sibling → the raw native exports as the module value. */
38
- export declare function napiRsShim(addonPath: string): string;
81
+ export declare function napiRsShim(addonTable: AddonTable): string;
39
82
  /** Classify a specifier for interception — pure decision logic, no filesystem. */
40
83
  export declare function classifySpecifier(source: string): {
41
84
  kind: 'node-gyp-build' | 'bindings';
@@ -122,3 +165,4 @@ export declare function hostNapiRsTriple(): string | null;
122
165
  * else. Register ONLY for `--app gjs` — the C-ABI runs under `@gjsify/napi`.
123
166
  */
124
167
  export declare function napiNodeAddonPlugin(options?: NapiNodeAddonPluginOptions): Plugin;
168
+ export {};