@gjsify/rolldown-plugin-gjsify 0.23.0 → 0.24.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.
@@ -0,0 +1,318 @@
1
+ // Resolver-layer guard: an unresolvable `@gjsify/*` edge is a build ERROR,
2
+ // never a silent external.
3
+ //
4
+ // ## The failure this closes
5
+ //
6
+ // Rolldown (like Rollup) treats an import nothing resolves as EXTERNAL: it
7
+ // emits an `UNRESOLVED_IMPORT` **warning**, re-emits the ORIGINAL specifier
8
+ // into the output, and exits 0. For a normal bundler that is a reasonable
9
+ // default — the specifier might be provided by the host. For `gjsify build` it
10
+ // is not, because the `@gjsify/*` edge that failed is precisely the SUBSTITUTION
11
+ // that makes the bundle runnable on the target:
12
+ //
13
+ // import { readFileSync } from 'node:fs'
14
+ // → aliasPlugin rewrites to `@gjsify/fs`
15
+ // → `@gjsify/fs` cannot be resolved (no `node_modules`, or the workspace
16
+ // package has no built `lib/` so its `exports["."]` points at a file
17
+ // that does not exist)
18
+ // → aliasPlugin falls through, nothing else claims it
19
+ // → `node:fs` is externalised, the build "succeeds"
20
+ //
21
+ // Measured on `packages/infra/cli/dist/cli.gjs.mjs` (repo task #63): 1 bare
22
+ // `node:` import on `origin/main` vs 11 from a worktree with no `node_modules`
23
+ // — a bundle stock GJS aborts on before one line runs
24
+ // (`ImportError: Unsupported URI scheme for importing: node`). The pre-commit
25
+ // hook then rebuilt and AUTO-STAGED it, and nothing local objected: tsc, lint,
26
+ // format, unit and e2e all run the Node entry, never the emitted GJS bundle.
27
+ //
28
+ // ## Why this is upstream of the `--app gjs` `node:` guard (PR #828)
29
+ //
30
+ // `utils/gjs-bundle-guard.ts` reads the finished module graph and refuses to
31
+ // EMIT a `--app gjs` bundle that still statically imports a bare `node:`
32
+ // specifier. That is the right last line of defence, and it stays. But it is:
33
+ //
34
+ // - **gjs-only** — the same silent externalisation happens on `--app node`
35
+ // and `--app browser`, where a surviving bare `@gjsify/foo` is equally
36
+ // unloadable and no `node:`-shaped symptom exists to detect;
37
+ // - **symptom-shaped** — it names `node:fs`, not the `@gjsify/fs` edge that
38
+ // actually failed, and cannot name the importer;
39
+ // - **post-tree-shake** — an unresolved edge that gets shaken out leaves no
40
+ // trace at all, so the artefact passes while the build is still wrong.
41
+ //
42
+ // This guard fires at RESOLUTION time instead: it names the specifier, the
43
+ // substitution target, the importer, and the likely cause.
44
+ //
45
+ // ## The legitimate-vs-broken line
46
+ //
47
+ // A blanket "fail on any external" would break every real build — externals are
48
+ // load-bearing on every target (`gi://*`, `cairo`/`system`/`gettext` on gjs; the
49
+ // whole `EXTERNALS_NODE` set plus `@gjsify/node-gi*` and `node-datachannel` on
50
+ // node; whatever the user passed to `--external`). Those never reach the
51
+ // unresolved fallback by accident — a `resolveId` hook or the `external` option
52
+ // CLAIMS them, deliberately. So the distinction drawn here is:
53
+ //
54
+ // DECLARED external → legitimate, ignored. Asked via the target's own
55
+ // externals predicate (`isExternal`), i.e. exactly the
56
+ // policy `externalsPlugin` enforces, so the guard and the
57
+ // policy cannot drift.
58
+ // PROMISED, missing → broken. Either (a) the specifier has an entry in the
59
+ // target's substitution table and that target does not
60
+ // resolve, or (b) the specifier IS a bare `@gjsify/*`
61
+ // workspace package that does not resolve.
62
+ // anything else → not our business. A missing `lodash` is a plain
63
+ // dependency bug that `UNRESOLVED_IMPORT` already
64
+ // reports; widening to every bare specifier would turn a
65
+ // genuinely optional peer into a hard build failure, and
66
+ // this guard's whole claim is that the `@gjsify/*` edge
67
+ // is NOT optional — the target cannot run without it.
68
+ //
69
+ // On (a): the check is keyed on the ALIAS TARGET being a `@gjsify/*` package,
70
+ // not merely on the entry existing. Every value in the curated + derived tables
71
+ // is a `@gjsify/*` specifier today, so this is a distinction without a
72
+ // difference for them — but it keeps a user `--alias foo=./some/local.js` (or a
73
+ // shim path like `random-access-file/index.js`) on the old fall-through
74
+ // behaviour instead of promoting a user's own mapping mistake to a fatal error
75
+ // in a plugin they did not ask for.
76
+ //
77
+ // ## Not registered for `--library`
78
+ //
79
+ // Library mode PRESERVES imports on purpose (`preserveModules`, bare specifiers
80
+ // kept so the consumer resolves them). An unresolved `@gjsify/*` there is the
81
+ // contract, not a bug, so `library/lib.ts` deliberately does not compose this
82
+ // plugin.
83
+ import { dirname } from 'node:path';
84
+ /** Bare `@gjsify/*` package specifier — the workspace edge this guard protects. */
85
+ const WORKSPACE_SCOPE = '@gjsify/';
86
+ /**
87
+ * How many reverse-looked-up source specifiers the error may name before the
88
+ * list stops being evidence and becomes noise. A per-builtin target inverts to
89
+ * 2 (`fs` + `node:fs`); a shared sink like `@gjsify/empty` inverts to ~50.
90
+ */
91
+ const MAX_REPORTED_ALIAS_SOURCES = 4;
92
+ /**
93
+ * Is `id` a bare `@gjsify/*` package specifier (root or subpath)?
94
+ *
95
+ * Deliberately excludes disk paths and synthetic ids: a resolved
96
+ * `/…/node_modules/@gjsify/fs/lib/esm/index.js` is already resolved, and a
97
+ * `\0gjsify-*` virtual id belongs to the plugin that emitted it.
98
+ */
99
+ export function isWorkspaceSpecifier(id) {
100
+ if (!id.startsWith(WORKSPACE_SCOPE))
101
+ return false;
102
+ if (id.includes('\0'))
103
+ return false;
104
+ // `@gjsify/fs` and `@gjsify/fs/register/x` qualify; `@gjsify/` and
105
+ // `@gjsify//x` do not (no package name). A resolved disk path can never
106
+ // reach here — it is absolute or `./`-relative, so it never starts with the
107
+ // scope in the first place.
108
+ const rest = id.slice(WORKSPACE_SCOPE.length);
109
+ return rest.length > 0 && !rest.startsWith('/');
110
+ }
111
+ /**
112
+ * Pure decision: does this import edge have to resolve, and to what?
113
+ *
114
+ * Split out from the plugin so the legitimate-vs-broken line is unit-testable
115
+ * without a bundler (`packages/infra/cli/src/unresolved-workspace-import.spec.ts`).
116
+ */
117
+ export function classifyImport(input) {
118
+ const { source, importer, aliases, isExternal } = input;
119
+ // Entry modules are files the caller named; they are resolved by the
120
+ // orchestrator, never externalised.
121
+ if (importer === undefined)
122
+ return { verdict: 'ignore', reason: 'entry' };
123
+ // Relative / absolute / synthetic ids are not workspace edges.
124
+ if (source.startsWith('.') || source.startsWith('/') || source.startsWith('\0')) {
125
+ return { verdict: 'ignore', reason: 'not-bare' };
126
+ }
127
+ // A specifier the target DECLARES external is a deliberate external.
128
+ if (isExternal?.(source))
129
+ return { verdict: 'ignore', reason: 'declared-external' };
130
+ const aliasTarget = aliases?.[source];
131
+ const candidate = aliasTarget ?? source;
132
+ // The alias target may itself be declared external (`system` →
133
+ // `@gjsify/node-gi/system` on the node target).
134
+ if (candidate !== source && isExternal?.(candidate)) {
135
+ return { verdict: 'ignore', reason: 'declared-external' };
136
+ }
137
+ if (!isWorkspaceSpecifier(candidate))
138
+ return { verdict: 'ignore', reason: 'out-of-scope' };
139
+ return aliasTarget === undefined ? { verdict: 'check', candidate } : { verdict: 'check', candidate, aliasTarget };
140
+ }
141
+ /** A `@gjsify/*` edge the build promised to substitute could not be resolved. */
142
+ export class UnresolvedWorkspaceImportError extends Error {
143
+ details;
144
+ constructor(details) {
145
+ super(formatUnresolvedWorkspaceImport(details));
146
+ this.name = 'UnresolvedWorkspaceImportError';
147
+ this.details = details;
148
+ }
149
+ }
150
+ /**
151
+ * The actionable message. Names the specifier, the importer and the likely
152
+ * cause — the three things `UNRESOLVED_IMPORT` (and the post-hoc `node:` guard)
153
+ * cannot tell you.
154
+ */
155
+ export function formatUnresolvedWorkspaceImport(details) {
156
+ const { target, source, candidate, aliasTarget, aliasedFrom, importer } = details;
157
+ // The specifiers `candidate` was standing in for: `source` itself when IT
158
+ // carried the table entry, else whatever the reverse lookup recovered.
159
+ //
160
+ // The reverse lookup is only reported when its fan-in is SMALL. A shared
161
+ // sink inverts to a useless wall of text — `@gjsify/empty` is the browser
162
+ // target for 49 specifiers, and printing all of them says nothing about
163
+ // which one this importer wrote, while `@gjsify/fs` inverts to exactly
164
+ // `['fs','node:fs']` (the two spellings of one builtin), which is the
165
+ // information the reader needs. Above the threshold, fall back to naming
166
+ // the package alone rather than guessing.
167
+ const reversed = aliasedFrom ?? [];
168
+ const substitutedFor = aliasTarget === undefined ? (reversed.length <= MAX_REPORTED_ALIAS_SOURCES ? reversed : []) : [source];
169
+ const quoted = substitutedFor.map((s) => `\`${s}\``).join(', ');
170
+ const headline = substitutedFor.length === 0
171
+ ? `gjsify build --app ${target}: cannot resolve the workspace package \`${candidate}\`.`
172
+ : `gjsify build --app ${target}: cannot resolve \`${candidate}\`, the \`--app ${target}\` ` +
173
+ `substitution for ${quoted}.`;
174
+ // The symptom is a property of the SPECIFIER that would survive, not of the
175
+ // target: only a `node:` specifier reaching stock GJS produces the URI-scheme
176
+ // abort; a bare `@gjsify/*` or `<pkg>/register` one produces `Module not
177
+ // found` (GJS's ESM loader has no node_modules walker and does not follow
178
+ // `exports` maps). Naming the wrong one sends the reader hunting the wrong bug.
179
+ const surviving = substitutedFor.length === 0 ? [source] : substitutedFor;
180
+ const symptom = target !== 'gjs'
181
+ ? ''
182
+ : surviving.some((s) => s.startsWith('node:'))
183
+ ? ' Stock GJS aborts the whole module graph at load: ' +
184
+ '"ImportError: Unsupported URI scheme for importing: node".'
185
+ : ' Stock GJS would fail at load with "Module not found" — its ESM loader has no node_modules ' +
186
+ 'walker and does not follow `package.json#exports` for bare specifiers.';
187
+ const consequence = (substitutedFor.length === 0
188
+ ? `Leaving it unresolved would silently externalise \`${source}\` into the bundle, which the ` +
189
+ `\`--app ${target}\` runtime cannot resolve.`
190
+ : `Leaving it unresolved would silently externalise the ORIGINAL ${substitutedFor.length === 1 ? 'specifier' : 'specifiers'} ${quoted} into the ` +
191
+ `bundle, defeating the substitution the \`--app ${target}\` target exists to perform.`) + symptom;
192
+ return [
193
+ headline,
194
+ ` imported by: ${importer}`,
195
+ '',
196
+ consequence,
197
+ '',
198
+ 'Likely causes:',
199
+ ' - `node_modules` is missing or incomplete — run `gjsify install` (`--immutable` in CI).',
200
+ ` - the workspace package is not built: its \`exports["."]\` names a \`lib/\` that does not exist —`,
201
+ ' run `gjsify run build:infra`, or `gjsify workspace <pkg> build` for the one package.',
202
+ ` - \`${candidate}\` is genuinely not a dependency of this project — add it.`,
203
+ ].join('\n');
204
+ }
205
+ /**
206
+ * Reverse the substitution table: alias TARGET → the specifiers that route to it.
207
+ *
208
+ * Built once per plugin instance (the tables run to ~150 entries per target, and
209
+ * the guard only consults this on the failure path).
210
+ */
211
+ export function buildReverseAliasIndex(aliases) {
212
+ const index = new Map();
213
+ if (!aliases)
214
+ return index;
215
+ for (const [from, to] of Object.entries(aliases)) {
216
+ const existing = index.get(to);
217
+ if (existing)
218
+ existing.push(from);
219
+ else
220
+ index.set(to, [from]);
221
+ }
222
+ for (const list of index.values())
223
+ list.sort();
224
+ return index;
225
+ }
226
+ /**
227
+ * Refuse a build whose `@gjsify/*` substitution could not be resolved.
228
+ *
229
+ * `order: 'post'` so every deliberate claim — `aliasPlugin` (`pre`),
230
+ * `napiNodeAddonPlugin` (`pre`), `gjsGiNodePlugin` (`pre`),
231
+ * `gjsImportsEmptyPlugin`, `externalsPlugin` — gets first refusal. Only ids that
232
+ * NOTHING claimed reach this hook, i.e. exactly the ones headed for the
233
+ * unresolved-import fallback.
234
+ *
235
+ * The hook re-runs the full resolution chain via `this.resolve(…, { skipSelf })`
236
+ * — which is what Rolldown's builtin resolver would have done next — and returns
237
+ * its result when it succeeds, so a healthy build resolves the specifier exactly
238
+ * once and behaves identically. Only a genuine `null` throws.
239
+ */
240
+ export function unresolvedWorkspaceImportPlugin(options) {
241
+ const { target, aliases, isExternal } = options;
242
+ // Re-entrancy belt: `skipSelf: true` is supposed to keep our own
243
+ // `this.resolve` from re-entering this hook, but a hang is a far worse
244
+ // failure than a missed check, so the in-flight candidate is tracked
245
+ // explicitly. Keyed by `candidate\0importer` — the same package legitimately
246
+ // resolves from many importers.
247
+ const inFlight = new Set();
248
+ // Alias TARGET → the specifiers that route to it. Only read on the failure
249
+ // path, to recover the `node:fs` behind a failed `@gjsify/fs`.
250
+ const reverseAliases = buildReverseAliasIndex(aliases);
251
+ // Successful resolutions, memoized per (candidate, importer DIRECTORY) —
252
+ // the pair node resolution actually depends on, so a hit is the answer the
253
+ // chain would have recomputed. Without it this hook was the single most
254
+ // expensive plugin in a CLI-bundle build (32% of plugin time): `@gjsify/*`
255
+ // edges repeat across hundreds of modules, and each miss re-runs the whole
256
+ // `pre`-order chain (alias, napi-addon, gi-node) for the same target. Same
257
+ // shape + rationale as `napiNodeAddonPlugin`'s `bareEntryCache` (#840).
258
+ // Only POSITIVE results are cached: a failure throws, so it is never hot,
259
+ // and caching it could outlive a package appearing mid-watch.
260
+ const resolvedCache = new Map();
261
+ return {
262
+ name: 'gjsify-unresolved-workspace-import',
263
+ resolveId: {
264
+ order: 'post',
265
+ async handler(source, rawImporter, extraOptions) {
266
+ // The two engines disagree on "no importer": npm `rolldown`
267
+ // passes `undefined`, `@gjsify/rolldown-native` passes `null`
268
+ // (its hook payload round-trips through JSON, which has no
269
+ // `undefined`). `classifyImport` reads an absent importer as
270
+ // "this is an ENTRY, never externalised" via `=== undefined`,
271
+ // and `null` fails that test — so under the GJS bundler an
272
+ // entry module would have been resolved as a normal edge and
273
+ // could throw this plugin's error for a file the caller named
274
+ // explicitly. Normalise once, at the boundary — same fix as
275
+ // `napiNodeAddonPlugin` (#840), whose `dirname(null)` threw
276
+ // and took the whole GJS build down as an UNHANDLEABLE_ERROR.
277
+ const importer = typeof rawImporter === 'string' ? rawImporter : undefined;
278
+ if (extraOptions?.isEntry)
279
+ return null;
280
+ const verdict = classifyImport({ source, importer, aliases, isExternal });
281
+ if (verdict.verdict === 'ignore')
282
+ return null;
283
+ // `kind` participates in the key: it selects the `import`
284
+ // vs `require` export condition, so the same specifier can
285
+ // legitimately resolve to different files from one directory.
286
+ const key = `${verdict.candidate}\0${importer === undefined ? '' : dirname(importer)}\0${extraOptions?.kind ?? ''}`;
287
+ const cached = resolvedCache.get(key);
288
+ if (cached)
289
+ return cached;
290
+ if (inFlight.has(key))
291
+ return null;
292
+ inFlight.add(key);
293
+ let resolved;
294
+ try {
295
+ resolved = await this.resolve(verdict.candidate, importer, {
296
+ skipSelf: true,
297
+ kind: extraOptions?.kind,
298
+ });
299
+ }
300
+ finally {
301
+ inFlight.delete(key);
302
+ }
303
+ if (resolved) {
304
+ resolvedCache.set(key, resolved);
305
+ return resolved;
306
+ }
307
+ throw new UnresolvedWorkspaceImportError({
308
+ target,
309
+ source,
310
+ candidate: verdict.candidate,
311
+ aliasTarget: verdict.aliasTarget,
312
+ aliasedFrom: reverseAliases.get(verdict.candidate)?.filter((s) => s !== source),
313
+ importer: importer ?? '<entry>',
314
+ });
315
+ },
316
+ },
317
+ };
318
+ }
@@ -319,7 +319,12 @@ export async function detectAutoGlobals(analysisOptions, pluginOptions, gjsifyPl
319
319
  ?.GJSIFY_DEBUG_AUTO_GLOBALS) {
320
320
  const path = `/tmp/gjsify-auto-globals-failed-chunk-${i}.mjs`;
321
321
  try {
322
- // eslint-disable-next-line @typescript-eslint/no-require-imports
322
+ // Dynamic `import()` on purpose: this is a debug-only
323
+ // branch and the module graph should not carry
324
+ // `node:fs` for it. (It is NOT a `require` — it never
325
+ // was; the rule-disable comment that used to sit here
326
+ // named a rule that cannot apply to an import
327
+ // expression.)
323
328
  const fs = await import('node:fs');
324
329
  fs.writeFileSync(path, code);
325
330
  console.error(`[gjsify-auto-globals] parse failed on chunk #${i} — wrote ${path} for inspection`);
@@ -7,6 +7,7 @@
7
7
  // first, then re-exports the real entry. `\0`-prefixed ids are Rollup's
8
8
  // convention for synthetic modules — Rolldown treats them as not-from-disk and
9
9
  // skips the default loader.
10
+ import { GJSIFY_VIRTUAL_PREFIX } from './virtual-module-id.js';
10
11
  /**
11
12
  * If there are side-effect imports to land alongside the user's entry, wrap each
12
13
  * entry in a virtual module that imports them first then re-exports the entry.
@@ -22,7 +23,7 @@ export function wrapInputWithSideEffects(input, sideEffects, opts = {}) {
22
23
  return { input, plugin: null };
23
24
  }
24
25
  const userEntries = new Map(); // virtualId → realPath
25
- const PREFIX = '\0gjsify-entry:';
26
+ const PREFIX = `${GJSIFY_VIRTUAL_PREFIX}entry:`;
26
27
  function wrap(realPath) {
27
28
  const id = PREFIX + realPath;
28
29
  userEntries.set(id, realPath);
@@ -6,3 +6,4 @@ export * from './merge.js';
6
6
  export { detectFreeGlobals } from './detect-free-globals.js';
7
7
  export { resolveGlobalsList, writeRegisterInjectFile } from './scan-globals.js';
8
8
  export { inlineStaticReads } from './inline-static-reads.js';
9
+ export { GJSIFY_VIRTUAL_PREFIX, isGjsifyVirtualModuleId } from './virtual-module-id.js';
@@ -6,3 +6,4 @@ export * from './merge.js';
6
6
  export { detectFreeGlobals } from './detect-free-globals.js';
7
7
  export { resolveGlobalsList, writeRegisterInjectFile } from './scan-globals.js';
8
8
  export { inlineStaticReads } from './inline-static-reads.js';
9
+ export { GJSIFY_VIRTUAL_PREFIX, isGjsifyVirtualModuleId } from './virtual-module-id.js';
@@ -0,0 +1,14 @@
1
+ /** Shared prefix of every gjsify-generated (synthetic) module id. */
2
+ export declare const GJSIFY_VIRTUAL_PREFIX = "\0gjsify-";
3
+ /**
4
+ * Is `id` a module gjsify's own plugins generated (as opposed to a user/npm
5
+ * source file)?
6
+ *
7
+ * Used by `aliasPlugin` to scope the alias tables to REAL source: generated
8
+ * module bodies name the runtime module they need explicitly and must not be
9
+ * re-pointed by a user alias or a slot-routing entry.
10
+ *
11
+ * @param id A Rolldown module id — typically a `resolveId` `importer`, which is
12
+ * `undefined` for entry modules.
13
+ */
14
+ export declare function isGjsifyVirtualModuleId(id: string | undefined | null): boolean;
@@ -0,0 +1,36 @@
1
+ // The ONE prefix every synthetic module id emitted by a gjsify plugin carries.
2
+ //
3
+ // Rollup/Rolldown convention is that a `\0`-prefixed id is not-from-disk; every
4
+ // gjsify plugin that emits one additionally namespaces it with `gjsify-`
5
+ // (`\0gjsify-entry:`, `\0gjsify-gi-node:`, `\0gjsify-napi-addon:`,
6
+ // `\0gjsify-empty-gjs-import`). Deriving those ids from THIS constant turns that
7
+ // naming habit into an enforced invariant, which matters because the alias layer
8
+ // keys off it: a module whose SOURCE we generated must bind to the RUNTIME's real
9
+ // modules, never to whatever a user `--alias` retargets a specifier onto.
10
+ //
11
+ // Concretely (the bug that motivated this): `gjsGiNodePlugin`'s virtual module
12
+ // emits `import { createRequire } from 'node:module'`. Under the node-gi consumer
13
+ // harness — which builds `--alias node:module=@gjsify/module` to put the polyfill
14
+ // UNDER TEST behind the specifier — that import was rewritten onto the polyfill
15
+ // itself, so the bundle called `@gjsify/module`'s `createRequire` at top level
16
+ // before its lazy GLib namespace proxy existed (`TypeError: Cannot read
17
+ // properties of undefined (reading 'filename_from_uri')`), and past that hit a
18
+ // genuine cycle: the polyfill's Gio-backed CJS loader needs GLib, and GLib is
19
+ // reached through `@gjsify/node-gi/gi` — which is what the virtual module was
20
+ // loading in the first place.
21
+ /** Shared prefix of every gjsify-generated (synthetic) module id. */
22
+ export const GJSIFY_VIRTUAL_PREFIX = '\0gjsify-';
23
+ /**
24
+ * Is `id` a module gjsify's own plugins generated (as opposed to a user/npm
25
+ * source file)?
26
+ *
27
+ * Used by `aliasPlugin` to scope the alias tables to REAL source: generated
28
+ * module bodies name the runtime module they need explicitly and must not be
29
+ * re-pointed by a user alias or a slot-routing entry.
30
+ *
31
+ * @param id A Rolldown module id — typically a `resolveId` `importer`, which is
32
+ * `undefined` for entry modules.
33
+ */
34
+ export function isGjsifyVirtualModuleId(id) {
35
+ return typeof id === 'string' && id.startsWith(GJSIFY_VIRTUAL_PREFIX);
36
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/rolldown-plugin-gjsify",
3
- "version": "0.23.0",
3
+ "version": "0.24.2",
4
4
  "description": "Rolldown / Rollup / Vite plugin orchestrator for GJS, Node, and Browser targets",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -55,11 +55,11 @@
55
55
  ],
56
56
  "license": "MIT",
57
57
  "dependencies": {
58
- "@gjsify/console": "^0.23.0",
59
- "@gjsify/resolve-npm": "^0.23.0",
60
- "@gjsify/rolldown-plugin-deepkit": "^0.23.0",
61
- "@gjsify/rolldown-plugin-pnp": "^0.23.0",
62
- "@gjsify/vite-plugin-blueprint": "^0.23.0",
58
+ "@gjsify/console": "^0.24.2",
59
+ "@gjsify/resolve-npm": "^0.24.2",
60
+ "@gjsify/rolldown-plugin-deepkit": "^0.24.2",
61
+ "@gjsify/rolldown-plugin-pnp": "^0.24.2",
62
+ "@gjsify/vite-plugin-blueprint": "^0.24.2",
63
63
  "@rollup/pluginutils": "^5.4.0",
64
64
  "acorn": "^8.17.0",
65
65
  "acorn-walk": "^8.3.5",
@@ -68,7 +68,7 @@
68
68
  "sass": "^1.101.0"
69
69
  },
70
70
  "peerDependencies": {
71
- "@gjsify/lightningcss-native": "^0.23.0",
71
+ "@gjsify/lightningcss-native": "^0.24.2",
72
72
  "rolldown": "^1.1.4"
73
73
  },
74
74
  "peerDependenciesMeta": {