void 0.7.5 → 0.7.6

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,577 @@
1
+ import { a as join } from "./pathe.M-eThtNZ-D-kmWkCS.mjs";
2
+ import { n as globSync } from "./dist-DUyXJLkq.mjs";
3
+ import { existsSync, readFileSync } from "node:fs";
4
+ import { parseSync } from "vite";
5
+ import { parse } from "es-module-lexer/js";
6
+ //#region ../../node_modules/.pnpm/estree-walker@3.0.3/node_modules/estree-walker/src/walker.js
7
+ /**
8
+ * @typedef { import('estree').Node} Node
9
+ * @typedef {{
10
+ * skip: () => void;
11
+ * remove: () => void;
12
+ * replace: (node: Node) => void;
13
+ * }} WalkerContext
14
+ */
15
+ var WalkerBase = class {
16
+ constructor() {
17
+ /** @type {boolean} */
18
+ this.should_skip = false;
19
+ /** @type {boolean} */
20
+ this.should_remove = false;
21
+ /** @type {Node | null} */
22
+ this.replacement = null;
23
+ /** @type {WalkerContext} */
24
+ this.context = {
25
+ skip: () => this.should_skip = true,
26
+ remove: () => this.should_remove = true,
27
+ replace: (node) => this.replacement = node
28
+ };
29
+ }
30
+ /**
31
+ * @template {Node} Parent
32
+ * @param {Parent | null | undefined} parent
33
+ * @param {keyof Parent | null | undefined} prop
34
+ * @param {number | null | undefined} index
35
+ * @param {Node} node
36
+ */
37
+ replace(parent, prop, index, node) {
38
+ if (parent && prop) if (index != null)
39
+ /** @type {Array<Node>} */ parent[prop][index] = node;
40
+ else
41
+ /** @type {Node} */ parent[prop] = node;
42
+ }
43
+ /**
44
+ * @template {Node} Parent
45
+ * @param {Parent | null | undefined} parent
46
+ * @param {keyof Parent | null | undefined} prop
47
+ * @param {number | null | undefined} index
48
+ */
49
+ remove(parent, prop, index) {
50
+ if (parent && prop) if (index !== null && index !== void 0)
51
+ /** @type {Array<Node>} */ parent[prop].splice(index, 1);
52
+ else delete parent[prop];
53
+ }
54
+ };
55
+ //#endregion
56
+ //#region ../../node_modules/.pnpm/estree-walker@3.0.3/node_modules/estree-walker/src/sync.js
57
+ /**
58
+ * @typedef { import('estree').Node} Node
59
+ * @typedef { import('./walker.js').WalkerContext} WalkerContext
60
+ * @typedef {(
61
+ * this: WalkerContext,
62
+ * node: Node,
63
+ * parent: Node | null,
64
+ * key: string | number | symbol | null | undefined,
65
+ * index: number | null | undefined
66
+ * ) => void} SyncHandler
67
+ */
68
+ var SyncWalker = class extends WalkerBase {
69
+ /**
70
+ *
71
+ * @param {SyncHandler} [enter]
72
+ * @param {SyncHandler} [leave]
73
+ */
74
+ constructor(enter, leave) {
75
+ super();
76
+ /** @type {boolean} */
77
+ this.should_skip = false;
78
+ /** @type {boolean} */
79
+ this.should_remove = false;
80
+ /** @type {Node | null} */
81
+ this.replacement = null;
82
+ /** @type {WalkerContext} */
83
+ this.context = {
84
+ skip: () => this.should_skip = true,
85
+ remove: () => this.should_remove = true,
86
+ replace: (node) => this.replacement = node
87
+ };
88
+ /** @type {SyncHandler | undefined} */
89
+ this.enter = enter;
90
+ /** @type {SyncHandler | undefined} */
91
+ this.leave = leave;
92
+ }
93
+ /**
94
+ * @template {Node} Parent
95
+ * @param {Node} node
96
+ * @param {Parent | null} parent
97
+ * @param {keyof Parent} [prop]
98
+ * @param {number | null} [index]
99
+ * @returns {Node | null}
100
+ */
101
+ visit(node, parent, prop, index) {
102
+ if (node) {
103
+ if (this.enter) {
104
+ const _should_skip = this.should_skip;
105
+ const _should_remove = this.should_remove;
106
+ const _replacement = this.replacement;
107
+ this.should_skip = false;
108
+ this.should_remove = false;
109
+ this.replacement = null;
110
+ this.enter.call(this.context, node, parent, prop, index);
111
+ if (this.replacement) {
112
+ node = this.replacement;
113
+ this.replace(parent, prop, index, node);
114
+ }
115
+ if (this.should_remove) this.remove(parent, prop, index);
116
+ const skipped = this.should_skip;
117
+ const removed = this.should_remove;
118
+ this.should_skip = _should_skip;
119
+ this.should_remove = _should_remove;
120
+ this.replacement = _replacement;
121
+ if (skipped) return node;
122
+ if (removed) return null;
123
+ }
124
+ /** @type {keyof Node} */
125
+ let key;
126
+ for (key in node) {
127
+ /** @type {unknown} */
128
+ const value = node[key];
129
+ if (value && typeof value === "object") {
130
+ if (Array.isArray(value)) {
131
+ const nodes = value;
132
+ for (let i = 0; i < nodes.length; i += 1) {
133
+ const item = nodes[i];
134
+ if (isNode(item)) {
135
+ if (!this.visit(item, node, key, i)) i--;
136
+ }
137
+ }
138
+ } else if (isNode(value)) this.visit(value, node, key, null);
139
+ }
140
+ }
141
+ if (this.leave) {
142
+ const _replacement = this.replacement;
143
+ const _should_remove = this.should_remove;
144
+ this.replacement = null;
145
+ this.should_remove = false;
146
+ this.leave.call(this.context, node, parent, prop, index);
147
+ if (this.replacement) {
148
+ node = this.replacement;
149
+ this.replace(parent, prop, index, node);
150
+ }
151
+ if (this.should_remove) this.remove(parent, prop, index);
152
+ const removed = this.should_remove;
153
+ this.replacement = _replacement;
154
+ this.should_remove = _should_remove;
155
+ if (removed) return null;
156
+ }
157
+ }
158
+ return node;
159
+ }
160
+ };
161
+ /**
162
+ * Ducktype a node.
163
+ *
164
+ * @param {unknown} value
165
+ * @returns {value is Node}
166
+ */
167
+ function isNode(value) {
168
+ return value !== null && typeof value === "object" && "type" in value && typeof value.type === "string";
169
+ }
170
+ //#endregion
171
+ //#region ../../node_modules/.pnpm/estree-walker@3.0.3/node_modules/estree-walker/src/index.js
172
+ /**
173
+ * @typedef {import('estree').Node} Node
174
+ * @typedef {import('./sync.js').SyncHandler} SyncHandler
175
+ * @typedef {import('./async.js').AsyncHandler} AsyncHandler
176
+ */
177
+ /**
178
+ * @param {Node} ast
179
+ * @param {{
180
+ * enter?: SyncHandler
181
+ * leave?: SyncHandler
182
+ * }} walker
183
+ * @returns {Node | null}
184
+ */
185
+ function walk(ast, { enter, leave }) {
186
+ return new SyncWalker(enter, leave).visit(ast, null);
187
+ }
188
+ //#endregion
189
+ //#region src/shared/ast.ts
190
+ function isIdentifier(node) {
191
+ return node?.type === "Identifier" && typeof node.name === "string";
192
+ }
193
+ function isLiteral(node) {
194
+ return node?.type === "Literal";
195
+ }
196
+ function isMemberExpression(node) {
197
+ return node?.type === "MemberExpression";
198
+ }
199
+ function isCallExpression(node) {
200
+ return node?.type === "CallExpression";
201
+ }
202
+ function isObjectExpression(node) {
203
+ return node?.type === "ObjectExpression";
204
+ }
205
+ //#endregion
206
+ //#region src/inference/walk.ts
207
+ const ENV_BINDING_RE = /\benv\s*\.\s*(DB|KV|STORAGE|QUEUE_\w+|AI|SANDBOX)\b/;
208
+ /**
209
+ * Infer which Cloudflare bindings a source file uses.
210
+ *
211
+ * Uses a tiered approach for performance:
212
+ * Tier 1: es-module-lexer to extract import sources (fast, asm.js, no init)
213
+ * Tier 2: Regex check for env.DB/KV/STORAGE patterns
214
+ * Tier 3: Full AST walk only when regex matches (to confirm member expressions)
215
+ */
216
+ function inferBindingsFromSource(code, filename) {
217
+ const result = {
218
+ needsD1: false,
219
+ needsKV: false,
220
+ needsR2: false,
221
+ needsAuth: false,
222
+ needsQueues: false,
223
+ needsAI: false,
224
+ needsSandbox: false,
225
+ needsLive: false
226
+ };
227
+ try {
228
+ const [imports] = parse(code);
229
+ for (const imp of imports) {
230
+ const source = imp.n;
231
+ if (!source) continue;
232
+ switch (source) {
233
+ case "void/db":
234
+ result.needsD1 = true;
235
+ break;
236
+ case "void/kv":
237
+ result.needsKV = true;
238
+ break;
239
+ case "void/storage":
240
+ result.needsR2 = true;
241
+ break;
242
+ case "void/auth":
243
+ result.needsAuth = true;
244
+ break;
245
+ case "void/queue":
246
+ result.needsQueues = true;
247
+ break;
248
+ case "void/ai":
249
+ result.needsAI = true;
250
+ break;
251
+ case "void/sandbox":
252
+ result.needsSandbox = true;
253
+ break;
254
+ case "void/live":
255
+ if (!isTypeOnlyImportStatement(code.slice(imp.ss, imp.se + 1))) result.needsLive = true;
256
+ break;
257
+ case "void/client": {
258
+ const stmt = code.slice(imp.ss, imp.se + 1);
259
+ if (/\bauth\b/.test(stmt)) result.needsAuth = true;
260
+ break;
261
+ }
262
+ }
263
+ }
264
+ } catch {
265
+ if (/\bfrom\s+["']void\/db["']/.test(code)) result.needsD1 = true;
266
+ if (/\bfrom\s+["']void\/kv["']/.test(code)) result.needsKV = true;
267
+ if (/\bfrom\s+["']void\/storage["']/.test(code)) result.needsR2 = true;
268
+ if (/\bfrom\s+["']void\/auth["']/.test(code)) result.needsAuth = true;
269
+ if (/\bfrom\s+["']void\/queue["']/.test(code)) result.needsQueues = true;
270
+ if (/\bfrom\s+["']void\/ai["']/.test(code)) result.needsAI = true;
271
+ if (/\bfrom\s+["']void\/sandbox["']/.test(code)) result.needsSandbox = true;
272
+ if (hasRuntimeImportFrom(code, "void/live")) result.needsLive = true;
273
+ if (/\bfrom\s+["']void\/client["']/.test(code) && /\bauth\b/.test(code)) result.needsAuth = true;
274
+ }
275
+ if (result.needsD1 && result.needsKV && result.needsR2 && result.needsAI && result.needsSandbox && result.needsLive) return result;
276
+ if (!ENV_BINDING_RE.test(code)) return result;
277
+ let parsed;
278
+ try {
279
+ parsed = parseSync(filename, code);
280
+ } catch {
281
+ return result;
282
+ }
283
+ const program = parsed.program;
284
+ walk(program, { enter(node) {
285
+ const current = node;
286
+ if (!isMemberExpression(current)) return;
287
+ if (current.computed) return;
288
+ const property = current.property;
289
+ if (!isIdentifier(property)) return;
290
+ const obj = current.object;
291
+ const isViaContextEnv = isMemberExpression(obj) && isIdentifier(obj.property) && obj.property.name === "env";
292
+ const isDirectEnv = isIdentifier(obj) && obj.name === "env";
293
+ if (!isViaContextEnv && !isDirectEnv) return;
294
+ switch (property.name) {
295
+ case "DB":
296
+ result.needsD1 = true;
297
+ break;
298
+ case "KV":
299
+ result.needsKV = true;
300
+ break;
301
+ case "STORAGE":
302
+ result.needsR2 = true;
303
+ break;
304
+ case "AI":
305
+ result.needsAI = true;
306
+ break;
307
+ case "SANDBOX":
308
+ result.needsSandbox = true;
309
+ break;
310
+ default:
311
+ if (property.name.startsWith("QUEUE_")) result.needsQueues = true;
312
+ break;
313
+ }
314
+ } });
315
+ return result;
316
+ }
317
+ function isTypeOnlyImportStatement(statement) {
318
+ if (/^\s*import\s+type\b/.test(statement)) return true;
319
+ const specifierStart = statement.indexOf("{");
320
+ const specifierEnd = statement.lastIndexOf("}");
321
+ if (specifierStart === -1 || specifierEnd === -1 || specifierEnd < specifierStart) return false;
322
+ const beforeSpecifiers = statement.slice(0, specifierStart);
323
+ if (!/^\s*import\s*$/.test(beforeSpecifiers)) return false;
324
+ const specifiers = statement.slice(specifierStart + 1, specifierEnd).split(",").map((specifier) => specifier.trim()).filter(Boolean);
325
+ return specifiers.length > 0 && specifiers.every((specifier) => specifier.startsWith("type "));
326
+ }
327
+ function hasRuntimeImportFrom(code, source) {
328
+ const escapedSource = source.replaceAll("/", "\\/");
329
+ const importRe = new RegExp(`\\bimport\\s+(?:[\\s\\S]*?\\bfrom\\s+)?["']${escapedSource}["']\\s*;?`, "g");
330
+ for (const match of code.matchAll(importRe)) {
331
+ const statement = match[0];
332
+ if (!isTypeOnlyImportStatement(statement)) return true;
333
+ }
334
+ return false;
335
+ }
336
+ /**
337
+ * Merge multiple InferredBindings into a single result (union).
338
+ */
339
+ function mergeBindings(bindings) {
340
+ return {
341
+ needsD1: bindings.some((b) => b.needsD1),
342
+ needsKV: bindings.some((b) => b.needsKV),
343
+ needsR2: bindings.some((b) => b.needsR2),
344
+ needsAuth: bindings.some((b) => b.needsAuth),
345
+ needsQueues: bindings.some((b) => b.needsQueues),
346
+ needsAI: bindings.some((b) => b.needsAI),
347
+ needsSandbox: bindings.some((b) => b.needsSandbox),
348
+ needsLive: bindings.some((b) => b.needsLive)
349
+ };
350
+ }
351
+ //#endregion
352
+ //#region src/ssr/entry.ts
353
+ const SSR_SERVER_ENTRY_RELATIVE_PATHS = ["src/main.ssr.ts", "src/main.ssr.tsx"];
354
+ const SSR_CLIENT_ENTRY_RELATIVE_PATHS = ["src/main.client.ts", "src/main.client.tsx"];
355
+ function resolveSingleEntry(root, entries, label) {
356
+ const matches = entries.map((relativePath) => ({
357
+ relativePath,
358
+ absolutePath: join(root, relativePath)
359
+ })).filter((entry) => existsSync(entry.absolutePath));
360
+ if (matches.length === 0) return null;
361
+ if (matches.length > 1) {
362
+ const names = matches.map((entry) => entry.relativePath).join(", ");
363
+ throw new Error(`ssr: Multiple ${label} entry files found: ${names}. Keep only one.`);
364
+ }
365
+ return matches[0];
366
+ }
367
+ function getSsrServerEntryPath(root) {
368
+ return resolveSingleEntry(root, SSR_SERVER_ENTRY_RELATIVE_PATHS, "SSR")?.absolutePath ?? null;
369
+ }
370
+ function hasSsrEntry(root) {
371
+ return getSsrServerEntryPath(root) !== null;
372
+ }
373
+ function validateServerRenderExport(entry) {
374
+ const { absolutePath, relativePath } = entry;
375
+ const source = readFileSync(absolutePath, "utf-8");
376
+ if (/\bexport\s+(?:async\s+)?function\s+render\b/.test(source) || /\bexport\s+const\s+render\b/.test(source) || /\bexport\s+default\s+(?:defineRender\b|(?:async\s+)?function\b)/.test(source)) return;
377
+ let parsed;
378
+ try {
379
+ parsed = parseSync(relativePath, source);
380
+ } catch (err) {
381
+ throw new Error(`ssr: Invalid entry '${relativePath}'. Could not parse source: '${err instanceof Error ? err.message : String(err)}'.`);
382
+ }
383
+ if (!(parsed.program.body ?? []).some((node) => {
384
+ if (node.type === "ExportDefaultDeclaration") {
385
+ const declaration = node.declaration;
386
+ if (declaration?.type === "FunctionDeclaration" || declaration?.type === "FunctionExpression" || declaration?.type === "ArrowFunctionExpression") return true;
387
+ if (declaration?.type === "CallExpression") {
388
+ const call = declaration;
389
+ return isIdentifier(call.callee) && call.callee.name === "defineRender";
390
+ }
391
+ return false;
392
+ }
393
+ if (node.type !== "ExportNamedDeclaration") return false;
394
+ const declaration = node.declaration;
395
+ if (declaration?.type === "FunctionDeclaration") {
396
+ const fn = declaration;
397
+ return isIdentifier(fn.id) && fn.id.name === "render";
398
+ }
399
+ if (declaration?.type === "VariableDeclaration") return (declaration.declarations ?? []).some((decl) => isIdentifier(decl.id) && decl.id.name === "render");
400
+ return (node.specifiers ?? []).some((specifier) => {
401
+ const exported = specifier.exported;
402
+ return isIdentifier(exported) && exported.name === "render";
403
+ });
404
+ })) throw new Error(`ssr: Invalid entry '${relativePath}'. Export \`render(c, assetTags)\` or \`export default defineRender(...)\`.`);
405
+ }
406
+ /**
407
+ * Validate SSR mode entry conventions.
408
+ * Returns null when SSR mode is not used.
409
+ */
410
+ function validateSsrEntries(root) {
411
+ const server = resolveSingleEntry(root, SSR_SERVER_ENTRY_RELATIVE_PATHS, "SSR");
412
+ const client = resolveSingleEntry(root, SSR_CLIENT_ENTRY_RELATIVE_PATHS, "SSR client");
413
+ if (!server && !client) return null;
414
+ if (server && !client) throw new Error(`ssr: Missing client entry. Add one of: ${SSR_CLIENT_ENTRY_RELATIVE_PATHS.join(", ")}.`);
415
+ if (!server && client) throw new Error(`ssr: Missing server entry. Add one of: ${SSR_SERVER_ENTRY_RELATIVE_PATHS.join(", ")}.`);
416
+ validateServerRenderExport(server);
417
+ return {
418
+ server,
419
+ client
420
+ };
421
+ }
422
+ function validateSsrEntry(root) {
423
+ return validateSsrEntries(root)?.server.absolutePath ?? null;
424
+ }
425
+ //#endregion
426
+ //#region src/plugin-inference.ts
427
+ const SOURCE_GLOB = "**/*.{ts,tsx,mts,js,jsx,mjs,astro}";
428
+ /** Directories to scan for binding inference in framework mode. */
429
+ const FRAMEWORK_SCAN_DIRS = [
430
+ "src",
431
+ "app",
432
+ "pages",
433
+ "routes",
434
+ "server",
435
+ "crons",
436
+ "queues"
437
+ ];
438
+ /** Directories to scan for binding inference in Void app mode. */
439
+ const DEFAULT_SCAN_DIRS = [
440
+ "routes",
441
+ "middleware",
442
+ "queues",
443
+ "pages",
444
+ "crons",
445
+ "src"
446
+ ];
447
+ /**
448
+ * Map from npm package name to framework identifier.
449
+ * Only packages that unambiguously indicate framework mode are listed.
450
+ * For example, `react-router` alone is a client-side router — only
451
+ * `@react-router/dev` signals the framework (Vite plugin) mode.
452
+ */
453
+ const FRAMEWORK_PACKAGES = {
454
+ "@tanstack/react-start": {
455
+ name: "tanstack-start",
456
+ class: "a"
457
+ },
458
+ "@react-router/dev": {
459
+ name: "react-router",
460
+ class: "a"
461
+ },
462
+ vinext: {
463
+ name: "vinext-pages",
464
+ class: "a"
465
+ },
466
+ "@sveltejs/kit": {
467
+ name: "sveltekit",
468
+ class: "b"
469
+ },
470
+ nuxt: {
471
+ name: "nuxt",
472
+ class: "c"
473
+ },
474
+ "@analogjs/platform": {
475
+ name: "analog",
476
+ class: "c"
477
+ },
478
+ astro: {
479
+ name: "astro",
480
+ class: "c"
481
+ }
482
+ };
483
+ /**
484
+ * Detect a meta-framework by checking package.json dependencies.
485
+ * Returns the detected framework with class info, or `undefined`.
486
+ */
487
+ function detectFramework(root) {
488
+ let pkg;
489
+ try {
490
+ pkg = JSON.parse(readFileSync(join(root, "package.json"), "utf-8"));
491
+ } catch {
492
+ return;
493
+ }
494
+ const deps = {
495
+ ...pkg.dependencies,
496
+ ...pkg.devDependencies
497
+ };
498
+ for (const [pkgName, framework] of Object.entries(FRAMEWORK_PACKAGES)) if (pkgName in deps) {
499
+ if (framework.name === "vinext-pages" && existsSync(join(root, "app"))) return {
500
+ name: "vinext-app",
501
+ class: "a"
502
+ };
503
+ return framework;
504
+ }
505
+ }
506
+ function extractAstroFrontmatter(code) {
507
+ return code.match(/^\uFEFF?---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/)?.[1] ?? "";
508
+ }
509
+ function inferBindingsFromFile(file, code) {
510
+ const filename = file.split("/").pop() ?? "unknown.ts";
511
+ if (!filename.endsWith(".astro")) return inferBindingsFromSource(code, filename);
512
+ return inferBindingsFromSource(extractAstroFrontmatter(code), filename.replace(/\.astro$/, ".ts"));
513
+ }
514
+ /**
515
+ * Synchronously infer which Cloudflare bindings the project needs
516
+ * by scanning route/middleware files and optional src/main.ssr.ts with oxc-parser.
517
+ *
518
+ * This runs once when voidPlugin() is called (before plugins initialize),
519
+ * so results are available to configure the Cloudflare plugin.
520
+ *
521
+ * @param scanDirs - Override the default scan directories (e.g., for framework mode)
522
+ */
523
+ function inferProjectBindings(root, options, scanDirs) {
524
+ if (options?.bindings) return {
525
+ needsD1: Boolean(options.bindings.db),
526
+ needsKV: Boolean(options.bindings.kv),
527
+ needsR2: Boolean(options.bindings.storage),
528
+ needsAuth: false,
529
+ needsQueues: false,
530
+ needsAI: Boolean(options.bindings.ai),
531
+ needsSandbox: false,
532
+ needsLive: false
533
+ };
534
+ const dirs = scanDirs ?? DEFAULT_SCAN_DIRS;
535
+ const allBindings = [];
536
+ for (const dir of dirs) {
537
+ const dirPath = join(root, dir);
538
+ let files;
539
+ try {
540
+ files = globSync(SOURCE_GLOB, {
541
+ cwd: dirPath,
542
+ absolute: true
543
+ });
544
+ } catch {
545
+ continue;
546
+ }
547
+ for (const file of files) {
548
+ const code = readFileSync(file, "utf-8");
549
+ allBindings.push(inferBindingsFromFile(file, code));
550
+ }
551
+ }
552
+ const ssrEntry = getSsrServerEntryPath(root);
553
+ if (ssrEntry) {
554
+ const code = readFileSync(ssrEntry, "utf-8");
555
+ const filename = ssrEntry.split("/").pop() ?? "main.ssr.ts";
556
+ allBindings.push(inferBindingsFromSource(code, filename));
557
+ }
558
+ if (!new Set(dirs).has("src")) {
559
+ const srcPath = join(root, "src");
560
+ let srcFiles;
561
+ try {
562
+ srcFiles = globSync(SOURCE_GLOB, {
563
+ cwd: srcPath,
564
+ absolute: true
565
+ });
566
+ } catch {
567
+ srcFiles = [];
568
+ }
569
+ for (const file of srcFiles) {
570
+ const code = readFileSync(file, "utf-8");
571
+ allBindings.push(inferBindingsFromFile(file, code));
572
+ }
573
+ }
574
+ return mergeBindings(allBindings);
575
+ }
576
+ //#endregion
577
+ export { SSR_CLIENT_ENTRY_RELATIVE_PATHS as a, validateSsrEntries as c, isCallExpression as d, isIdentifier as f, walk as g, isObjectExpression as h, inferProjectBindings as i, validateSsrEntry as l, isMemberExpression as m, FRAMEWORK_SCAN_DIRS as n, SSR_SERVER_ENTRY_RELATIVE_PATHS as o, isLiteral as p, detectFramework as r, hasSsrEntry as s, DEFAULT_SCAN_DIRS as t, inferBindingsFromSource as u };
@@ -3,8 +3,8 @@ import { n as cliTitle } from "./output-BwlcIYSR.mjs";
3
3
  import { n as loadVoidAuthConfig, t as findVoidAuthConfig } from "./config-CvHtTM0q.mjs";
4
4
  import { c as R, g as ge, u as Se, y as ye } from "./dist-Dayj3gCK.mjs";
5
5
  import { c as getDatabaseDialect, f as readConfig } from "./config-BIa9HwVX.mjs";
6
- import { t as scanRoutes } from "./scan-QtRTdh94.mjs";
7
- import { i as inferProjectBindings, n as FRAMEWORK_SCAN_DIRS, r as detectFramework } from "./plugin-inference-CCtRkt9O.mjs";
6
+ import { t as scanRoutes } from "./scan-vv5u7rHu.mjs";
7
+ import { i as inferProjectBindings, n as FRAMEWORK_SCAN_DIRS, r as detectFramework } from "./plugin-inference-CXUuq0aC.mjs";
8
8
  import { i as generateDbDts, n as generateQueueTypes, t as generateRouteTypes } from "./route-types-DReF1gUY.mjs";
9
9
  import { n as ensureProjectTsconfig } from "./project-tsconfig-DfkESbDL.mjs";
10
10
  import { t as discoverSchema } from "./discover-B7FkXBLB.mjs";
@@ -1,5 +1,5 @@
1
1
  import { a as join, s as resolve } from "./pathe.M-eThtNZ-D-kmWkCS.mjs";
2
- import { s as hasSsrEntry } from "./plugin-inference-CCtRkt9O.mjs";
2
+ import { s as hasSsrEntry } from "./plugin-inference-CXUuq0aC.mjs";
3
3
  import { existsSync, readFileSync } from "node:fs";
4
4
  //#region src/cli/preset.ts
5
5
  /**
@@ -1,5 +1,6 @@
1
1
  import { n as HeadDescriptor, t as HeadConfig } from "./head-CZGAunBV.mjs";
2
2
  import { n as CloudContext, t as CloudBindings } from "./handler-dKQWyF-G.mjs";
3
+ import { t as DevCssAsset } from "./types-D6AuY5Bf.mjs";
3
4
 
4
5
  //#region src/pages/protocol.d.ts
5
6
  /** Escape characters that are unsafe inside inline <script> tags to prevent XSS. */
@@ -22,6 +23,8 @@ type AssetTags = {
22
23
  css: string;
23
24
  preloads: string;
24
25
  body: string;
26
+ devCss?: Array<DevCssAsset>;
27
+ devCssNonce?: string;
25
28
  };
26
29
  type RenderPage = (pageObj: PageObject, assetTags: AssetTags) => Promise<PageRenderResult>;
27
30
  type GetAssetTags = (req: Request, env: CloudBindings, componentId: string) => Promise<AssetTags>;
@@ -1,6 +1,6 @@
1
1
  import { a as join, t as basename } from "./pathe.M-eThtNZ-D-kmWkCS.mjs";
2
2
  import { n as globSync, t as glob } from "./dist-DUyXJLkq.mjs";
3
- import { d as isCallExpression, f as isIdentifier, h as isObjectExpression, p as isLiteral } from "./plugin-inference-CCtRkt9O.mjs";
3
+ import { d as isCallExpression, f as isIdentifier, h as isObjectExpression, p as isLiteral } from "./plugin-inference-CXUuq0aC.mjs";
4
4
  import { o as parseRouteFilename, s as parseWebSocketFilename, t as scanPages } from "./scan-Ba4hFwlH.mjs";
5
5
  import { readFileSync } from "node:fs";
6
6
  import { parseSync } from "vite";
@@ -53,5 +53,13 @@ interface PageScanResult {
53
53
  layouts: Array<LayoutDefinition>;
54
54
  namedLayouts: Array<NamedLayoutDefinition>;
55
55
  }
56
+ interface DevCssAsset {
57
+ /** Vite client URL used to request the CSS module. */
58
+ url: string;
59
+ /** Vite dev style id used by the client to adopt/update SSR-inlined styles. */
60
+ id?: string;
61
+ /** CSS bytes returned by Vite's client environment transform with ?inline. */
62
+ css: string;
63
+ }
56
64
  //#endregion
57
- export { PageScanResult as i, NamedLayoutDefinition as n, PageDefinition as r, LayoutDefinition as t };
65
+ export { PageScanResult as a, PageDefinition as i, LayoutDefinition as n, NamedLayoutDefinition as r, DevCssAsset as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "void",
3
- "version": "0.7.5",
3
+ "version": "0.7.6",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/voidzero-dev/void.git",
@@ -300,6 +300,7 @@
300
300
  "drizzle-orm": "^0.45.2",
301
301
  "drizzle-valibot": "^0.4.2",
302
302
  "drizzle-zod": "^0.8.3",
303
+ "es-module-lexer": "^2.1.0",
303
304
  "hono": "^4.12.18",
304
305
  "ignore": "^7.0.5",
305
306
  "jsonc-parser": "3.3.1",
@@ -314,7 +315,6 @@
314
315
  "@types/pg": "^8.20.0",
315
316
  "@typescript/native-preview": "7.0.0-dev.20260507.1",
316
317
  "arktype": "^2.2.0",
317
- "es-module-lexer": "^2.1.0",
318
318
  "estree-walker": "^3.0.3",
319
319
  "magic-string": "^0.30.21",
320
320
  "ofetch": "2.0.0-alpha.3",
@@ -332,7 +332,7 @@
332
332
  "valibot": ">=1.0.0-beta.7",
333
333
  "vite": "^8.0.0",
334
334
  "zod": "^3.25.0 || ^4.0.0",
335
- "@void/md": "0.7.5"
335
+ "@void/md": "0.7.6"
336
336
  },
337
337
  "peerDependenciesMeta": {
338
338
  "@void/md": {