@gjsify/cli 0.13.1 → 0.13.2
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 +76 -71
- package/lib/actions/build.js +31 -1
- package/lib/commands/affected.js +8 -1
- package/lib/commands/install.js +6 -0
- package/lib/utils/install-backend-native.js +35 -2
- package/lib/utils/install-backend.d.ts +13 -0
- package/lib/utils/node-version.d.ts +21 -0
- package/lib/utils/node-version.js +56 -0
- package/package.json +18 -17
package/lib/actions/build.js
CHANGED
|
@@ -2,7 +2,7 @@ import { runBundle, runWatch, bundleToChunks } from '../bundler-pick.js';
|
|
|
2
2
|
import { gjsifyPlugin, textLoaderPlugin, resolveShebangLine, NODE_SHEBANG } from '@gjsify/rolldown-plugin-gjsify';
|
|
3
3
|
import { isGjs } from '@gjsify/rolldown-plugin-gjsify/runtime';
|
|
4
4
|
import { resolveUserPlugins } from '../utils/resolve-plugin-by-name.js';
|
|
5
|
-
import { resolveGlobalsList, writeRegisterInjectFile, detectAutoGlobals } from '@gjsify/rolldown-plugin-gjsify/globals';
|
|
5
|
+
import { resolveGlobalsList, writeRegisterInjectFile, detectAutoGlobals, detectNodeGiGlobals, } from '@gjsify/rolldown-plugin-gjsify/globals';
|
|
6
6
|
import { pnpPlugin } from '@gjsify/rolldown-plugin-pnp';
|
|
7
7
|
import { dirname, extname, join } from 'node:path';
|
|
8
8
|
import { pathToFileURL } from 'node:url';
|
|
@@ -402,6 +402,36 @@ export class BuildAction {
|
|
|
402
402
|
{ extraGlobalsList: extras, excludeGlobals, cwd: process.cwd() }, bundleToChunks);
|
|
403
403
|
pluginOpts.autoGlobalsInject = injectPath;
|
|
404
404
|
}
|
|
405
|
+
else if (app === 'node' && autoMode) {
|
|
406
|
+
// `--app node` reverse direction: detect GJS ambient globals
|
|
407
|
+
// (`print`/`imports`/…) in the bundled, tree-shaken output and
|
|
408
|
+
// inject `@gjsify/node-gi/globals` only when present. A single
|
|
409
|
+
// in-memory analysis pass (the shim is external — no convergence
|
|
410
|
+
// loop). Gated on `autoMode` so `--globals none` opts out. The
|
|
411
|
+
// detection must run BEFORE the final build so the entry can be
|
|
412
|
+
// wrapped; nothing is injected when no globals are referenced (the
|
|
413
|
+
// eager-native-load regression guard).
|
|
414
|
+
const gjsifyPluginFactory = async (opts) => {
|
|
415
|
+
const cfg = await gjsifyPlugin({
|
|
416
|
+
input: userBundler.input,
|
|
417
|
+
output: { file: outfile, dir: outdir },
|
|
418
|
+
userExternal,
|
|
419
|
+
userBanner,
|
|
420
|
+
userAliases: aliases,
|
|
421
|
+
shebang: this.configData.shebang,
|
|
422
|
+
}, opts);
|
|
423
|
+
return { options: cfg.options, plugins: cfg.plugins };
|
|
424
|
+
};
|
|
425
|
+
const needsGiGlobals = await detectNodeGiGlobals({
|
|
426
|
+
input: userBundler.input,
|
|
427
|
+
plugins: [...pnpPlugins, ...userPlugins],
|
|
428
|
+
external: userBundler.external,
|
|
429
|
+
transform: userBundler.transform,
|
|
430
|
+
format,
|
|
431
|
+
}, pluginOpts, gjsifyPluginFactory, bundleToChunks);
|
|
432
|
+
if (needsGiGlobals)
|
|
433
|
+
pluginOpts.nodeGiGlobalsInject = true;
|
|
434
|
+
}
|
|
405
435
|
else if (extras) {
|
|
406
436
|
pluginOpts.autoGlobalsInject = await this.resolveGlobalsInject(app, extras, verbose);
|
|
407
437
|
}
|
package/lib/commands/affected.js
CHANGED
|
@@ -119,8 +119,15 @@ const IGNORE = [
|
|
|
119
119
|
/^refs\//,
|
|
120
120
|
/^website\//,
|
|
121
121
|
/^docs\//,
|
|
122
|
-
/^\.github\/workflows\/(deploy-docs|commitlint|release|audit-runtimes|prebuilds)\.yml$/,
|
|
122
|
+
/^\.github\/workflows\/(deploy-docs|commitlint|release|audit-runtimes|prebuilds|node-gi)\.yml$/,
|
|
123
123
|
/^\.githooks\//,
|
|
124
|
+
// @gjsify/node-gi (the Node-native GObject-Introspection engine, Axis 5) is
|
|
125
|
+
// NOT a gjsify workspace member — the GJS-first install/foreach tooling can't
|
|
126
|
+
// build its node-gyp addon, so the main workflow neither builds nor tests it.
|
|
127
|
+
// Its own `.github/workflows/node-gi.yml` is the source of truth (built +
|
|
128
|
+
// tested on Node). Without this carve-out its files map to no workspace and
|
|
129
|
+
// land in `unmatched`, forcing a conservative full run on every node-gi PR.
|
|
130
|
+
/^packages\/node-gi\//,
|
|
124
131
|
// Flatpak build/distribution tooling (SDK-extension manifest + metainfo).
|
|
125
132
|
// Like `.githooks/`, it has no package-test consumers; its own
|
|
126
133
|
// `tests/e2e/flatpak-sdk-extension` runs on `tests/e2e/**` / global triggers.
|
package/lib/commands/install.js
CHANGED
|
@@ -619,6 +619,11 @@ async function workspaceInstall(cwd, args, signal) {
|
|
|
619
619
|
overrides,
|
|
620
620
|
signal,
|
|
621
621
|
progress,
|
|
622
|
+
// Workspace-named packages are symlinked above — the native backend
|
|
623
|
+
// must never fetch a same-named published version over those
|
|
624
|
+
// symlinks (e.g. a `types-dev/<lib>` workspace that also exists on
|
|
625
|
+
// npm and is pinned transitively in the lockfile).
|
|
626
|
+
workspaceNames: new Set(byName.keys()),
|
|
622
627
|
});
|
|
623
628
|
}
|
|
624
629
|
else if (args.verbose) {
|
|
@@ -644,6 +649,7 @@ async function workspaceInstall(cwd, args, signal) {
|
|
|
644
649
|
lockfile: !args.immutable,
|
|
645
650
|
frozen: args.immutable,
|
|
646
651
|
signal,
|
|
652
|
+
workspaceNames: new Set(byName.keys()),
|
|
647
653
|
});
|
|
648
654
|
}
|
|
649
655
|
// Re-wire workspace symlinks once more now that the external + scoped
|
|
@@ -21,6 +21,7 @@ import { DEFAULT_REGISTRY, fetchPackument, fetchPackumentConditional, fetchTarba
|
|
|
21
21
|
import { extractTarball } from '@gjsify/tar';
|
|
22
22
|
import { getCachedTarball, getForeignCachedTarball, putCachedTarball, } from './install-tarball-cache.js';
|
|
23
23
|
import { getCachedPackument, putCachedPackument } from './install-packument-cache.js';
|
|
24
|
+
import { assertNativeBackendNodeVersion } from './node-version.js';
|
|
24
25
|
// 16-wide download pool. Matched to the shared Soup.Session's lifted
|
|
25
26
|
// `max-conns-per-host` (see @gjsify/fetch `getSharedSession`) — a higher pool
|
|
26
27
|
// here only translates into real concurrency because that cap was raised from
|
|
@@ -30,6 +31,9 @@ const DEFAULT_CONCURRENCY = Number(process.env.GJSIFY_INSTALL_CONCURRENCY ?? '16
|
|
|
30
31
|
const LOCKFILE_NAME = 'gjsify-lock.json';
|
|
31
32
|
const LOCKFILE_VERSION = 2;
|
|
32
33
|
export async function installPackagesNative(opts) {
|
|
34
|
+
// Fail clearly on an unsupported Node major BEFORE touching the ABI-locked
|
|
35
|
+
// native deps — otherwise they SIGSEGV mid-extract with no actionable message.
|
|
36
|
+
assertNativeBackendNodeVersion();
|
|
33
37
|
if (opts.specs.length === 0) {
|
|
34
38
|
throw new Error('installPackagesNative: empty specs list');
|
|
35
39
|
}
|
|
@@ -72,12 +76,29 @@ export async function installPackagesNative(opts) {
|
|
|
72
76
|
// (and silently bumping transitive deps) on a one-package add.
|
|
73
77
|
const preferred = !opts.refreshLockfile && existingLock ? buildPreferredVersions(existingLock) : undefined;
|
|
74
78
|
log('install: resolving %d top-level spec(s) → %s%s', opts.specs.length, opts.prefix, preferred ? ` (preserving ${preferred.size} locked name(s))` : '');
|
|
75
|
-
nodes = await resolveDeps(opts.specs, npmrc, log, opts.overrides, opts.skipDeps, opts.signal, progress, preferred);
|
|
79
|
+
nodes = await resolveDeps(opts.specs, npmrc, log, opts.overrides, opts.skipDeps, opts.signal, progress, preferred, opts.workspaceNames);
|
|
76
80
|
if (opts.lockfile) {
|
|
77
81
|
writeLockfile(lockfilePath, opts.specs, nodes);
|
|
78
82
|
log('install: wrote %s (%d entries)', LOCKFILE_NAME, nodes.length);
|
|
79
83
|
}
|
|
80
84
|
}
|
|
85
|
+
// A package whose name is one of the monorepo's own workspaces is provided
|
|
86
|
+
// by a workspace symlink (wired by `workspaceInstall`), NOT by a registry
|
|
87
|
+
// tarball — even when the lockfile or a transitive edge pins a same-named
|
|
88
|
+
// published version. Drop those nodes from the fetch/extract set so
|
|
89
|
+
// `extractOne` never `rm`s + overwrites the workspace source symlink (its
|
|
90
|
+
// data-loss guard would otherwise abort the whole install). This keeps
|
|
91
|
+
// `--immutable` robust against a committed lockfile that still carries such
|
|
92
|
+
// registry entries (it is built from the lockfile verbatim and never runs
|
|
93
|
+
// `resolveDeps`); a fresh resolve additionally skips them at the source.
|
|
94
|
+
if (opts.workspaceNames && opts.workspaceNames.size > 0) {
|
|
95
|
+
const before = nodes.length;
|
|
96
|
+
nodes = nodes.filter((n) => !opts.workspaceNames.has(n.name));
|
|
97
|
+
const dropped = before - nodes.length;
|
|
98
|
+
if (dropped > 0) {
|
|
99
|
+
log('install: %d workspace-provided package(s) symlinked, not fetched', dropped);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
81
102
|
log('install: downloading %d tarball(s)', nodes.length);
|
|
82
103
|
await downloadAndExtractAll(nodes, opts.prefix, npmrc, log, opts.signal, progress);
|
|
83
104
|
await linkBins(nodes, opts.prefix, log);
|
|
@@ -143,7 +164,14 @@ async function resolveDeps(specs, npmrc, log, overrides, skipDeps, signal, progr
|
|
|
143
164
|
* Undefined ⇒ a fresh resolve that always picks the newest in-range version
|
|
144
165
|
* (first install, or an explicit `--refresh-lockfile`).
|
|
145
166
|
*/
|
|
146
|
-
preferredVersions
|
|
167
|
+
preferredVersions,
|
|
168
|
+
/**
|
|
169
|
+
* Names of the monorepo's own workspace packages. An edge whose name is in
|
|
170
|
+
* this set is satisfied by the workspace symlink, so it is skipped here —
|
|
171
|
+
* the published version (and its subtree) never enters the resolved tree or
|
|
172
|
+
* the lockfile.
|
|
173
|
+
*/
|
|
174
|
+
workspaceNames) {
|
|
147
175
|
progress?.beginPhase('resolve', specs.length);
|
|
148
176
|
const applyOverride = (name, range) => {
|
|
149
177
|
if (!overrides)
|
|
@@ -209,6 +237,11 @@ preferredVersions) {
|
|
|
209
237
|
// cache instead of blocking on a fresh round-trip.
|
|
210
238
|
for (let wi = 0; wi < wave.length; wi++) {
|
|
211
239
|
const edge = wave[wi];
|
|
240
|
+
// A workspace member is satisfied by its workspace symlink, never by
|
|
241
|
+
// a registry tarball — skip the edge so the published version (and
|
|
242
|
+
// its subtree) never enters the resolved tree or the lockfile.
|
|
243
|
+
if (workspaceNames?.has(edge.name))
|
|
244
|
+
continue;
|
|
212
245
|
// Walk the ancestor chain to see whether a satisfying placement is
|
|
213
246
|
// already visible from the requester's `node_modules` lookup. npm's
|
|
214
247
|
// resolver does this — each level of nesting acts as a fallback.
|
|
@@ -70,6 +70,19 @@ export interface InstallOptions {
|
|
|
70
70
|
* to override.
|
|
71
71
|
*/
|
|
72
72
|
progress?: ProgressReporter;
|
|
73
|
+
/**
|
|
74
|
+
* Native backend only: the names of the monorepo's own workspace packages.
|
|
75
|
+
* A package whose name is in this set is materialised as a symlink to its
|
|
76
|
+
* workspace source by `workspaceInstall`, never fetched from the registry —
|
|
77
|
+
* even when the lockfile or a transitive edge references a same-named
|
|
78
|
+
* published version (e.g. a `types-dev/<lib>` workspace that ALSO exists on
|
|
79
|
+
* npm). The native backend drops such names from `resolveDeps` AND from the
|
|
80
|
+
* fetch/extract set, so `extractOne` never tries to `rm` + overwrite a
|
|
81
|
+
* workspace source symlink (its data-loss guard would otherwise abort the
|
|
82
|
+
* whole install). The `npm` backend ignores this — npm resolves workspaces
|
|
83
|
+
* itself.
|
|
84
|
+
*/
|
|
85
|
+
workspaceNames?: Set<string>;
|
|
73
86
|
}
|
|
74
87
|
export interface InstallResult {
|
|
75
88
|
/** Top-level packages that were requested, with the version each
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimum Node.js major the native install backend supports — its prebuilt native
|
|
3
|
+
* modules are ABI-locked to this line (kept in sync with `.nvmrc`).
|
|
4
|
+
*/
|
|
5
|
+
export declare const MIN_NODE_MAJOR = 24;
|
|
6
|
+
/** Parse the major from a `process.versions.node`-style string (`'24.18.0'` → 24). */
|
|
7
|
+
export declare function parseNodeMajor(version: string): number;
|
|
8
|
+
/**
|
|
9
|
+
* The preflight verdict for the native install backend, factored out so it can be
|
|
10
|
+
* unit-tested without spawning a foreign Node. Returns an error message when the
|
|
11
|
+
* runtime is real Node older than {@link MIN_NODE_MAJOR}, else `null` — i.e. on a
|
|
12
|
+
* supported Node, on GJS (which fakes `process.versions.node` and does not use
|
|
13
|
+
* these prebuilds), or on a version string that does not parse.
|
|
14
|
+
*/
|
|
15
|
+
export declare function nativeBackendNodeError(version: string, onRealNode: boolean): string | null;
|
|
16
|
+
/**
|
|
17
|
+
* Guard the native install backend: throw a clear error on an unsupported Node
|
|
18
|
+
* major instead of letting the ABI-mismatched prebuilds SIGSEGV mid-install.
|
|
19
|
+
* No-op under GJS and on supported Node.
|
|
20
|
+
*/
|
|
21
|
+
export declare function assertNativeBackendNodeVersion(): void;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Node-version preflight for the native install backend.
|
|
3
|
+
//
|
|
4
|
+
// The native backend composes native deps whose prebuilt binaries are ABI-locked
|
|
5
|
+
// to the Node line gjsify targets (see `.nvmrc`). On an older Node major they load
|
|
6
|
+
// a mismatched ABI and SIGSEGV mid-install instead of failing cleanly — a
|
|
7
|
+
// confusing crash with no actionable message (observed: Node 22 in a Fedora
|
|
8
|
+
// container segfaults `gjsify install --backend native` during download/extract).
|
|
9
|
+
// This preflight turns that into a clear, actionable error.
|
|
10
|
+
import { isNode } from '@gjsify/rolldown-plugin-gjsify/runtime';
|
|
11
|
+
/**
|
|
12
|
+
* Minimum Node.js major the native install backend supports — its prebuilt native
|
|
13
|
+
* modules are ABI-locked to this line (kept in sync with `.nvmrc`).
|
|
14
|
+
*/
|
|
15
|
+
export const MIN_NODE_MAJOR = 24;
|
|
16
|
+
/** Parse the major from a `process.versions.node`-style string (`'24.18.0'` → 24). */
|
|
17
|
+
export function parseNodeMajor(version) {
|
|
18
|
+
return Number.parseInt(String(version).split('.', 1)[0] ?? '', 10);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The preflight verdict for the native install backend, factored out so it can be
|
|
22
|
+
* unit-tested without spawning a foreign Node. Returns an error message when the
|
|
23
|
+
* runtime is real Node older than {@link MIN_NODE_MAJOR}, else `null` — i.e. on a
|
|
24
|
+
* supported Node, on GJS (which fakes `process.versions.node` and does not use
|
|
25
|
+
* these prebuilds), or on a version string that does not parse.
|
|
26
|
+
*/
|
|
27
|
+
export function nativeBackendNodeError(version, onRealNode) {
|
|
28
|
+
if (!onRealNode)
|
|
29
|
+
return null;
|
|
30
|
+
const major = parseNodeMajor(version);
|
|
31
|
+
if (!Number.isFinite(major) || major >= MIN_NODE_MAJOR)
|
|
32
|
+
return null;
|
|
33
|
+
return (`gjsify install (native backend) requires Node ≥ ${MIN_NODE_MAJOR}, but this is Node ${version}. ` +
|
|
34
|
+
`Its prebuilt native modules are ABI-locked to Node ${MIN_NODE_MAJOR} and crash on older majors. ` +
|
|
35
|
+
`Use Node ${MIN_NODE_MAJOR} (nvm/asdf locally, actions/setup-node in CI), or run with --backend npm.`);
|
|
36
|
+
}
|
|
37
|
+
/** True when the CLI runs on real Node — NOT GJS, which fakes `process.versions.node`. */
|
|
38
|
+
function onRealNode() {
|
|
39
|
+
// GJS exposes `imports.system.version`; @gjsify/process fakes
|
|
40
|
+
// `process.versions.node = '20.0.0'` for compat, so check GJS FIRST — a plain
|
|
41
|
+
// `process.versions.node` read would be a false Node positive under GJS.
|
|
42
|
+
const sysVersion = globalThis.imports?.system?.version;
|
|
43
|
+
if (sysVersion !== undefined)
|
|
44
|
+
return false;
|
|
45
|
+
return isNode();
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Guard the native install backend: throw a clear error on an unsupported Node
|
|
49
|
+
* major instead of letting the ABI-mismatched prebuilds SIGSEGV mid-install.
|
|
50
|
+
* No-op under GJS and on supported Node.
|
|
51
|
+
*/
|
|
52
|
+
export function assertNativeBackendNodeVersion() {
|
|
53
|
+
const message = nativeBackendNodeError(process.versions.node, onRealNode());
|
|
54
|
+
if (message)
|
|
55
|
+
throw new Error(message);
|
|
56
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/cli",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.2",
|
|
4
4
|
"description": "CLI for Gjsify",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -108,6 +108,7 @@
|
|
|
108
108
|
"start": "node lib/index.js",
|
|
109
109
|
"build": "tsc && mkdir -p lib/templates/flatpak && cp -L src/templates/install.mjs.tmpl lib/templates/install.mjs.tmpl && cp src/templates/flatpak/*.tmpl lib/templates/flatpak/ && cp src/templates/oxlintrc.json.tmpl lib/templates/oxlintrc.json.tmpl && cp src/templates/oxfmtrc.tmpl lib/templates/oxfmtrc.tmpl && gjsify run chmod",
|
|
110
110
|
"build:gjs-bundle": "node lib/index.js build src/index.ts --app gjs --outfile dist/cli.gjs.mjs --shebang",
|
|
111
|
+
"build:affected-bundle": "node lib/index.js build src/affected-entry.ts --app gjs --outfile dist/affected.gjs.mjs",
|
|
111
112
|
"chmod": "chmod +x ./lib/index.js",
|
|
112
113
|
"build:test:node": "node lib/index.js build src/test.mts --app node --outfile dist/test.node.mjs",
|
|
113
114
|
"test:node": "node dist/test.node.mjs",
|
|
@@ -120,19 +121,19 @@
|
|
|
120
121
|
"cli"
|
|
121
122
|
],
|
|
122
123
|
"dependencies": {
|
|
123
|
-
"@gjsify/buffer": "^0.13.
|
|
124
|
-
"@gjsify/create-app": "^0.13.
|
|
125
|
-
"@gjsify/node-globals": "^0.13.
|
|
126
|
-
"@gjsify/node-polyfills": "^0.13.
|
|
127
|
-
"@gjsify/npm-registry": "^0.13.
|
|
128
|
-
"@gjsify/resolve-npm": "^0.13.
|
|
129
|
-
"@gjsify/rolldown-plugin-gjsify": "^0.13.
|
|
130
|
-
"@gjsify/rolldown-plugin-pnp": "^0.13.
|
|
131
|
-
"@gjsify/semver": "^0.13.
|
|
132
|
-
"@gjsify/tar": "^0.13.
|
|
133
|
-
"@gjsify/tsc": "^0.13.
|
|
134
|
-
"@gjsify/web-polyfills": "^0.13.
|
|
135
|
-
"@gjsify/workspace": "^0.13.
|
|
124
|
+
"@gjsify/buffer": "^0.13.2",
|
|
125
|
+
"@gjsify/create-app": "^0.13.2",
|
|
126
|
+
"@gjsify/node-globals": "^0.13.2",
|
|
127
|
+
"@gjsify/node-polyfills": "^0.13.2",
|
|
128
|
+
"@gjsify/npm-registry": "^0.13.2",
|
|
129
|
+
"@gjsify/resolve-npm": "^0.13.2",
|
|
130
|
+
"@gjsify/rolldown-plugin-gjsify": "^0.13.2",
|
|
131
|
+
"@gjsify/rolldown-plugin-pnp": "^0.13.2",
|
|
132
|
+
"@gjsify/semver": "^0.13.2",
|
|
133
|
+
"@gjsify/tar": "^0.13.2",
|
|
134
|
+
"@gjsify/tsc": "^0.13.2",
|
|
135
|
+
"@gjsify/web-polyfills": "^0.13.2",
|
|
136
|
+
"@gjsify/workspace": "^0.13.2",
|
|
136
137
|
"cosmiconfig": "^9.0.2",
|
|
137
138
|
"get-tsconfig": "^4.14.0",
|
|
138
139
|
"pkg-types": "^2.3.1",
|
|
@@ -140,13 +141,13 @@
|
|
|
140
141
|
"yargs": "^18.0.0"
|
|
141
142
|
},
|
|
142
143
|
"devDependencies": {
|
|
143
|
-
"@gjsify/unit": "^0.13.
|
|
144
|
+
"@gjsify/unit": "^0.13.2",
|
|
144
145
|
"@types/yargs": "^17.0.35",
|
|
145
146
|
"typescript": "^6.0.3"
|
|
146
147
|
},
|
|
147
148
|
"peerDependencies": {
|
|
148
|
-
"@gjsify/oxfmt-native": "^0.13.
|
|
149
|
-
"@gjsify/rolldown-native": "^0.13.
|
|
149
|
+
"@gjsify/oxfmt-native": "^0.13.2",
|
|
150
|
+
"@gjsify/rolldown-native": "^0.13.2"
|
|
150
151
|
},
|
|
151
152
|
"peerDependenciesMeta": {
|
|
152
153
|
"@gjsify/oxfmt-native": {
|