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.
package/dist/index.mjs CHANGED
@@ -4,10 +4,10 @@ import { u as require_picocolors } from "./output-BwlcIYSR.mjs";
4
4
  import { n as loadVoidAuthConfig, t as findVoidAuthConfig } from "./config-CvHtTM0q.mjs";
5
5
  import { r as readProjectConfig } from "./project-TqORyHn8.mjs";
6
6
  import { c as getToken, u as isStagingMode } from "./client-DCqnMpDt.mjs";
7
- import { C as resolveSandboxConfig, S as isSandboxEnabled, _ as readExistingLiveBindingConfig, a as prerenderPagesNode, b as syncWranglerBindings, c as filterLoadedEnv, d as LIVE_MIGRATION_TAG, f as ensureWranglerCompatibilityDate, g as normalizeWranglerCompatibilityFlags, h as nextDurableObjectMigrationTag, i as prerenderPages, l as resolveRemoteMode, m as hasDurableObjectSqliteMigration, n as resolveDistDir, o as DEFAULT_PROXY_URL, p as ensureWranglerNodejsAlsFlag, r as resolveWorkerDirName, s as STAGING_PROXY_URL, u as stripInternalEnvKeys, v as readWranglerCompat, x as SANDBOX_MIGRATION_TAG, y as resolveLiveBindingConfig } from "./deploy-CRIz77mw.mjs";
7
+ import { C as isSandboxEnabled, S as SANDBOX_MIGRATION_TAG, _ as normalizeWranglerCompatibilityFlags, a as prerenderPagesNode, b as resolveLiveBindingConfig, c as filterLoadedEnv, d as LIVE_MIGRATION_TAG, f as ensureWranglerCompat, g as nextDurableObjectMigrationTag, h as hasDurableObjectSqliteMigration, i as prerenderPages, l as resolveRemoteMode, m as ensureWranglerNodejsAlsFlag, n as resolveDistDir, o as DEFAULT_PROXY_URL, p as ensureWranglerCompatibilityDate, r as resolveWorkerDirName, s as STAGING_PROXY_URL, u as stripInternalEnvKeys, v as readExistingLiveBindingConfig, w as resolveSandboxConfig, x as syncWranglerBindings, y as readWranglerCompat } from "./deploy-B5rTuzXw.mjs";
8
8
  import { c as getDatabaseDialect, f as readConfig, l as isNodeTarget, p as resolveBindingNames } from "./config-BIa9HwVX.mjs";
9
- import { i as scanJobsSync, n as scanWebSocketRoutesSync, r as scanQueuesSync, t as scanRoutes } from "./scan-QtRTdh94.mjs";
10
- import { a as SSR_CLIENT_ENTRY_RELATIVE_PATHS, c as validateSsrEntries, f as isIdentifier, g as walk, i as inferProjectBindings, l as validateSsrEntry, m as isMemberExpression, n as FRAMEWORK_SCAN_DIRS, o as SSR_SERVER_ENTRY_RELATIVE_PATHS, p as isLiteral, r as detectFramework, t as DEFAULT_SCAN_DIRS, u as inferBindingsFromSource } from "./plugin-inference-CCtRkt9O.mjs";
9
+ import { i as scanJobsSync, n as scanWebSocketRoutesSync, r as scanQueuesSync, t as scanRoutes } from "./scan-vv5u7rHu.mjs";
10
+ import { a as SSR_CLIENT_ENTRY_RELATIVE_PATHS, c as validateSsrEntries, f as isIdentifier, g as walk, i as inferProjectBindings, l as validateSsrEntry, m as isMemberExpression, n as FRAMEWORK_SCAN_DIRS, o as SSR_SERVER_ENTRY_RELATIVE_PATHS, p as isLiteral, r as detectFramework, t as DEFAULT_SCAN_DIRS, u as inferBindingsFromSource } from "./plugin-inference-CXUuq0aC.mjs";
11
11
  import { i as voidWarn, n as voidError, r as voidLog, t as setShowTimestamp } from "./log-DXdqnmhF.mjs";
12
12
  import { r as parseDotenvFile } from "./dotenv-DwO4ti0Z.mjs";
13
13
  import { i as generateDbDts, n as generateQueueTypes, r as DRIZZLE_OPERATORS, t as generateRouteTypes } from "./route-types-DReF1gUY.mjs";
@@ -27,8 +27,374 @@ import { fileURLToPath, pathToFileURL } from "node:url";
27
27
  import { cloudflare } from "@cloudflare/vite-plugin";
28
28
  import { loadEnv, normalizePath, parseSync } from "vite";
29
29
  import { homedir } from "node:os";
30
- //#region src/plugin-dev-triggers-hint.ts
30
+ import { init, parse } from "es-module-lexer";
31
+ //#region src/pages/dev-css-assets.ts
31
32
  var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
33
+ const DEV_CSS_ASSET_MODULE_ID = "virtual:void-pages-dev-assets";
34
+ const DEV_CSS_ASSET_ENDPOINT = "/__void/dev/pages-css";
35
+ const DEV_CSS_ASSET_GUARD_HEADER = "X-Void-Dev-Asset-Request";
36
+ const DEV_CSS_ASSET_GUARD_VALUE = "pages-css";
37
+ const CSS_REQUEST_RE = /\.(?:css|scss|sass|less|styl|stylus|pcss|postcss)(?:$|[?#])/;
38
+ const STYLE_QUERY_RE = /[?&](?:vue|svelte|island-style)\b.*[?&]type=style\b|[?&]type=style\b/;
39
+ const CSS_BYPASS_RE = /[?&](?:raw|url|worker|sharedworker)\b/;
40
+ const INLINE_CSS_EXPORT_RE = /(?:export\s+default|__vite__css\s*=)\s*("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|`(?:[^`\\]|\\.)*`)/;
41
+ const VITE_DEV_ID_RE = /const\s+__vite__id\s*=\s*("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')/;
42
+ const SKIPPABLE_VIRTUAL_URL_RE = /^(?:\/@id\/__x00__)?virtual:void-client-(?:browser|worker)(?:$|[?#])/;
43
+ function splitQueryHash(value) {
44
+ const index = value.search(/[?#]/);
45
+ if (index === -1) return {
46
+ pathname: value,
47
+ suffix: ""
48
+ };
49
+ return {
50
+ pathname: value.slice(0, index),
51
+ suffix: value.slice(index)
52
+ };
53
+ }
54
+ function normalizeDevCssUrl(id, root) {
55
+ const normalized = normalizePath(id);
56
+ if (normalized.startsWith("/@id/")) return normalized;
57
+ if (normalized.startsWith("\0")) return "/@id/__x00__" + normalized.slice(1);
58
+ if (normalized.startsWith("virtual:")) return "/@id/__x00__" + normalized;
59
+ const { pathname, suffix } = splitQueryHash(normalized);
60
+ const normalizedRoot = normalizePath(root);
61
+ if (pathname === normalizedRoot || pathname.startsWith(normalizedRoot + "/")) return "/" + normalizePath(pathname.slice(normalizedRoot.length + 1)) + suffix;
62
+ if (pathname.startsWith("/@fs/") || pathname.startsWith("/@vite/") || pathname === "/@vite/client" || pathname.startsWith("/@react-refresh") || pathname.startsWith("/node_modules/.vite/")) return normalized;
63
+ if (pathname.startsWith("/")) {
64
+ const rootFirstSegment = normalizedRoot.split("/").filter(Boolean)[0];
65
+ if (rootFirstSegment && !pathname.startsWith(`/${rootFirstSegment}/`)) return normalized;
66
+ return "/@fs" + pathname + suffix;
67
+ }
68
+ return normalized;
69
+ }
70
+ function normalizeRequestUrl(url) {
71
+ return normalizePath(url).replace(/^\/@id\/__x00__/, "\0");
72
+ }
73
+ function toTransformRequestUrl(url) {
74
+ return normalizeRequestUrl(url);
75
+ }
76
+ function isCssRequest(url) {
77
+ return !CSS_BYPASS_RE.test(url) && (CSS_REQUEST_RE.test(url) || STYLE_QUERY_RE.test(url));
78
+ }
79
+ function isOptimizedDepUrl(url) {
80
+ return normalizePath(url).startsWith("/node_modules/.vite/deps/");
81
+ }
82
+ function isSkippableVirtualUrl(url) {
83
+ const normalized = normalizePath(url);
84
+ return SKIPPABLE_VIRTUAL_URL_RE.test(normalized) || normalized.charCodeAt(0) === 0 && /^virtual:void-client-(?:browser|worker)(?:$|[?#])/.test(normalized.slice(1));
85
+ }
86
+ function appendInlineQuery(url) {
87
+ const parsed = new URL(url, "http://void.local");
88
+ if (!parsed.searchParams.has("inline")) parsed.searchParams.append("inline", "");
89
+ return parsed.pathname + parsed.search + parsed.hash;
90
+ }
91
+ function extractInlineCss(code) {
92
+ const match = code.match(INLINE_CSS_EXPORT_RE);
93
+ if (!match) throw new Error("Unable to extract inline CSS from Vite transform output.");
94
+ const raw = match[1];
95
+ if (raw.startsWith("`")) throw new Error("Unexpected template literal inline CSS output.");
96
+ return JSON.parse(raw);
97
+ }
98
+ function extractViteDevId(code) {
99
+ const match = code.match(VITE_DEV_ID_RE);
100
+ if (!match) return;
101
+ return JSON.parse(match[1]);
102
+ }
103
+ function createOrderedEdgeStore(root) {
104
+ let version = 0;
105
+ const byKey = /* @__PURE__ */ new Map();
106
+ const aliasesForId = (id) => {
107
+ const normalized = normalizePath(id);
108
+ const aliases = new Set([normalized, normalizeDevCssUrl(normalized, root)]);
109
+ if (normalized.startsWith("/@id/__x00__")) aliases.add(normalized.replace("/@id/__x00__", "\0"));
110
+ return [...aliases];
111
+ };
112
+ return {
113
+ get version() {
114
+ return version;
115
+ },
116
+ set(importer, edges) {
117
+ version++;
118
+ for (const key of aliasesForId(importer)) byKey.set(key, edges);
119
+ },
120
+ deleteForId(id) {
121
+ let deleted = false;
122
+ for (const key of aliasesForId(id)) deleted = byKey.delete(key) || deleted;
123
+ if (deleted) version++;
124
+ },
125
+ getForNode(node) {
126
+ const keys = [node.url, node.id].filter((value) => typeof value === "string");
127
+ for (const key of keys) {
128
+ const direct = byKey.get(normalizePath(key));
129
+ if (direct) return direct;
130
+ const url = normalizeDevCssUrl(key, root);
131
+ const byUrl = byKey.get(url) ?? byKey.get(normalizeRequestUrl(url));
132
+ if (byUrl) return byUrl;
133
+ }
134
+ const staticUrls = node.staticImportedUrls;
135
+ return staticUrls ? [...staticUrls] : void 0;
136
+ }
137
+ };
138
+ }
139
+ var DevCssProvider = class {
140
+ cache = /* @__PURE__ */ new Map();
141
+ graphVersion = 0;
142
+ constructor(server, root, edgeStore) {
143
+ this.server = server;
144
+ this.root = root;
145
+ this.edgeStore = edgeStore;
146
+ }
147
+ invalidate() {
148
+ this.graphVersion++;
149
+ this.cache.clear();
150
+ }
151
+ async collect(rootPhases) {
152
+ const normalizedPhases = rootPhases.map((phase) => phase.map((root) => normalizeDevCssUrl(root, this.root)));
153
+ const cacheKey = JSON.stringify({
154
+ roots: normalizedPhases,
155
+ graphVersion: this.graphVersion,
156
+ edgeVersion: this.edgeStore.version
157
+ });
158
+ const cached = this.cache.get(cacheKey);
159
+ if (cached) return cached;
160
+ const environment = this.server.environments.client;
161
+ const graph = environment.moduleGraph;
162
+ const seen = /* @__PURE__ */ new Set();
163
+ const seenCssUrls = /* @__PURE__ */ new Set();
164
+ const cssUrls = [];
165
+ const cssViteDevIds = /* @__PURE__ */ new Map();
166
+ const addByUrl = async (rawUrl) => {
167
+ const url = normalizeDevCssUrl(rawUrl, this.root);
168
+ if (isOptimizedDepUrl(url)) return;
169
+ const requestUrl = toTransformRequestUrl(url);
170
+ let result;
171
+ try {
172
+ result = await environment.transformRequest(requestUrl);
173
+ } catch (error) {
174
+ if (!isSkippableVirtualUrl(url)) this.server.config.logger.warnOnce(`[void] Skipping dev CSS traversal for ${url}: ${error instanceof Error ? error.message : String(error)}`);
175
+ return;
176
+ }
177
+ const node = await graph.getModuleByUrl(url) ?? (requestUrl !== url ? await graph.getModuleByUrl(requestUrl) : void 0);
178
+ if (node) await visit(node, result?.code);
179
+ };
180
+ const visit = async (node, transformedCode) => {
181
+ if (seen.has(node)) return;
182
+ seen.add(node);
183
+ if (isCssRequest(node.url)) {
184
+ if (!seenCssUrls.has(node.url)) {
185
+ seenCssUrls.add(node.url);
186
+ cssUrls.push(node.url);
187
+ }
188
+ const viteDevId = transformedCode ? extractViteDevId(transformedCode) : void 0;
189
+ cssViteDevIds.set(node.url, viteDevId ?? node.id ?? node.url);
190
+ return;
191
+ }
192
+ if (isOptimizedDepUrl(node.url)) return;
193
+ const staticUrls = this.edgeStore.getForNode(node);
194
+ if (!staticUrls) {
195
+ this.server.config.logger.warnOnce(`[void] Missing ordered static import metadata for ${node.url}; skipping broad dev CSS traversal.`);
196
+ return;
197
+ }
198
+ for (const dep of staticUrls) await addByUrl(dep);
199
+ };
200
+ for (const roots of normalizedPhases) for (const root of roots) await addByUrl(root);
201
+ const assets = [];
202
+ for (const url of cssUrls) {
203
+ const inlineUrl = appendInlineQuery(url);
204
+ const result = await environment.transformRequest(inlineUrl);
205
+ if (!result) continue;
206
+ assets.push({
207
+ url,
208
+ id: cssViteDevIds.get(url) ?? url,
209
+ css: extractInlineCss(result.code)
210
+ });
211
+ }
212
+ this.cache.set(cacheKey, assets);
213
+ if (this.cache.size > 100) {
214
+ const oldest = this.cache.keys().next().value;
215
+ if (oldest) this.cache.delete(oldest);
216
+ }
217
+ return assets;
218
+ }
219
+ };
220
+ async function readJsonBody(req) {
221
+ const chunks = [];
222
+ for await (const chunk of req) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
223
+ if (chunks.length === 0) return {};
224
+ return JSON.parse(Buffer.concat(chunks).toString("utf-8"));
225
+ }
226
+ function getInternalDevOrigin(server) {
227
+ const address = server.httpServer?.address();
228
+ if (address && typeof address === "object") {
229
+ const protocol = server.config.server.https ? "https" : "http";
230
+ const rawHost = address.address === "::" || address.address === "0.0.0.0" ? "127.0.0.1" : address.address;
231
+ return `${protocol}://${rawHost.includes(":") ? `[${rawHost}]` : rawHost}:${address.port}`;
232
+ }
233
+ const localUrl = server.resolvedUrls?.local[0];
234
+ if (localUrl) return new URL(localUrl).origin;
235
+ return `${server.config.server.https ? "https" : "http"}://127.0.0.1:${server.config.server.port ?? 5173}`;
236
+ }
237
+ function pagesDevCssAssetsPlugin(root, token) {
238
+ const edgeStore = createOrderedEdgeStore(root);
239
+ let provider = null;
240
+ let viteServer = null;
241
+ return [{
242
+ name: "void:pages-dev-css-assets",
243
+ apply: "serve",
244
+ resolveId(id) {
245
+ if (id !== "virtual:void-pages-dev-assets") return;
246
+ if (this.environment?.name === "client") throw new Error(`${DEV_CSS_ASSET_MODULE_ID} is server-only and cannot be imported by client code.`);
247
+ return "\0" + DEV_CSS_ASSET_MODULE_ID;
248
+ },
249
+ load(id) {
250
+ if (id !== "\0virtual:void-pages-dev-assets") return;
251
+ if (this.environment?.name === "client") throw new Error(`${DEV_CSS_ASSET_MODULE_ID} is server-only and cannot be loaded by client code.`);
252
+ const internalOrigin = viteServer ? getInternalDevOrigin(viteServer) : "http://127.0.0.1:5173";
253
+ return `
254
+ const TOKEN = ${JSON.stringify(token)};
255
+ const INTERNAL_ORIGIN = ${JSON.stringify(internalOrigin)};
256
+ const ENDPOINT = ${JSON.stringify(DEV_CSS_ASSET_ENDPOINT)};
257
+ const GUARD_HEADER = ${JSON.stringify(DEV_CSS_ASSET_GUARD_HEADER)};
258
+ const GUARD_VALUE = ${JSON.stringify(DEV_CSS_ASSET_GUARD_VALUE)};
259
+
260
+ function createDevCssRequest(url, payload, signal) {
261
+ return new Request(url, {
262
+ method: "POST",
263
+ headers: {
264
+ "Authorization": "Bearer " + TOKEN,
265
+ "Content-Type": "application/json",
266
+ [GUARD_HEADER]: GUARD_VALUE,
267
+ },
268
+ body: JSON.stringify(payload),
269
+ signal,
270
+ });
271
+ }
272
+
273
+ async function readDevCssResponse(response) {
274
+ if (!response.ok) {
275
+ throw new Error("HTTP " + response.status);
276
+ }
277
+ const body = await response.json();
278
+ return Array.isArray(body.assets) ? body.assets : [];
279
+ }
280
+
281
+ export async function getVoidPagesDevCss(request, env, payload) {
282
+ const controller = new AbortController();
283
+ const timeout = setTimeout(() => controller.abort(), 1500);
284
+ const attempts = [];
285
+ if (env?.ASSETS && typeof env.ASSETS.fetch === "function") {
286
+ attempts.push({
287
+ fetcher: env.ASSETS,
288
+ label: "ASSETS",
289
+ url: new URL(ENDPOINT, request.url).toString(),
290
+ });
291
+ } else {
292
+ attempts.push({
293
+ fetcher: "global",
294
+ label: INTERNAL_ORIGIN,
295
+ url: new URL(ENDPOINT, INTERNAL_ORIGIN).toString(),
296
+ });
297
+ }
298
+ try {
299
+ let lastError;
300
+ let lastLabel = "unknown";
301
+ for (const attempt of attempts) {
302
+ try {
303
+ const request = createDevCssRequest(attempt.url, payload, controller.signal);
304
+ const response =
305
+ attempt.fetcher === "global"
306
+ ? await fetch(request)
307
+ : await attempt.fetcher.fetch(request);
308
+ return await readDevCssResponse(response);
309
+ } catch (error) {
310
+ lastError = error;
311
+ lastLabel = attempt.label;
312
+ }
313
+ }
314
+ throw new Error(
315
+ lastLabel + ": " + (lastError instanceof Error ? lastError.message : String(lastError)),
316
+ );
317
+ } catch (error) {
318
+ console.warn("[void] dev CSS collection failed:", error instanceof Error ? error.message : String(error));
319
+ return [];
320
+ } finally {
321
+ clearTimeout(timeout);
322
+ }
323
+ }
324
+ `;
325
+ },
326
+ configureServer(server) {
327
+ viteServer = server;
328
+ provider = new DevCssProvider(server, root, edgeStore);
329
+ const invalidate = () => provider?.invalidate();
330
+ server.watcher.on("add", invalidate);
331
+ server.watcher.on("change", invalidate);
332
+ server.watcher.on("unlink", invalidate);
333
+ server.middlewares.use(async (req, res, next) => {
334
+ if (!req.url) return next();
335
+ const url = new URL(req.url, "http://void.local");
336
+ if (url.pathname === "/@id/virtual:void-pages-dev-assets" || url.pathname === "/@id/__x00__virtual:void-pages-dev-assets") {
337
+ res.statusCode = 404;
338
+ res.end("Not Found");
339
+ return;
340
+ }
341
+ if (url.pathname !== "/__void/dev/pages-css") return next();
342
+ if (req.method !== "POST") {
343
+ res.statusCode = 405;
344
+ res.end("Method Not Allowed");
345
+ return;
346
+ }
347
+ if (req.headers["X-Void-Dev-Asset-Request".toLowerCase()] !== "pages-css") {
348
+ res.statusCode = 403;
349
+ res.end("Forbidden");
350
+ return;
351
+ }
352
+ if (req.headers.authorization !== `Bearer ${token}`) {
353
+ res.statusCode = 401;
354
+ res.end("Unauthorized");
355
+ return;
356
+ }
357
+ try {
358
+ const body = await readJsonBody(req);
359
+ const rootPhases = Array.isArray(body.rootPhases) ? body.rootPhases : [];
360
+ const assets = await provider.collect(rootPhases);
361
+ res.statusCode = 200;
362
+ res.setHeader("Content-Type", "application/json");
363
+ res.end(JSON.stringify({ assets }));
364
+ } catch (error) {
365
+ server.config.logger.warn(`[void] dev CSS collection failed: ${error instanceof Error ? error.message : String(error)}`);
366
+ res.statusCode = 200;
367
+ res.setHeader("Content-Type", "application/json");
368
+ res.end(JSON.stringify({ assets: [] }));
369
+ }
370
+ });
371
+ }
372
+ }, {
373
+ name: "void:pages-dev-css-static-edges",
374
+ apply: "serve",
375
+ enforce: "post",
376
+ async transform(code, id) {
377
+ if (this.environment?.name !== "client") return;
378
+ if (id.includes("/node_modules/.vite/")) return;
379
+ await init;
380
+ let imports;
381
+ try {
382
+ [imports] = parse(code);
383
+ } catch {
384
+ return;
385
+ }
386
+ const edges = [];
387
+ for (const item of imports) {
388
+ if (item.d !== -1 || !item.n) continue;
389
+ const resolved = await this.resolve(item.n, id, { skipSelf: true });
390
+ if (resolved?.id) edges.push(normalizeDevCssUrl(resolved.id, root));
391
+ }
392
+ edgeStore.set(id, edges);
393
+ }
394
+ }];
395
+ }
396
+ //#endregion
397
+ //#region src/plugin-dev-triggers-hint.ts
32
398
  /**
33
399
  * Prints a one-shot hint on dev server start when the project has crons
34
400
  * or queues, explaining how to trigger them locally. Both default Void mode
@@ -1953,6 +2319,16 @@ function pushDefaultErrorPageHelpers(lines, options) {
1953
2319
  lines.push(` return /<\\/body\\s*>/i.test(html) ? html.replace(/<\\/body\\s*>/i, overlay + "</body>") : html + overlay;`);
1954
2320
  lines.push(`}`);
1955
2321
  lines.push("");
2322
+ lines.push(`function __voidGetErrorAssetCss(error) {`);
2323
+ lines.push(` const tags = error && (typeof error === "object" || typeof error === "function") ? error.__voidPageAssetTags : null;`);
2324
+ lines.push(` return tags && typeof tags.css === "string" ? tags.css : "";`);
2325
+ lines.push(`}`);
2326
+ lines.push("");
2327
+ lines.push(`function __voidInjectErrorAssetCss(html, css) {`);
2328
+ lines.push(` if (!css) return html;`);
2329
+ lines.push(` return /<\\/head\\s*>/i.test(html) ? html.replace(/<\\/head\\s*>/i, css + "</head>") : css + html;`);
2330
+ lines.push(`}`);
2331
+ lines.push("");
1956
2332
  lines.push(`function __voidRenderErrorPage(request, status, title, error) {`);
1957
2333
  lines.push(` const heading = status + ": " + title;`);
1958
2334
  lines.push(` const prefix = status + ": ";`);
@@ -1963,6 +2339,7 @@ function pushDefaultErrorPageHelpers(lines, options) {
1963
2339
  lines.push(` <meta charset="utf-8">`);
1964
2340
  lines.push(` <meta name="viewport" content="width=device-width, initial-scale=1">`);
1965
2341
  lines.push(` <title>\${__voidEscapeHtml(heading)}</title>`);
2342
+ lines.push(` \${__voidGetErrorAssetCss(error)}`);
1966
2343
  lines.push(` <style>`);
1967
2344
  lines.push(` :root {`);
1968
2345
  lines.push(` color-scheme: light dark;`);
@@ -2615,6 +2992,7 @@ function compilePageRoutes(lines, scan, pages, options) {
2615
2992
  lines.push(`import { handlePageGet, handlePageMutation } from ${JSON.stringify(pages.protocolPath)};`);
2616
2993
  lines.push(`import { renderHeadToString, renderHtmlAttrs, renderBodyAttrs } from ${JSON.stringify(pages.headPath)};`);
2617
2994
  lines.push(`import { renderPage } from "virtual:void-pages-renderer";`);
2995
+ if (options.dev) lines.push(`import { getVoidPagesDevCss } from "virtual:void-pages-dev-assets";`);
2618
2996
  const hasIslandPages = scan.pages.pages.some((p) => p.island);
2619
2997
  if (hasIslandPages) lines.push(`import { renderIslandPage } from "virtual:void-islands-renderer";`);
2620
2998
  lines.push("");
@@ -2636,11 +3014,18 @@ function compilePageRoutes(lines, scan, pages, options) {
2636
3014
  lines.push(` return { css: "", preloads, body: bodyTag };`);
2637
3015
  lines.push(`}`);
2638
3016
  lines.push("");
3017
+ if (options.dev) {
3018
+ lines.push(`async function collectVoidDevCss(request, env, kind, componentId, rootPhases) {`);
3019
+ lines.push(` const devCss = await getVoidPagesDevCss(request, env, { kind, componentId, rootPhases });`);
3020
+ lines.push(` return Array.isArray(devCss) ? devCss : [];`);
3021
+ lines.push(`}`);
3022
+ lines.push("");
3023
+ }
2639
3024
  lines.push(`function collectPagesManifestFiles(manifest, entryId) {`);
2640
3025
  lines.push(` const seen = new Set();`);
2641
3026
  lines.push(` const toVisit = [entryId];`);
2642
- lines.push(` while (toVisit.length > 0) {`);
2643
- lines.push(` const currentId = toVisit.pop();`);
3027
+ lines.push(` for (let index = 0; index < toVisit.length; index++) {`);
3028
+ lines.push(` const currentId = toVisit[index];`);
2644
3029
  lines.push(` if (seen.has(currentId)) continue;`);
2645
3030
  lines.push(` seen.add(currentId);`);
2646
3031
  lines.push(` const chunk = manifest[currentId];`);
@@ -2652,56 +3037,58 @@ function compilePageRoutes(lines, scan, pages, options) {
2652
3037
  lines.push("");
2653
3038
  const relPagesDir = pages.pagesDirRelative;
2654
3039
  const pageCssKeys = {};
3040
+ const pageDevRootPhases = {};
3041
+ const projectRoot = options.projectRoot;
3042
+ const toDevRootUrl = (absolutePath) => "/" + absolutePath.replaceAll("\\", "/").slice(projectRoot.replaceAll("\\", "/").length + 1);
3043
+ const virtualDevUrl = (id) => "/@id/__x00__" + id;
2655
3044
  for (const page of scan.pages.pages) {
2656
- const keys = [`${relPagesDir}/${page.componentPath}`];
3045
+ const keys = [];
3046
+ const routeRootPhases = [[virtualDevUrl(page.island ? pages.islandClientEntryId ?? pages.clientEntryId : pages.clientEntryId)]];
3047
+ if (page.island && pages.mdClientEntryId) routeRootPhases[0].push(virtualDevUrl(pages.mdClientEntryId));
2657
3048
  const layoutIds = resolveLayoutIds(page, scan.pages.layouts, scan.pages.namedLayouts);
3049
+ const layoutRoots = [];
2658
3050
  for (const layoutId of layoutIds) {
2659
3051
  const layout = scan.pages.layouts.find((l) => (l.directory ? `${l.directory}/layout` : "layout") === layoutId);
2660
3052
  if (layout) {
2661
3053
  keys.push(`${relPagesDir}/${layout.filePath}`);
3054
+ layoutRoots.push(toDevRootUrl(`${pages.pagesDir}/${layout.filePath}`));
2662
3055
  continue;
2663
3056
  }
2664
3057
  const named = scan.pages.namedLayouts.find((nl) => {
2665
3058
  return (nl.directory ? `${nl.directory}/_layouts/${nl.name}` : `_layouts/${nl.name}`) === layoutId;
2666
3059
  });
2667
- if (named) keys.push(`${relPagesDir}/${named.filePath}`);
3060
+ if (named) {
3061
+ keys.push(`${relPagesDir}/${named.filePath}`);
3062
+ layoutRoots.push(toDevRootUrl(`${pages.pagesDir}/${named.filePath}`));
3063
+ }
2668
3064
  }
3065
+ keys.push(`${relPagesDir}/${page.componentPath}`);
3066
+ routeRootPhases.push(layoutRoots);
3067
+ routeRootPhases.push([toDevRootUrl(`${pages.pagesDir}/${page.componentPath}`)]);
2669
3068
  pageCssKeys[page.componentId] = keys;
3069
+ pageDevRootPhases[page.componentId] = routeRootPhases.filter((phase) => phase.length > 0);
2670
3070
  }
2671
3071
  lines.push(`const PAGE_CSS_KEYS = ${JSON.stringify(pageCssKeys)};`);
3072
+ if (options.dev) lines.push(`const PAGE_DEV_ROOT_PHASES = ${JSON.stringify(pageDevRootPhases)};`);
2672
3073
  lines.push("");
2673
3074
  lines.push(`function collectRouteCss(manifest, entryId, pageKeys) {`);
2674
3075
  lines.push(` const cssFiles = new Set();`);
2675
3076
  lines.push(` const visited = new Set();`);
2676
- lines.push(` const toVisit = [entryId];`);
2677
- lines.push(` while (toVisit.length > 0) {`);
2678
- lines.push(` const id = toVisit.pop();`);
2679
- lines.push(` if (visited.has(id)) continue;`);
3077
+ lines.push(` function visit(id) {`);
3078
+ lines.push(` if (visited.has(id)) return;`);
2680
3079
  lines.push(` visited.add(id);`);
2681
3080
  lines.push(` const chunk = manifest[id];`);
2682
- lines.push(` if (!chunk) continue;`);
3081
+ lines.push(` if (!chunk) return;`);
2683
3082
  lines.push(` if (Array.isArray(chunk.css)) {`);
2684
3083
  lines.push(` for (const f of chunk.css) cssFiles.add(f);`);
2685
3084
  lines.push(` }`);
2686
3085
  lines.push(` if (Array.isArray(chunk.imports)) {`);
2687
- lines.push(` for (const i of chunk.imports) toVisit.push(i);`);
3086
+ lines.push(` for (const i of chunk.imports) visit(i);`);
2688
3087
  lines.push(` }`);
2689
3088
  lines.push(` }`);
3089
+ lines.push(` visit(entryId);`);
2690
3090
  lines.push(` for (const key of pageKeys) {`);
2691
- lines.push(` const stack = [key];`);
2692
- lines.push(` while (stack.length > 0) {`);
2693
- lines.push(` const id = stack.pop();`);
2694
- lines.push(` if (visited.has(id)) continue;`);
2695
- lines.push(` visited.add(id);`);
2696
- lines.push(` const chunk = manifest[id];`);
2697
- lines.push(` if (!chunk) continue;`);
2698
- lines.push(` if (Array.isArray(chunk.css)) {`);
2699
- lines.push(` for (const f of chunk.css) cssFiles.add(f);`);
2700
- lines.push(` }`);
2701
- lines.push(` if (Array.isArray(chunk.imports)) {`);
2702
- lines.push(` for (const i of chunk.imports) stack.push(i);`);
2703
- lines.push(` }`);
2704
- lines.push(` }`);
3091
+ lines.push(` visit(key);`);
2705
3092
  lines.push(` }`);
2706
3093
  lines.push(` return cssFiles;`);
2707
3094
  lines.push(`}`);
@@ -2725,7 +3112,10 @@ function compilePageRoutes(lines, scan, pages, options) {
2725
3112
  lines.push(` const manifest = await loadPagesManifest(request, env);`);
2726
3113
  lines.push(` if (!manifest || typeof manifest !== "object") {`);
2727
3114
  lines.push(` if (!import.meta.env.DEV) return { css: "", preloads: "", body: "" };`);
2728
- lines.push(` return getPagesDevClientTags();`);
3115
+ if (options.dev) {
3116
+ lines.push(` const tags = getPagesDevClientTags();`);
3117
+ lines.push(` return { ...tags, devCss: await collectVoidDevCss(request, env, "pages", componentId, PAGE_DEV_ROOT_PHASES[componentId] || [[PAGES_CLIENT_ENTRY_URL]]) };`);
3118
+ } else lines.push(` return getPagesDevClientTags();`);
2729
3119
  lines.push(` }`);
2730
3120
  lines.push(` const entry = manifest[PAGES_CLIENT_ENTRY_ID];`);
2731
3121
  lines.push(` if (!entry || typeof entry !== "object" || typeof entry.file !== "string") {`);
@@ -2774,7 +3164,10 @@ function compilePageRoutes(lines, scan, pages, options) {
2774
3164
  lines.push(` const manifest = await loadPagesManifest(request, env);`);
2775
3165
  lines.push(` if (!manifest || typeof manifest !== "object") {`);
2776
3166
  lines.push(` if (!import.meta.env.DEV) return { css: "", preloads: "", body: "" };`);
2777
- lines.push(` return getIslandsDevClientTags();`);
3167
+ if (options.dev) {
3168
+ lines.push(` const tags = getIslandsDevClientTags();`);
3169
+ lines.push(` return { ...tags, devCss: await collectVoidDevCss(request, env, "islands", componentId, PAGE_DEV_ROOT_PHASES[componentId] || [[ISLANDS_CLIENT_ENTRY_URL]]) };`);
3170
+ } else lines.push(` return getIslandsDevClientTags();`);
2778
3171
  lines.push(` }`);
2779
3172
  lines.push(` const entry = manifest[ISLANDS_CLIENT_ENTRY_ID];`);
2780
3173
  lines.push(` if (!entry || typeof entry !== "object" || typeof entry.file !== "string") {`);
@@ -2896,6 +3289,15 @@ function compilePageRoutes(lines, scan, pages, options) {
2896
3289
  lines.push(` const errReq = new Request(new URL("/" + status + ".html", c.req.url));`);
2897
3290
  lines.push(` const errRes = await assets.fetch(errReq);`);
2898
3291
  lines.push(` if (errRes.ok) {`);
3292
+ lines.push(` const assetCss = __voidGetErrorAssetCss(error);`);
3293
+ lines.push(` if (assetCss) {`);
3294
+ lines.push(` const html = __voidInjectErrorAssetCss(await errRes.text(), assetCss);`);
3295
+ lines.push(` const body = __VOID_DEV && status === 500 && error && __voidShouldServeHtmlErrorPage(c.req.raw) ? __voidInjectDevErrorOverlay(html, __voidRenderDevErrorOverlay(c.req.raw, status, fallbackText, error)) : html;`);
3296
+ lines.push(` return new Response(c.req.method === "HEAD" ? null : body, {`);
3297
+ lines.push(` status,`);
3298
+ lines.push(` headers: { "content-type": "text/html; charset=utf-8" },`);
3299
+ lines.push(` });`);
3300
+ lines.push(` }`);
2899
3301
  lines.push(` if (__VOID_DEV && status === 500 && error && __voidShouldServeHtmlErrorPage(c.req.raw)) {`);
2900
3302
  lines.push(` const overlay = __voidRenderDevErrorOverlay(c.req.raw, status, fallbackText, error);`);
2901
3303
  lines.push(` const html = await errRes.text();`);
@@ -4138,6 +4540,23 @@ function createSandboxSdkResolvePlugin() {
4138
4540
  }
4139
4541
  };
4140
4542
  }
4543
+ function createWranglerCompatPersistPlugin(root, config) {
4544
+ let persisted = false;
4545
+ const persist = () => {
4546
+ if (persisted || isNodeTarget(config.target)) return;
4547
+ persisted = true;
4548
+ ensureWranglerCompat(root, config);
4549
+ };
4550
+ return {
4551
+ name: "void:wrangler-compat-persist",
4552
+ buildStart() {
4553
+ persist();
4554
+ },
4555
+ configureServer() {
4556
+ persist();
4557
+ }
4558
+ };
4559
+ }
4141
4560
  /**
4142
4561
  * Read Void auth credentials for local dev AI proxy access.
4143
4562
  * Returns a discriminated union so callers can distinguish
@@ -4307,8 +4726,8 @@ function voidPlugin(options) {
4307
4726
  if (detected && (detected.class === "b" || detected.class === "c")) {
4308
4727
  const bindingNames = resolveBindingNames(config.inference?.bindings);
4309
4728
  const frameworkPersistRoot = join(root, ".wrangler", "state");
4310
- const syncFrameworkCompat = () => {
4311
- if (ensureWranglerCompatibilityDate(root, readWranglerCompat(root, config).compatibilityDate)) voidLog("Synced compatibility_date to wrangler config");
4729
+ const syncFrameworkCompat = (compat) => {
4730
+ if (ensureWranglerCompatibilityDate(root, compat.compatibilityDate)) voidLog("Synced compatibility_date to wrangler config");
4312
4731
  };
4313
4732
  return [
4314
4733
  createCloudflareBuiltinsExternalPlugin(),
@@ -4316,15 +4735,21 @@ function voidPlugin(options) {
4316
4735
  name: "void:wrangler-compat",
4317
4736
  enforce: "pre",
4318
4737
  config(_, env) {
4319
- syncFrameworkCompat();
4738
+ syncFrameworkCompat(ensureWranglerCompat(root, config));
4320
4739
  if (env.command !== "serve") return;
4321
4740
  if (ensureWranglerNodejsAlsFlag(root)) voidLog("Synced nodejs_als to wrangler config");
4741
+ },
4742
+ buildStart() {
4743
+ syncFrameworkCompat(ensureWranglerCompat(root, config));
4744
+ },
4745
+ configureServer() {
4746
+ syncFrameworkCompat(ensureWranglerCompat(root, config));
4322
4747
  }
4323
4748
  },
4324
4749
  {
4325
4750
  name: "void:wrangler-sync",
4326
4751
  configResolved(resolvedConfig) {
4327
- syncFrameworkCompat();
4752
+ syncFrameworkCompat(readWranglerCompat(root, config));
4328
4753
  if (resolvedConfig.command !== "serve") return;
4329
4754
  if (syncWranglerBindings(root, bindings, {
4330
4755
  bindingNames,
@@ -4617,6 +5042,7 @@ function voidPlugin(options) {
4617
5042
  } : void 0;
4618
5043
  return [
4619
5044
  createCloudflareBuiltinsExternalPlugin(),
5045
+ createWranglerCompatPersistPlugin(root, config),
4620
5046
  restartPlugin(),
4621
5047
  bindingWatchPlugin,
4622
5048
  envPlugin,
@@ -4656,6 +5082,7 @@ function voidPlugin(options) {
4656
5082
  restartPlugin(),
4657
5083
  envPlugin,
4658
5084
  envSchemaPlugin(root),
5085
+ ...pagesDevCssAssetsPlugin(root, devTriggerToken),
4659
5086
  routingPlugin(root, {
4660
5087
  isAuthEnabled: () => false,
4661
5088
  devTriggerToken,
@@ -4686,6 +5113,7 @@ function voidPlugin(options) {
4686
5113
  return [
4687
5114
  createCloudflareBuiltinsExternalPlugin(),
4688
5115
  createDefaultWorkerEnvironmentPlugin(),
5116
+ createWranglerCompatPersistPlugin(root, config),
4689
5117
  restartPlugin(),
4690
5118
  bindingWatchPlugin,
4691
5119
  envPlugin,
@@ -4694,6 +5122,7 @@ function voidPlugin(options) {
4694
5122
  envClientFoldPlugin(),
4695
5123
  clientStubsPlugin,
4696
5124
  ...bindings.needsSandbox ? [createSandboxSdkResolvePlugin()] : [],
5125
+ ...pagesDevCssAssetsPlugin(root, devTriggerToken),
4697
5126
  routingPlugin(root, {
4698
5127
  isAuthEnabled: () => authEnabled,
4699
5128
  devTriggerToken,
@@ -4,7 +4,7 @@ import { _ as me, c as R, g as ge, i as Ee, u as Se, v as ue, x as q, y as ye }
4
4
  import { a as writeProjectConfig, r as readProjectConfig } from "./project-TqORyHn8.mjs";
5
5
  import { c as getToken, n as PlatformClient, u as isStagingMode } from "./client-DCqnMpDt.mjs";
6
6
  import { c as getDatabaseDialect, f as readConfig } from "./config-BIa9HwVX.mjs";
7
- import { r as detectFramework } from "./plugin-inference-CCtRkt9O.mjs";
7
+ import { r as detectFramework } from "./plugin-inference-CXUuq0aC.mjs";
8
8
  import { r as parseDotenvFile, t as expandDotenv } from "./dotenv-DwO4ti0Z.mjs";
9
9
  import { n as ensureProjectTsconfig, t as createProjectTsconfig } from "./project-tsconfig-DfkESbDL.mjs";
10
10
  import { t as MagicString } from "./magic-string.es-D6g9UnIy.mjs";
@@ -12,7 +12,7 @@ import { n as writeDrizzleConfig } from "./config-BzM9Dy7T.mjs";
12
12
  import { n as getAgentById, r as getPackageDir, t as detectAgents } from "./agents-DqkFfc2c.mjs";
13
13
  import { n as promptProjectSelection, t as promptAndCreateProject } from "./create-project-Bg88Kq_I.mjs";
14
14
  import { t as promptForLoginToken } from "./login-B5HHT32i.mjs";
15
- import { r as formatProjectCommand } from "./preset-jKn1hQwP.mjs";
15
+ import { r as formatProjectCommand } from "./preset-BhnZpb7t.mjs";
16
16
  import { n as findInstalledYarnPnpRuntime, r as hasLocalLockfile, t as buildDrizzleKitSpawnEnv } from "./yarn-pnp-6LD6_3Ej.mjs";
17
17
  import { createRequire } from "node:module";
18
18
  import { existsSync, mkdirSync, readFileSync, readdirSync, rmdirSync, unlinkSync, writeFileSync } from "node:fs";
@@ -1,4 +1,4 @@
1
- import { t as PageObject } from "../protocol-DxGzKEz2.mjs";
1
+ import { t as PageObject } from "../protocol-COz1NHxc.mjs";
2
2
  import { CacheForInput, CacheForResult } from "./prefetch.mjs";
3
3
 
4
4
  //#region src/pages/action-result.d.ts