@gjsify/rolldown-plugin-gjsify 0.64.16 → 0.64.17

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.
@@ -95,10 +95,26 @@ export const setupForNativescript = async (input) => {
95
95
  }
96
96
  // Legacy / per-target overrides — kept as a separate Record so future
97
97
  // mobile-specific shims (e.g. an NS-equivalent of `@gjsify/process`)
98
- // have an explicit landing pad. Today: empty. New entries SHOULD go
99
- // into `ALIASES_NODE_FOR_NATIVESCRIPT` so the same wiring is reachable
100
- // from the Vite-plugin track (`gjsifyNativescript()` preset) too.
101
- const nativescriptOverrideAliases = {};
98
+ // have an explicit landing pad. New entries SHOULD go into
99
+ // `ALIASES_NODE_FOR_NATIVESCRIPT` so the same wiring is reachable from
100
+ // the Vite-plugin track (`gjsifyNativescript()` preset) too — this
101
+ // record exists only for an entry whose ANSWER depends on the platform
102
+ // the curated table cannot see (`ALIASES_NODE_FOR_NATIVESCRIPT` is one
103
+ // flat map for the whole `nativescript` target).
104
+ //
105
+ // `gettext` is exactly that: the curated table points it at
106
+ // `@gjsify/node-gi/gettext`, correct on Android (ADR 0110 § 1's real
107
+ // engine) but not on iOS/visionOS — there is no node-gi payload there
108
+ // (`engine-target.ios.ts`), and `@gjsify/node-gi/index.js` loads
109
+ // `libnode_gi.so` at MODULE EVAL, not behind any call, so merely
110
+ // bundling the real answer crashes the app before anything of its own
111
+ // runs. An undetected platform gets the same safe default.
112
+ const nativescriptOverrideAliases = platform === 'android'
113
+ ? {}
114
+ : {
115
+ gettext: '@gjsify/native-platform/gettext-fallback',
116
+ 'node:gettext': '@gjsify/native-platform/gettext-fallback',
117
+ };
102
118
  // Derived `@gjsify/<X>` aliases driven by per-package `gjsify.runtimes`
103
119
  // triplet declarations. Merge order: derived (lowest priority) → curated
104
120
  // bare/`node:*` Node-builtin map → per-target overrides → user.
package/lib/index.d.ts CHANGED
@@ -13,7 +13,7 @@ export type { GiSystemProbe } from './plugins/gi-runtime-paths.js';
13
13
  export type { ProcessStubPluginOptions } from './plugins/process-stub.js';
14
14
  export { findImplicitGlobalAssignments, rewriteImplicitGlobalAssignments, implicitGlobalAssignPlugin, IMPLICIT_GLOBAL_ASSIGN_PLUGIN, } from './plugins/implicit-global-assign.js';
15
15
  export type { ImplicitGlobalAssignment } from './plugins/implicit-global-assign.js';
16
- export { workerUrlPlugin, findWorkerUrls, rewriteWorkerUrls, WorkerEntries, WORKER_URL_PLUGIN, } from './plugins/worker-url.js';
16
+ export { workerUrlPlugin, findWorkerUrls, rewriteWorkerUrls, WorkerEntries, bundleSuffix, WORKER_URL_PLUGIN, } from './plugins/worker-url.js';
17
17
  export type { WorkerUrlSite } from './plugins/worker-url.js';
18
18
  export { gschemaPlugin, parseGschema, GSCHEMA_PLUGIN, GSCHEMA_REGISTER } from './plugins/gschema.js';
19
19
  export type { GschemaOut, GschemaKey, GschemaPluginOptions } from './plugins/gschema.js';
@@ -39,7 +39,7 @@ export type { WorkspaceImportGuardOptions, WorkspaceImportGuardTarget, ImportVer
39
39
  export { napiNodeAddonPlugin, resolveAddonPath, enumerateAddonTargets, nearestPackageRoot, classifySpecifier, directNodeShim, nodeGypBuildShim, bindingsShim, napiRsShim, ADDON_FILTER_RE, isNapiRsPackageJson, isNapiRsSibling, isGjsifyNativeBridge, detectNapiRsEntry, hostNapiRsTriple, AddonNotBuiltError, } from './plugins/napi-node-addon.js';
40
40
  export type { NapiNodeAddonPluginOptions, AddonPackageJson } from './plugins/napi-node-addon.js';
41
41
  export { nodeNativeExternalPlugin, isNodeAddonPackage, packageNameOf } from './plugins/node-native-external.js';
42
- export { platformResolvePlugin, nativescriptSuffixChain, desktopSuffixChain, browserSuffixChain, desktopOsSuffix, DESKTOP_OS_SUFFIXES, DESKTOP_REFUSED_SUFFIXES, BROWSER_REFUSED_SUFFIXES, PlatformVariantExternalError, detectNativescriptPlatform, nativescriptPlatformDefines, } from './plugins/platform-resolve.js';
42
+ export { platformResolvePlugin, nativescriptSuffixChain, NATIVESCRIPT_PLATFORMS, desktopSuffixChain, browserSuffixChain, desktopOsSuffix, DESKTOP_OS_SUFFIXES, DESKTOP_REFUSED_SUFFIXES, BROWSER_REFUSED_SUFFIXES, PlatformVariantExternalError, detectNativescriptPlatform, nativescriptPlatformDefines, } from './plugins/platform-resolve.js';
43
43
  export type { PlatformResolvePluginOptions, NativescriptPlatform } from './plugins/platform-resolve.js';
44
44
  export { rnRouteManifestPlugin, renderRouteManifest, walkRoutes, RouteManifestError, RN_ROUTES_MODULE_ID, MAX_ROUTE_DEPTH, } from './plugins/rn-route-manifest.js';
45
45
  export type { RnRouteManifestOptions, FoundRoute } from './plugins/rn-route-manifest.js';
package/lib/index.js CHANGED
@@ -9,7 +9,7 @@ export { giRuntimePathsStub } from './plugins/gi-runtime-paths.js';
9
9
  export { giOptionalPlugin, giOptionalShimSource, giOptionalNodeShimSource, giOptionalMarkerSource, parseOptionalGiSpecifier, GI_OPTIONAL_FLAG, GI_OPTIONAL_MARKER, } from './plugins/gi-optional.js';
10
10
  export { bindConsoleLocally, consoleAssignPlugin, freeConsoleAssignmentInsertion, CONSOLE_LOCAL_BINDING, } from './plugins/console-assign.js';
11
11
  export { findImplicitGlobalAssignments, rewriteImplicitGlobalAssignments, implicitGlobalAssignPlugin, IMPLICIT_GLOBAL_ASSIGN_PLUGIN, } from './plugins/implicit-global-assign.js';
12
- export { workerUrlPlugin, findWorkerUrls, rewriteWorkerUrls, WorkerEntries, WORKER_URL_PLUGIN, } from './plugins/worker-url.js';
12
+ export { workerUrlPlugin, findWorkerUrls, rewriteWorkerUrls, WorkerEntries, bundleSuffix, WORKER_URL_PLUGIN, } from './plugins/worker-url.js';
13
13
  export { gschemaPlugin, parseGschema, GSCHEMA_PLUGIN, GSCHEMA_REGISTER } from './plugins/gschema.js';
14
14
  export { gresourcePlugin, compileGresource, prepareGresourceXml, gresourceModuleSource, GRESOURCE_PLUGIN, } from './plugins/gresource.js';
15
15
  export { cssAsStringPlugin } from './plugins/css-as-string.js';
@@ -24,7 +24,7 @@ export { externalsPlugin } from './plugins/externals.js';
24
24
  export { unresolvedWorkspaceImportPlugin, classifyImport, isWorkspaceSpecifier, formatUnresolvedWorkspaceImport, buildReverseAliasIndex, UnresolvedWorkspaceImportError, } from './plugins/unresolved-workspace-import.js';
25
25
  export { napiNodeAddonPlugin, resolveAddonPath, enumerateAddonTargets, nearestPackageRoot, classifySpecifier, directNodeShim, nodeGypBuildShim, bindingsShim, napiRsShim, ADDON_FILTER_RE, isNapiRsPackageJson, isNapiRsSibling, isGjsifyNativeBridge, detectNapiRsEntry, hostNapiRsTriple, AddonNotBuiltError, } from './plugins/napi-node-addon.js';
26
26
  export { nodeNativeExternalPlugin, isNodeAddonPackage, packageNameOf } from './plugins/node-native-external.js';
27
- export { platformResolvePlugin, nativescriptSuffixChain, desktopSuffixChain, browserSuffixChain, desktopOsSuffix, DESKTOP_OS_SUFFIXES, DESKTOP_REFUSED_SUFFIXES, BROWSER_REFUSED_SUFFIXES, PlatformVariantExternalError, detectNativescriptPlatform, nativescriptPlatformDefines, } from './plugins/platform-resolve.js';
27
+ export { platformResolvePlugin, nativescriptSuffixChain, NATIVESCRIPT_PLATFORMS, desktopSuffixChain, browserSuffixChain, desktopOsSuffix, DESKTOP_OS_SUFFIXES, DESKTOP_REFUSED_SUFFIXES, BROWSER_REFUSED_SUFFIXES, PlatformVariantExternalError, detectNativescriptPlatform, nativescriptPlatformDefines, } from './plugins/platform-resolve.js';
28
28
  export { rnRouteManifestPlugin, renderRouteManifest, walkRoutes, RouteManifestError, RN_ROUTES_MODULE_ID, MAX_ROUTE_DEPTH, } from './plugins/rn-route-manifest.js';
29
29
  export { reactNativeAliasPlugin, classifyReactNativeSpecifier, couldBeSurfaceSpecifier, loadLayer, FALLBACK_SURFACES, REACT_NATIVE_ALIAS_TARGET, REACT_NATIVE_SPECIFIER, ReactNativeDeepImportError, ReactNativeAliasTargetMissingError, SURFACE_MENTION, SURFACE_NAME_PREFIXES, } from './plugins/react-native-alias.js';
30
30
  export { reactNativeSupportGatePlugin, loadSupportTable, findSupportViolations, formatSupportViolations, formatOpaqueReference, formatUnreadableModule, SUPPORT_TABLE_SUBPATH, WATCHED_SPECIFIERS, watchedSpecifiers, ReactNativeUnsupportedImportError, SupportTableUnreadableError, } from './plugins/react-native-gate.js';
@@ -3,6 +3,11 @@ export declare const NATIVESCRIPT_GI_SELECTION_PLUGIN = "gjsify-nativescript-gi-
3
3
  export interface NativescriptGiSelectionOptions {
4
4
  /** `giNamespaces` as the app declares it, `Ns` or `Ns-Version`. */
5
5
  declared: readonly string[];
6
+ /**
7
+ * The app's dependency names. When given, a selection that needs an add-on package
8
+ * (ADR 0117 § 1) fails naming it; left out, only the namespace check runs.
9
+ */
10
+ installed?: readonly string[];
6
11
  }
7
12
  /**
8
13
  * Refuse a NativeScript bundle that imports a GI namespace the APK was not told to
@@ -28,7 +28,7 @@
28
28
  // The scan is a LOWER BOUND, so only one direction is fatal — the asymmetry
29
29
  // `gi-selection.ts` carries in full.
30
30
  import { scanGiNamespaces } from '../utils/gi-namespaces.js';
31
- import { assertGiNamespaceEntries, planGiSelection } from '../utils/gi-selection.js';
31
+ import { assertGiNamespaceEntries, planGiAddons, planGiSelection } from '../utils/gi-selection.js';
32
32
  export const NATIVESCRIPT_GI_SELECTION_PLUGIN = 'gjsify-nativescript-gi-selection';
33
33
  /**
34
34
  * Refuse a NativeScript bundle that imports a GI namespace the APK was not told to
@@ -64,6 +64,14 @@ export function nativescriptGiSelectionPlugin(options) {
64
64
  const files = [...new Set(origin.values())].sort().join(', ');
65
65
  throw new Error(`${NATIVESCRIPT_GI_SELECTION_PLUGIN}: ${error.message} (read from ${files})`);
66
66
  }
67
+ if (options.installed) {
68
+ try {
69
+ planGiAddons({ selected: selection.selected, installed: options.installed });
70
+ }
71
+ catch (error) {
72
+ throw new Error(`${NATIVESCRIPT_GI_SELECTION_PLUGIN}: ${error.message}`);
73
+ }
74
+ }
67
75
  for (const namespace of selection.unscanned) {
68
76
  this.warn(`${NATIVESCRIPT_GI_SELECTION_PLUGIN}: giNamespaces declares ${namespace}, which the bundle ` +
69
77
  'does not appear to import. The APK carries it anyway — drop it if nothing needs it, ' +
@@ -1,5 +1,6 @@
1
1
  import type { Plugin } from 'rolldown';
2
2
  export type NativescriptPlatform = 'android' | 'ios' | 'visionos';
3
+ export declare const NATIVESCRIPT_PLATFORMS: readonly NativescriptPlatform[];
3
4
  /**
4
5
  * The desktop suffix for one host OS, keyed by `process.platform`.
5
6
  *
@@ -36,12 +36,12 @@
36
36
  // gjsify Rolldown/Vite plugin pipeline.
37
37
  import { readdirSync } from 'node:fs';
38
38
  import { basename, dirname, resolve as resolvePath } from 'node:path';
39
- const PLATFORMS = ['android', 'ios', 'visionos'];
39
+ export const NATIVESCRIPT_PLATFORMS = ['android', 'ios', 'visionos'];
40
40
  // JS/TS extensions a source specifier may carry. Stripped so the platform
41
41
  // suffix lands BEFORE the extension (`./foo.js` → `./foo.android`).
42
42
  const KNOWN_EXT_RE = /\.(tsx?|jsx?|mts|cts|mjs|cjs)$/;
43
43
  function isPlatform(value) {
44
- return PLATFORMS.includes(value);
44
+ return NATIVESCRIPT_PLATFORMS.includes(value);
45
45
  }
46
46
  /**
47
47
  * The desktop suffix for one host OS, keyed by `process.platform`.
@@ -21,7 +21,10 @@ export declare function findWorkerUrls(code: string, id: string): WorkerUrlSite[
21
21
  export declare class WorkerEntries {
22
22
  #private;
23
23
  readonly extension: string;
24
- /** @param extension the main bundle's extension (`.js`, `.mjs`), mirrored so a worker loads like its parent. */
24
+ /**
25
+ * @param extension the main bundle's whole suffix (`.js`, `.mjs`, `.gjs.mjs`, see {@link bundleSuffix}),
26
+ * mirrored so a worker loads like its parent and a per-target build into one dir keeps its own file.
27
+ */
25
28
  constructor(extension?: string);
26
29
  /** The file name (no directory) the worker built from `source` gets beside the bundle. */
27
30
  register(source: string): string;
@@ -31,6 +34,12 @@ export declare class WorkerEntries {
31
34
  fileName: string;
32
35
  }[];
33
36
  }
37
+ /**
38
+ * Everything after the first dot of the main outfile's name: `app.gjs.mjs` → `.gjs.mjs`. An app
39
+ * that builds per target into one dir (`app.gjs.mjs`, `app.node.mjs`) would otherwise get one
40
+ * `w.worker.mjs` from both builds, the second overwriting the first.
41
+ */
42
+ export declare function bundleSuffix(outfile: string): string;
34
43
  /** `code` with each resolvable worker URL pointed at its emitted file, or null when nothing changed. */
35
44
  export declare function rewriteWorkerUrls(code: string, id: string, resolveSource: (specifier: string) => Promise<string | null>, entries: WorkerEntries): Promise<string | null>;
36
45
  /**
@@ -123,7 +123,10 @@ export class WorkerEntries {
123
123
  #names = new Map();
124
124
  #taken = new Set();
125
125
  #built = new Set();
126
- /** @param extension the main bundle's extension (`.js`, `.mjs`), mirrored so a worker loads like its parent. */
126
+ /**
127
+ * @param extension the main bundle's whole suffix (`.js`, `.mjs`, `.gjs.mjs`, see {@link bundleSuffix}),
128
+ * mirrored so a worker loads like its parent and a per-target build into one dir keeps its own file.
129
+ */
127
130
  constructor(extension = '.js') {
128
131
  this.extension = extension;
129
132
  }
@@ -153,6 +156,16 @@ export class WorkerEntries {
153
156
  return pending;
154
157
  }
155
158
  }
159
+ /**
160
+ * Everything after the first dot of the main outfile's name: `app.gjs.mjs` → `.gjs.mjs`. An app
161
+ * that builds per target into one dir (`app.gjs.mjs`, `app.node.mjs`) would otherwise get one
162
+ * `w.worker.mjs` from both builds, the second overwriting the first.
163
+ */
164
+ export function bundleSuffix(outfile) {
165
+ const name = basename(outfile).replace(/^\.+/, '');
166
+ const dot = name.indexOf('.');
167
+ return dot === -1 ? '.js' : name.slice(dot);
168
+ }
156
169
  /** FNV-1a over the path, base 36 — stable across builds and engines, no crypto dependency. */
157
170
  function pathHash(path) {
158
171
  let hash = 0x811c9dc5;
@@ -29,3 +29,29 @@ export declare function planGiSelection({ declared, scanned }: {
29
29
  declared: string[];
30
30
  scanned: string[];
31
31
  }): GiSelection;
32
+ /**
33
+ * The add-on packages that provide namespaces the core AAR does not carry (ADR 0117 § 1).
34
+ *
35
+ * A static table, not a read of installed manifests: the whole point is to name an add-on
36
+ * that is NOT installed. `packages/node-gi/node-gi/test/gi-runtime-android.test.mjs` holds
37
+ * it equal to each add-on's `gjsify.giRuntime.namespaces`, so it cannot drift.
38
+ */
39
+ export declare const GI_ADDONS: readonly {
40
+ package: string;
41
+ namespaces: readonly string[];
42
+ }[];
43
+ /**
44
+ * Refuse a selection whose namespaces an add-on provides, when that add-on is not a
45
+ * dependency of the app. Without it the APK carries no typelib for the namespace and the
46
+ * import throws on the device, naming a missing file rather than the package to install.
47
+ *
48
+ * A selection the core carries alone passes untouched, so today's apps change nothing.
49
+ *
50
+ * @param spec.selected {@link GiSelection.selected}
51
+ * @param spec.installed the app's dependency names
52
+ * @throws naming each missing add-on and the namespaces that need it
53
+ */
54
+ export declare function planGiAddons({ selected, installed, }: {
55
+ selected: readonly string[];
56
+ installed: readonly string[];
57
+ }): void;
@@ -92,3 +92,44 @@ export function planGiSelection({ declared, scanned }) {
92
92
  .sort();
93
93
  return { selected: [...byNamespace.values()].sort(), unscanned };
94
94
  }
95
+ /**
96
+ * The add-on packages that provide namespaces the core AAR does not carry (ADR 0117 § 1).
97
+ *
98
+ * A static table, not a read of installed manifests: the whole point is to name an add-on
99
+ * that is NOT installed. `packages/node-gi/node-gi/test/gi-runtime-android.test.mjs` holds
100
+ * it equal to each add-on's `gjsify.giRuntime.namespaces`, so it cannot drift.
101
+ */
102
+ export const GI_ADDONS = [
103
+ {
104
+ package: '@gjsify/gi-runtime-android-gtk',
105
+ namespaces: ['Adw', 'Gdk', 'GdkPixbuf', 'Graphene', 'Gsk', 'Gtk', 'HarfBuzz', 'Pango', 'PangoCairo'],
106
+ },
107
+ ];
108
+ /**
109
+ * Refuse a selection whose namespaces an add-on provides, when that add-on is not a
110
+ * dependency of the app. Without it the APK carries no typelib for the namespace and the
111
+ * import throws on the device, naming a missing file rather than the package to install.
112
+ *
113
+ * A selection the core carries alone passes untouched, so today's apps change nothing.
114
+ *
115
+ * @param spec.selected {@link GiSelection.selected}
116
+ * @param spec.installed the app's dependency names
117
+ * @throws naming each missing add-on and the namespaces that need it
118
+ */
119
+ export function planGiAddons({ selected, installed, }) {
120
+ const have = new Set(installed);
121
+ const wanted = new Set(selected.map(namespaceOf));
122
+ const problems = [];
123
+ for (const addon of GI_ADDONS) {
124
+ if (have.has(addon.package))
125
+ continue;
126
+ const needed = addon.namespaces.filter((ns) => wanted.has(ns));
127
+ if (needed.length > 0)
128
+ problems.push(`${needed.join(', ')} need ${addon.package}`);
129
+ }
130
+ if (problems.length > 0) {
131
+ throw new Error(`nativescript.giNamespaces selects namespaces the core GI runtime does not carry: ${problems.join('; ')}. ` +
132
+ "Add the package to the app's dependencies (next to @gjsify/gi-runtime-android, same version), " +
133
+ 'or drop the namespace.');
134
+ }
135
+ }
@@ -14,5 +14,5 @@ export { staticStringValue, walkModuleAst, importedSpecifier, moduleSpecifiers }
14
14
  export type { SpecifierNode, AstNode } from './module-ast.js';
15
15
  export { scanGiNamespaces, scanGiRequirements, giSpecifierKey } from './gi-namespaces.js';
16
16
  export type { GiRequirements } from './gi-namespaces.js';
17
- export { planGiSelection, assertGiNamespaceEntries } from './gi-selection.js';
17
+ export { planGiSelection, planGiAddons, assertGiNamespaceEntries, GI_ADDONS } from './gi-selection.js';
18
18
  export type { GiSelection } from './gi-selection.js';
@@ -11,4 +11,4 @@ export { locateSurvivingJsx, classifyJsxParseFailure, formatSurvivingJsx } from
11
11
  export { wrapInputWithSideEffects } from './entry-wrapper.js';
12
12
  export { staticStringValue, walkModuleAst, importedSpecifier, moduleSpecifiers } from './module-ast.js';
13
13
  export { scanGiNamespaces, scanGiRequirements, giSpecifierKey } from './gi-namespaces.js';
14
- export { planGiSelection, assertGiNamespaceEntries } from './gi-selection.js';
14
+ export { planGiSelection, planGiAddons, assertGiNamespaceEntries, GI_ADDONS } from './gi-selection.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/rolldown-plugin-gjsify",
3
- "version": "0.64.16",
3
+ "version": "0.64.17",
4
4
  "description": "Rolldown / Rollup / Vite plugin orchestrator for GJS, Node, and Browser targets",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -67,13 +67,13 @@
67
67
  ],
68
68
  "license": "MIT",
69
69
  "dependencies": {
70
- "@gjsify/console": "^0.64.16",
71
- "@gjsify/resolve-npm": "^0.64.16",
72
- "@gjsify/rolldown-plugin-deepkit": "^0.64.16",
73
- "@gjsify/rolldown-plugin-pnp": "^0.64.16",
74
- "@gjsify/utils": "^0.64.16",
75
- "@gjsify/vite-plugin-blueprint": "^0.64.16",
76
- "@gjsify/vite-plugin-gettext": "^0.64.16",
70
+ "@gjsify/console": "^0.64.17",
71
+ "@gjsify/resolve-npm": "^0.64.17",
72
+ "@gjsify/rolldown-plugin-deepkit": "^0.64.17",
73
+ "@gjsify/rolldown-plugin-pnp": "^0.64.17",
74
+ "@gjsify/utils": "^0.64.17",
75
+ "@gjsify/vite-plugin-blueprint": "^0.64.17",
76
+ "@gjsify/vite-plugin-gettext": "^0.64.17",
77
77
  "@rollup/pluginutils": "^5.4.0",
78
78
  "acorn": "^8.17.0",
79
79
  "acorn-typescript": "^1.4.13",
@@ -83,7 +83,7 @@
83
83
  "sass": "^1.101.0"
84
84
  },
85
85
  "peerDependencies": {
86
- "@gjsify/lightningcss-native": "^0.64.16",
86
+ "@gjsify/lightningcss-native": "^0.64.17",
87
87
  "rolldown": "^1.1.4"
88
88
  },
89
89
  "peerDependenciesMeta": {
@@ -95,8 +95,8 @@
95
95
  }
96
96
  },
97
97
  "devDependencies": {
98
- "@gjsify/cli": "^0.64.16",
99
- "@gjsify/unit": "^0.64.16",
98
+ "@gjsify/cli": "^0.64.17",
99
+ "@gjsify/unit": "^0.64.17",
100
100
  "@types/node": "^25.9.2",
101
101
  "rolldown": "^1.1.4",
102
102
  "typescript": "^6.0.3"