void 1.2.0 → 1.3.0

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.
Files changed (169) hide show
  1. package/dist/{account-cmd-CdUll_35.mjs → account-cmd-B4i71m7k.mjs} +3 -3
  2. package/dist/{application-analysis-fEqoSeMp.mjs → application-analysis-DYdVoMAY.mjs} +8 -6
  3. package/dist/{application-routing-DAhNP4u3.mjs → application-routing-C8EqRDfv.mjs} +3 -1
  4. package/dist/{auth-link-C87vGXM-.mjs → auth-link-BKwHPbdv.mjs} +3 -3
  5. package/dist/{auth-router-6I81r-ix.mjs → auth-router-DqLx8E0F.mjs} +2 -2
  6. package/dist/{better-auth-shared-D-6z0q0f.mjs → better-auth-shared-7FM3Uk2N.mjs} +48 -2
  7. package/dist/{build-cmd-ex1g-j_e.mjs → build-cmd-Dy4psnt1.mjs} +1 -1
  8. package/dist/{cache-oHzrnY3z.mjs → cache-DV37S6dl.mjs} +1 -1
  9. package/dist/{cancel-deploy-viAMD0Q_.mjs → cancel-deploy-DMPyu1Vt.mjs} +1 -1
  10. package/dist/{cf-build-output-BhVxldCw.mjs → cf-build-output-Bapzc_8Z.mjs} +102 -1
  11. package/dist/cf-build-output-DlBkWdNU.mjs +1 -0
  12. package/dist/cli/cli.mjs +41 -32
  13. package/dist/cli/cloudflare-operation-process.mjs +27 -6
  14. package/dist/cli/env-schema-probe.mjs +2 -2
  15. package/dist/{client-BEkdj1kx.mjs → client-BEMtySaV.mjs} +8 -1
  16. package/dist/client-DyxPQnF_.mjs +1 -0
  17. package/dist/{cloudflare-cmd-DMzCv12s.mjs → cloudflare-cmd-BaqIigwI.mjs} +1 -1
  18. package/dist/{cloudflare-connect-CCRTVg-I.mjs → cloudflare-connect-pNLQmr_e.mjs} +1 -1
  19. package/dist/{cloudflare-operations-DsSaw2BT.mjs → cloudflare-operations-PCM4wucv.mjs} +1 -1
  20. package/dist/{cloudflare-operations-Dh9dEHJj.mjs → cloudflare-operations-vP3b5CQf.mjs} +3 -3
  21. package/dist/config-BTu1o3Dc.mjs +49 -0
  22. package/dist/{config-DQfHOKh9.d.mts → config-Du88-7Y8.d.mts} +2 -1
  23. package/dist/config-entry.d.mts +1 -1
  24. package/dist/{connect-k7R2rPVA.mjs → connect-DwVsBvVh.mjs} +4 -4
  25. package/dist/{create-project-DTuy-l0z.mjs → create-project-CgrnvzyA.mjs} +1 -1
  26. package/dist/{create-project-DV71ol5d.mjs → create-project-CjzbBlTv.mjs} +1 -1
  27. package/dist/{db-DVOkLH5X.mjs → db-rvo64snS.mjs} +13 -13
  28. package/dist/{delete-BbP5eopu.mjs → delete-DWX6dP4M.mjs} +1 -1
  29. package/dist/deploy-CtHE2A3R.mjs +2 -0
  30. package/dist/{deploy-7H32EnUs.mjs → deploy-hRPvw8ci.mjs} +229 -69
  31. package/dist/{deploy-managed-static-DlvcvnQT.mjs → deploy-managed-static-CDYA2p3L.mjs} +30 -14
  32. package/dist/{deploy-transport-BzGEj0Ge.mjs → deploy-transport-JCxw7QDi.mjs} +3 -3
  33. package/dist/deploy.mjs +4 -3
  34. package/dist/{dispatch-DoUnxTNo.mjs → dispatch-OVLeWW8K.mjs} +71 -2
  35. package/dist/{domain-CA2wBgra.mjs → domain-CH5iBD9Y.mjs} +2 -2
  36. package/dist/{email-DXpCc77w.mjs → email-CbTO1l78.mjs} +58 -9
  37. package/dist/{email-cloudflare-D03g2TkS.mjs → email-cloudflare-B8-pq_-W.mjs} +106 -5
  38. package/dist/{env-DgOQ9_8S.mjs → env-BBdw236G.mjs} +3 -3
  39. package/dist/{env-BJjULvL0.mjs → env-BaMz0j7H.mjs} +6 -1
  40. package/dist/{env-validation-BmsdCZEk.mjs → env-validation-BfBVvBNe.mjs} +1 -1
  41. package/dist/{env-validation-Dwq3PJzK.mjs → env-validation-XcukUlFM.mjs} +1 -1
  42. package/dist/{gen-BfmcIi2g.mjs → gen-CCx3t2Ju.mjs} +1 -1
  43. package/dist/gen-TgXy93Rr.mjs +1 -0
  44. package/dist/{github-cmd-CY9LUqLh.mjs → github-cmd-BzkRLkbg.mjs} +1 -1
  45. package/dist/{handler-BbkSPzGF.d.mts → handler-CQv5YDS0.d.mts} +1 -1
  46. package/dist/{help-CxSlPpzJ.mjs → help-CKbrhZha.mjs} +16 -1
  47. package/dist/help-qOZr3wng.mjs +1 -0
  48. package/dist/index.d.mts +2 -4
  49. package/dist/index.mjs +317 -122
  50. package/dist/{info-7VDlhtyy.mjs → info-oBm8yK8J.mjs} +2 -2
  51. package/dist/{init-DxYyOs4-.mjs → init-CBp_uMve.mjs} +217 -197
  52. package/dist/{link-Ddmod1dZ.mjs → link-Dt_QXmM4.mjs} +2 -2
  53. package/dist/{list-MogaugiO.mjs → list-DF6asTdt.mjs} +2 -2
  54. package/dist/{live-Bt8Y_0bg.d.mts → live-CXJ9yC98.d.mts} +1 -1
  55. package/dist/{local-d1-BHBnKWRb.mjs → local-d1-CUhH3qtj.mjs} +1 -1
  56. package/dist/{login-Cttnagmm.mjs → login-BjSyhXlT.mjs} +2 -2
  57. package/dist/login-Cdo8Aco1.mjs +1 -0
  58. package/dist/{logs-CAszUWZI.mjs → logs-DmvBl6xA.mjs} +2 -2
  59. package/dist/{migrate-DyT2jJ8y.mjs → migrate-BXRHpYwR.mjs} +1 -1
  60. package/dist/migrate-COPncCGx.mjs +1 -0
  61. package/dist/nitro.mjs +2 -2
  62. package/dist/{node-WB7c2N4L.mjs → node-DtD7ZiPf.mjs} +4 -4
  63. package/dist/{operator-args-UnE8Y2eK.mjs → operator-args-BsJIYXaT.mjs} +8 -1
  64. package/dist/operator-cmd-DDiX7Y3f.mjs +1 -0
  65. package/dist/{operator-cmd-skshjMGl.mjs → operator-cmd-DjZKGGgN.mjs} +4 -3
  66. package/dist/pages/client.d.mts +21 -4
  67. package/dist/pages/client.mjs +174 -35
  68. package/dist/pages/index.d.mts +18 -2
  69. package/dist/pages/index.mjs +2 -52
  70. package/dist/pages/islands-plugin.d.mts +1 -1
  71. package/dist/pages/islands-plugin.mjs +9 -3
  72. package/dist/pages/protocol.d.mts +2 -2
  73. package/dist/platform-args-BC8_hsDj.mjs +1 -0
  74. package/dist/{platform-args-DVbVClZl.mjs → platform-args-BMD2gjc_.mjs} +1 -1
  75. package/dist/{platform-auth-config-C-pm5Qzx.mjs → platform-auth-config-BgnuMbml.mjs} +3 -3
  76. package/dist/{platform-auth-protection-SHhvim1L.mjs → platform-auth-protection-NjRejttU.mjs} +2 -2
  77. package/dist/{platform-auth-recovery-DXVWs-wA.mjs → platform-auth-recovery-Ug12d9W5.mjs} +2 -2
  78. package/dist/{platform-cmd-PiNRkopU.mjs → platform-cmd-BYKLMPCn.mjs} +1 -1
  79. package/dist/{platform-cmd-D5I1beUX.mjs → platform-cmd-HByuZAO7.mjs} +4 -4
  80. package/dist/{platform-domain-jpmBfZeb.mjs → platform-domain-DLSQ8GF8.mjs} +2 -2
  81. package/dist/{platform-lifecycle-DyKmuNY6.mjs → platform-lifecycle-3dwFJmnq.mjs} +102 -40
  82. package/dist/{platform-lifecycle-DH3Yr1qQ.mjs → platform-lifecycle-BRqcxerG.mjs} +1 -1
  83. package/dist/{platform-management-7m-PLaPJ.mjs → platform-management-ZK6XcbCo.mjs} +1 -1
  84. package/dist/{platform-management--vDwSn35.mjs → platform-management-ZZ6bQM5j.mjs} +1 -1
  85. package/dist/{platform-recovery-BiNpZZab.mjs → platform-recovery-8vNE5dNN.mjs} +2 -2
  86. package/dist/{plugin-inference-DUjCd55H.mjs → plugin-inference-CeiB6BG5.mjs} +53 -18
  87. package/dist/{prepare-BcAE5Sdj.mjs → prepare-5BR7Splm.mjs} +1 -1
  88. package/dist/prepare-B3VrSF1Z.mjs +1 -0
  89. package/dist/{prepare-DA-17DhO.mjs → prepare-Dseww74N.mjs} +4 -4
  90. package/dist/{prerender-render-Cijv7UFo.mjs → prerender-render-CaShbHJ3.mjs} +13 -1
  91. package/dist/prerender-render.d.mts +1 -0
  92. package/dist/prerender-render.mjs +1 -1
  93. package/dist/{project-cmd-DA4K5faU.mjs → project-cmd-CjLNNxwe.mjs} +15 -15
  94. package/dist/{project-team-CQBNveX3.mjs → project-team-DE5drjcl.mjs} +1 -1
  95. package/dist/{project-token-CCalFyQf.mjs → project-token-XEYEXfiJ.mjs} +1 -1
  96. package/dist/{project-zero-trust-DPnkiEuT.mjs → project-zero-trust-6VPU8zmV.mjs} +1 -1
  97. package/dist/{protocol-BBDpJz3G.d.mts → protocol-BekmFxCI.d.mts} +2 -2
  98. package/dist/{provision-DtROpNNI.mjs → provision-B7UFrBH7.mjs} +1 -1
  99. package/dist/{provision-BFLCrnUp.mjs → provision-Chq0NRAV.mjs} +1 -1
  100. package/dist/{requests-BpH0kImL.mjs → requests-CG-Pj8ze.mjs} +1 -1
  101. package/dist/{rollback-CXS1tAa-.mjs → rollback-CIrm2txZ.mjs} +2 -2
  102. package/dist/{route-types-BZi26DVS.mjs → route-types--PAOzHlH.mjs} +49 -28
  103. package/dist/routes-stub.d.mts +22 -13
  104. package/dist/runtime/better-auth-mysql.mjs +1 -1
  105. package/dist/runtime/better-auth-pg.mjs +1 -1
  106. package/dist/runtime/better-auth.mjs +1 -1
  107. package/dist/runtime/handler.d.mts +1 -1
  108. package/dist/runtime/live-client.d.mts +1 -1
  109. package/dist/runtime/live.d.mts +1 -1
  110. package/dist/runtime/log.mjs +19 -1
  111. package/dist/runtime/routing.d.mts +2 -2
  112. package/dist/runtime/routing.mjs +4 -3
  113. package/dist/runtime/validator.d.mts +1 -1
  114. package/dist/runtime/ws-server.d.mts +1 -1
  115. package/dist/runtime/ws.d.mts +1 -1
  116. package/dist/{scan-8IzYXiU_.mjs → scan-N9WzdcAl.mjs} +302 -23
  117. package/dist/{secret-BbXHfLAt.mjs → secret-BL6g7mF5.mjs} +3 -3
  118. package/dist/static-asset-marker-Btf-6oCD.mjs +32 -0
  119. package/dist/{types-7AIz0OZu.d.mts → types-w72dljaA.d.mts} +6 -1
  120. package/dist/{version-metadata-tS39iW09.mjs → version-metadata-DmaZNTYW.mjs} +1 -1
  121. package/dist/worker-conditions-AWFRcFxR.mjs +11 -0
  122. package/dist/{wrangler-F96NnLyb.mjs → wrangler-CDiEBCdS.mjs} +2 -1
  123. package/dist/wrangler-DOPr4jyI.mjs +1 -0
  124. package/dist/{wrapper-D3sZyh2C.mjs → wrapper-CEiDeCqD.mjs} +6 -10
  125. package/dist/{ws-BH-im_tX.d.mts → ws-D1zWiB_P.d.mts} +1 -1
  126. package/docs/guide/auth.md +3 -1
  127. package/docs/guide/edge/static-assets.md +10 -0
  128. package/docs/guide/email/domains.md +1 -1
  129. package/docs/guide/email/receiving.md +2 -0
  130. package/docs/guide/email/sending.md +1 -1
  131. package/docs/guide/pages-routing/actions-and-forms.md +19 -13
  132. package/docs/guide/pages-routing/markdown.md +2 -0
  133. package/docs/guide/pages-routing/overview.md +34 -3
  134. package/docs/guide/platform/administration/email.md +18 -0
  135. package/docs/guide/platform/installation/prerequisites.md +9 -4
  136. package/docs/guide/platform/installation/uninstall.md +2 -0
  137. package/docs/guide/queues.md +13 -1
  138. package/docs/guide/quickstart.md +26 -1
  139. package/docs/guide/sandboxes.md +2 -2
  140. package/docs/guide/server-routing.md +38 -2
  141. package/docs/guide/type-safety.md +7 -7
  142. package/docs/guide/websockets.md +4 -2
  143. package/docs/reference/api/pages.md +4 -4
  144. package/docs/reference/cli/email.md +13 -0
  145. package/docs/reference/cli/platform-email.md +2 -2
  146. package/docs/reference/cli.md +2 -1
  147. package/docs/reference/structure.md +3 -1
  148. package/package.json +8 -7
  149. package/sandbox.Dockerfile +1 -1
  150. package/templates/assets/icons.svg +49 -0
  151. package/templates/assets/react.svg +1 -0
  152. package/templates/assets/solid.svg +1 -0
  153. package/templates/assets/stack.svg +35 -0
  154. package/templates/assets/svelte.svg +1 -0
  155. package/templates/assets/void.svg +5 -0
  156. package/templates/assets/vue.svg +1 -0
  157. package/dist/cf-build-output-BJHuSsVN.mjs +0 -1
  158. package/dist/client-BiRDZTSd.mjs +0 -1
  159. package/dist/config-CyUJzi3q.mjs +0 -32
  160. package/dist/deploy-CE0Ev0Ob.mjs +0 -2
  161. package/dist/gen-NrOlWZaG.mjs +0 -1
  162. package/dist/help-BeAFFE5C.mjs +0 -1
  163. package/dist/login-DgDwlKc_.mjs +0 -1
  164. package/dist/migrate-n49ZeS1X.mjs +0 -1
  165. package/dist/operator-cmd-d2MvJOrl.mjs +0 -1
  166. package/dist/parse-filename-DioPHiR9.mjs +0 -77
  167. package/dist/platform-args-kQrgxScY.mjs +0 -1
  168. package/dist/prepare-C4I0f--h.mjs +0 -1
  169. package/dist/wrangler-BLb3_luP.mjs +0 -1
@@ -1,4 +1,22 @@
1
1
  //#region src/runtime/log.ts
2
+ function errorReplacer() {
3
+ const seen = /* @__PURE__ */ new WeakSet();
4
+ return (_key, value) => {
5
+ if (!(value instanceof Error)) return value;
6
+ if (seen.has(value)) return {
7
+ name: value.name,
8
+ message: value.message
9
+ };
10
+ seen.add(value);
11
+ return {
12
+ ...value,
13
+ name: value.name,
14
+ message: value.message,
15
+ stack: value.stack,
16
+ cause: value.cause
17
+ };
18
+ };
19
+ }
2
20
  function format(message, fields) {
3
21
  try {
4
22
  const payload = Object.create(null);
@@ -8,7 +26,7 @@ function format(message, fields) {
8
26
  if (typeof value === "function") continue;
9
27
  payload[key] = value;
10
28
  }
11
- return JSON.stringify(payload);
29
+ return JSON.stringify(payload, errorReplacer());
12
30
  } catch {
13
31
  return JSON.stringify({
14
32
  msg: message,
@@ -1,5 +1,5 @@
1
- import { A as filterInternalBindings, M as createClientAssetTags, N as createManifestLoader, O as createAssetFallback, j as ClientAssetTags, k as createWorkerFetch } from "../handler-BbkSPzGF.mjs";
2
- import { a as handlePageMutation, i as handlePageGet } from "../protocol-BBDpJz3G.mjs";
1
+ import { A as filterInternalBindings, M as createClientAssetTags, N as createManifestLoader, O as createAssetFallback, j as ClientAssetTags, k as createWorkerFetch } from "../handler-CQv5YDS0.mjs";
2
+ import { a as handlePageMutation, i as handlePageGet } from "../protocol-BekmFxCI.mjs";
3
3
  import { AsyncLocalStorage } from "node:async_hooks";
4
4
  import { Context, Hono, MiddlewareHandler } from "hono";
5
5
  //#region src/runtime/routing-errors.d.ts
@@ -3,6 +3,7 @@ import { t as convertReturnValue } from "../response-Tn7rU0MV.mjs";
3
3
  import { i as searchWithoutActionKey, n as hasActionKey, r as markActionKey, t as actionKeySegment } from "../action-key-XZ9HkWAO.mjs";
4
4
  import { n as handlePageGet, r as handlePageMutation } from "../protocol-DimNxVRr.mjs";
5
5
  import { t as VoidAssetRewriteError } from "../handler-BZ1t7-Rv.mjs";
6
+ import { n as markStaticAsset } from "../static-asset-marker-Btf-6oCD.mjs";
6
7
  import { AsyncLocalStorage } from "node:async_hooks";
7
8
  import { compilePattern, matchPattern, matchPatternCaptures, mergeQueryIntoLocation, substituteParams } from "@void/edge";
8
9
  //#region src/runtime/routing-worker.ts
@@ -189,7 +190,7 @@ function createPagesFallback(options) {
189
190
  if (path === "/api" || path.startsWith("/api/") || c.req.method !== "GET" && c.req.method !== "HEAD") return c.text("Not Found", 404);
190
191
  const assets = c.env?.ASSETS;
191
192
  const assetResponse = assets && typeof assets.fetch === "function" ? await assets.fetch(c.req.raw) : options.routing.markNoMatch(c.req.raw, new Response("Not Found", { status: 404 }));
192
- if (assetResponse.status !== 404) return cachePolicy(c.req.raw, c.env, assetResponse);
193
+ if (assetResponse.status !== 404) return markStaticAsset(c, await cachePolicy(c.req.raw, c.env, assetResponse));
193
194
  const fallback = options.fallbackRules ? await options.routing.applyFallback(c, options.fallbackRules) : void 0;
194
195
  if (fallback) return fallback;
195
196
  if (path.includes("/.") || path.substring(path.lastIndexOf("/") + 1).includes(".")) return options.errors.serveCustomPage(c, 404, "Not Found");
@@ -207,7 +208,7 @@ function createSsrFallback(options) {
207
208
  const binding = c.env?.ASSETS;
208
209
  if (!binding || typeof binding.fetch !== "function") return options.routing.markNoMatch(c.req.raw, new Response("Not Found", { status: 404 }));
209
210
  const response = await binding.fetch(c.req.raw);
210
- return response.status === 404 ? options.routing.markNoMatch(c.req.raw, new Response("Not Found", { status: 404 })) : cachePolicy(c.req.raw, c.env, response);
211
+ return response.status === 404 ? options.routing.markNoMatch(c.req.raw, new Response("Not Found", { status: 404 })) : markStaticAsset(c, await cachePolicy(c.req.raw, c.env, response));
211
212
  };
212
213
  return async (c) => {
213
214
  if (options.nodeTarget && options.fallbackRules) {
@@ -237,7 +238,7 @@ function createAssetNotFound(options) {
237
238
  const assets = c.env?.ASSETS;
238
239
  if (assets && typeof assets.fetch === "function") {
239
240
  const response = await assets.fetch(c.req.raw);
240
- if (response.status !== 404) return cachePolicy(c.req.raw, c.env, response);
241
+ if (response.status !== 404) return markStaticAsset(c, await cachePolicy(c.req.raw, c.env, response));
241
242
  }
242
243
  }
243
244
  return (options.fallbackRules ? await options.routing.applyFallback(c, options.fallbackRules) : void 0) ?? options.routing.markNoMatch(c.req.raw, new Response("Not Found", { status: 404 }));
@@ -1,2 +1,2 @@
1
- import { D as runValidation, E as ValidatorSlots, T as HandlerInput } from "../handler-BbkSPzGF.mjs";
1
+ import { D as runValidation, E as ValidatorSlots, T as HandlerInput } from "../handler-CQv5YDS0.mjs";
2
2
  export { HandlerInput, ValidatorSlots, runValidation };
@@ -1,6 +1,6 @@
1
1
  import { n as AuthState } from "../auth-DkcFflXV.mjs";
2
2
  import { r as VoidAuthRuntimeOptions, t as VoidAuthEnv } from "../better-auth-shared-DVk2DkTW.mjs";
3
- import { f as WebSocketInstanceKey, t as AnyWebSocketDefinition } from "../ws-BH-im_tX.mjs";
3
+ import { f as WebSocketInstanceKey, t as AnyWebSocketDefinition } from "../ws-D1zWiB_P.mjs";
4
4
  //#region src/runtime/ws-server.d.ts
5
5
  export type WebSocketRouteMeta = {
6
6
  name?: string;
@@ -1,2 +1,2 @@
1
- import { a as RoomDefinition, c as VoidSocket, d as WebSocketConnection, f as WebSocketInstanceKey, h as defineWebSocket, i as RoomController, l as VoidSocketCloseEvent, m as defineRoom, n as ConnectCommonOptions, o as SocketContext, p as connect, r as RoomContext, s as SocketDefinition, t as AnyWebSocketDefinition, u as WebSocketBaseContext } from "../ws-BH-im_tX.mjs";
1
+ import { a as RoomDefinition, c as VoidSocket, d as WebSocketConnection, f as WebSocketInstanceKey, h as defineWebSocket, i as RoomController, l as VoidSocketCloseEvent, m as defineRoom, n as ConnectCommonOptions, o as SocketContext, p as connect, r as RoomContext, s as SocketDefinition, t as AnyWebSocketDefinition, u as WebSocketBaseContext } from "../ws-D1zWiB_P.mjs";
2
2
  export { AnyWebSocketDefinition, ConnectCommonOptions, RoomContext, RoomController, RoomDefinition, SocketContext, SocketDefinition, VoidSocket, VoidSocketCloseEvent, WebSocketBaseContext, WebSocketConnection, WebSocketInstanceKey, connect, defineRoom, defineWebSocket };
@@ -1,13 +1,136 @@
1
- import { a as join, n as dirname, r as extname, t as basename } from "./dist-ipQi0Q8y.mjs";
1
+ import { a as join, l as toSlash, n as dirname, r as extname, t as basename } from "./dist-ipQi0Q8y.mjs";
2
2
  import { n as readProjectPaths } from "./project-paths-DGu_QZ_Q.mjs";
3
3
  import { t as glob } from "./dist-D15hFhP0.mjs";
4
4
  import { n as isIdentifier, o as moduleExportName, r as isLiteral } from "./ast-CsZ_q_gc.mjs";
5
5
  import { a as staticLiteral, i as staticExportInitializers, t as bindingNames } from "./ast-bindings-C3yaPs1y.mjs";
6
- import { n as parseRouteFilename } from "./parse-filename-DioPHiR9.mjs";
7
6
  import { i as voidWarn } from "./log-BMwmN5Ae.mjs";
8
7
  import { t as MagicString } from "./dist-Cegxq8gs.mjs";
9
- import { existsSync, readFileSync } from "node:fs";
8
+ import { existsSync, readFileSync, statSync } from "node:fs";
10
9
  import { parseSync } from "vite";
10
+ //#region src/shared/route-extensions.ts
11
+ const ROUTE_EXTENSIONS = [
12
+ "ts",
13
+ "tsx",
14
+ "js",
15
+ "jsx",
16
+ "mjs",
17
+ "mts"
18
+ ];
19
+ const ROUTE_EXTENSIONS_SET = new Set(ROUTE_EXTENSIONS.map((ext) => `.${ext}`));
20
+ //#endregion
21
+ //#region src/router/parse-filename.ts
22
+ const ENV_SUFFIXES = ["dev", "prod"];
23
+ function parsePath(relativePath, isWebSocketRoute) {
24
+ const filePath = relativePath;
25
+ let path = relativePath.replace(/\\/g, "/");
26
+ for (const ext of ROUTE_EXTENSIONS) if (path.endsWith(`.${ext}`)) {
27
+ path = path.slice(0, -(ext.length + 1));
28
+ break;
29
+ }
30
+ if (isWebSocketRoute && path.endsWith(".ws")) path = path.slice(0, -3);
31
+ const segments = path.split("/");
32
+ let filename = segments.pop();
33
+ let env = null;
34
+ for (const suffix of ENV_SUFFIXES) if (filename.endsWith(`.${suffix}`)) {
35
+ env = suffix;
36
+ filename = filename.slice(0, -(suffix.length + 1));
37
+ break;
38
+ }
39
+ segments.push(filename);
40
+ if (segments[segments.length - 1] === "index") segments.pop();
41
+ const filtered = segments.filter((s) => !s.startsWith("(") || !s.endsWith(")"));
42
+ const params = [];
43
+ let catchAll = false;
44
+ return {
45
+ pattern: "/" + filtered.map((segment) => {
46
+ if (segment.startsWith("[...") && segment.endsWith("]")) {
47
+ const paramName = segment.slice(4, -1);
48
+ catchAll = true;
49
+ if (paramName) {
50
+ params.push(paramName);
51
+ return `:${paramName}{.+}`;
52
+ }
53
+ return "*";
54
+ }
55
+ if (segment.startsWith("[") && segment.endsWith("]")) {
56
+ const paramName = segment.slice(1, -1);
57
+ params.push(paramName);
58
+ return `:${paramName}`;
59
+ }
60
+ return segment;
61
+ }).join("/"),
62
+ methods: [],
63
+ params,
64
+ catchAll,
65
+ env,
66
+ filePath
67
+ };
68
+ }
69
+ /**
70
+ * Parse a route filename (relative to routes/) into a RouteDefinition.
71
+ *
72
+ * Rules (applied in order):
73
+ * 1. Strip file extension (.ts, .tsx, .js, .jsx, .mts, .mjs)
74
+ * 2. Check for env suffix (.dev, .prod) → strip and record
75
+ * 3. Strip trailing "index" segment
76
+ * 4. Remove route group directories: (groupname)
77
+ * 5. Convert [param] → :param, [...param] → :param{.+}, [...] → *
78
+ * 6. Prefix with /
79
+ */
80
+ function parseRouteFilename(relativePath) {
81
+ return parsePath(relativePath, false);
82
+ }
83
+ /** Parse a `.ws.*` route filename into a regular route definition. */
84
+ function parseWebSocketFilename(relativePath) {
85
+ return parsePath(relativePath, true);
86
+ }
87
+ function isRouteEnabledForEnvironment(route, environment) {
88
+ return environment === void 0 || route.env === null || route.env === environment;
89
+ }
90
+ //#endregion
91
+ //#region src/shared/source-analysis-cache.ts
92
+ /**
93
+ * How long after a file changes its stat is trusted to identify its contents.
94
+ * Some file systems keep coarse timestamps (FAT: 2 s, HFS+: 1 s, ext4: one
95
+ * kernel tick) and Linux reuses inodes, so a second write inside that window
96
+ * can leave the signature unchanged. Like Git's racily clean index entries,
97
+ * values derived from recently changed files are recomputed on the next read.
98
+ */
99
+ const RACY_WINDOW_MS = 3e3;
100
+ const entries = /* @__PURE__ */ new Map();
101
+ /**
102
+ * Derive a value from a source file, reusing it while the file is unchanged.
103
+ * A dev server rescans every source file on each file event, and several
104
+ * plugins scan the same pages, but only edited files need to be read and
105
+ * parsed again. `kind` separates analyses of the same file. `derive` must be a
106
+ * pure function of the source, and callers must not mutate its result.
107
+ */
108
+ function deriveFromSource(path, kind, derive) {
109
+ const key = toSlash(path);
110
+ const stat = statSync(key, {
111
+ bigint: true,
112
+ throwIfNoEntry: false
113
+ });
114
+ if (!stat) return derive(readFileSync(key, "utf-8"));
115
+ const signature = `${stat.ino}:${stat.size}:${stat.mtimeNs}:${stat.ctimeNs}`;
116
+ const changedAt = Number((stat.mtimeNs > stat.ctimeNs ? stat.mtimeNs : stat.ctimeNs) / 1000000n);
117
+ const trusted = Date.now() - changedAt > RACY_WINDOW_MS;
118
+ const entry = entries.get(key);
119
+ if (trusted && entry?.signature === signature && entry.derived.has(kind)) return entry.derived.get(kind);
120
+ const value = derive(readFileSync(key, "utf-8"));
121
+ if (!trusted) entries.delete(key);
122
+ else if (entry?.signature === signature) entry.derived.set(kind, value);
123
+ else entries.set(key, {
124
+ signature,
125
+ derived: /* @__PURE__ */ new Map([[kind, value]])
126
+ });
127
+ return value;
128
+ }
129
+ /** Forget values derived from a file. Dev servers call this for watcher events. */
130
+ function invalidateSourceAnalysis(path) {
131
+ entries.delete(toSlash(path));
132
+ }
133
+ //#endregion
11
134
  //#region src/pages/island-imports.ts
12
135
  /** The whole JS/TS module, or each `<script>` block of a Vue/Svelte SFC with its offset in the file. */
13
136
  function scriptBlocks(code, filename) {
@@ -150,6 +273,99 @@ function resolveLayoutIds(page, layouts, namedLayouts) {
150
273
  return resolveEffectiveLayoutEntries(page, layouts, namedLayouts).map((layout) => layout.id);
151
274
  }
152
275
  //#endregion
276
+ //#region src/pages/manifest.ts
277
+ /**
278
+ * Generates the component import map and layout tree as code strings.
279
+ * Used by both SSR renderer and client entry virtual modules.
280
+ *
281
+ * Client entries load this eagerly, so it grows with every page. Each page id
282
+ * is written once, identical layout chains are shared, and static routes are
283
+ * matched by exact lookup instead of a RegExp per page. The emitted bindings
284
+ * (`components`, `layoutTree`, `routeMeta`, `matchRoute`) keep their shape;
285
+ * `matchRoute` takes a decoded pathname (see `decodePagePath`).
286
+ */
287
+ function generateComponentManifest(scan, pagesDir) {
288
+ const load = (filePath) => `() => import(${JSON.stringify(`${pagesDir}/${filePath}`)})`;
289
+ const pageIds = new Set(scan.pages.map((page) => page.componentId));
290
+ const layoutKey = (id) => {
291
+ if (!pageIds.has(id)) return id;
292
+ const slash = id.lastIndexOf("/");
293
+ return id.slice(0, slash + 1) + "_" + id.slice(slash + 1);
294
+ };
295
+ const chains = [];
296
+ const chainIndexes = /* @__PURE__ */ new Map();
297
+ const staticRows = [];
298
+ const dynamicRows = [];
299
+ let inStaticPrefix = true;
300
+ for (const page of scan.pages) {
301
+ const chain = JSON.stringify(resolveLayoutIds(page, scan.layouts, scan.namedLayouts).map(layoutKey));
302
+ let chainIndex = chain === "[]" ? -1 : chainIndexes.get(chain);
303
+ if (chainIndex === void 0) {
304
+ chainIndex = chains.push(chain) - 1;
305
+ chainIndexes.set(chain, chainIndex);
306
+ }
307
+ const id = JSON.stringify(page.componentId);
308
+ inStaticPrefix &&= isStaticPattern(page.pattern);
309
+ if (inStaticPrefix) {
310
+ const pattern = page.pattern === `/${page.componentId}` ? "" : `, ${JSON.stringify(page.pattern)}`;
311
+ staticRows.push(` [${id}, ${load(page.componentPath)}, ${chainIndex}${pattern}],`);
312
+ } else dynamicRows.push(` [${patternToRegex(page.pattern)}, ${id}, ${load(page.componentPath)}, ${chainIndex}],`);
313
+ }
314
+ const lines = [];
315
+ lines.push("const components = {};");
316
+ lines.push(`const __voidLayoutChains = [${chains.join(", ")}];`);
317
+ lines.push("const __voidStaticRoutes = [", ...staticRows, "];");
318
+ lines.push("const __voidDynamicRoutes = [", ...dynamicRows, "];");
319
+ lines.push(`const layoutTree = {};
320
+ const __voidStaticRouteIds = new Map();
321
+ for (const [id, load, chain, pattern = "/" + id] of __voidStaticRoutes) {
322
+ components[id] = load;
323
+ if (chain >= 0) layoutTree[id] = __voidLayoutChains[chain];
324
+ if (!__voidStaticRouteIds.has(pattern)) __voidStaticRouteIds.set(pattern, id);
325
+ }
326
+ const routes = [];
327
+ for (const [pattern, id, load, chain] of __voidDynamicRoutes) {
328
+ components[id] = load;
329
+ if (chain >= 0) layoutTree[id] = __voidLayoutChains[chain];
330
+ routes.push({ pattern, id });
331
+ }`);
332
+ for (const layout of [...scan.layouts, ...scan.namedLayouts]) lines.push(`components[${JSON.stringify(layoutKey(toLayoutId(layout)))}] = ${load(layout.filePath)};`);
333
+ lines.push("const routeMeta = {");
334
+ for (const page of scan.pages) if (page.island) lines.push(` ${JSON.stringify(page.componentId)}: { island: true },`);
335
+ lines.push("};");
336
+ lines.push(`function matchRoute(path) {
337
+ const id = __voidStaticRouteIds.get(path);
338
+ if (id !== undefined) return id;
339
+ for (const r of routes) {
340
+ if (r.pattern.test(path)) return r.id;
341
+ }
342
+ return null;
343
+ }`);
344
+ return lines.join("\n");
345
+ }
346
+ const REGEX_SYNTAX = ".*+?^${}()|[]\\";
347
+ /** The capture group for `*`, `:name{.+}` and `:name`; other segments match as written. */
348
+ function captureGroup(segment) {
349
+ if (segment === "*") return "(.*)";
350
+ if (segment.length < 2 || segment[0] !== ":") return;
351
+ const name = segment.endsWith("{.+}") ? segment.slice(1, -4) : "";
352
+ return name && !name.includes("{") && !name.includes("}") ? "(.+)" : "([^\\/]+)";
353
+ }
354
+ /** Whether `patternToRegex` matches only the pattern's own text. */
355
+ function isStaticPattern(pattern) {
356
+ return pattern.split("/").every((segment) => captureGroup(segment) === void 0);
357
+ }
358
+ /** The RegExp literal a page pattern matches with, the same on the client and the server. */
359
+ function patternToRegex(pattern) {
360
+ return `/^${pattern.split("/").map((segment) => {
361
+ const group = captureGroup(segment);
362
+ if (group) return group;
363
+ let literal = "";
364
+ for (const char of segment) literal += REGEX_SYNTAX.includes(char) ? "\\" + char : char;
365
+ return literal;
366
+ }).join("\\/")}$/`;
367
+ }
368
+ //#endregion
153
369
  //#region src/pages/scan.ts
154
370
  const COMPONENT_EXTENSIONS = [
155
371
  "vue",
@@ -158,13 +374,6 @@ const COMPONENT_EXTENSIONS = [
158
374
  "svelte",
159
375
  "md"
160
376
  ];
161
- const SERVER_EXTENSIONS = [
162
- "ts",
163
- "tsx",
164
- "js",
165
- "mjs",
166
- "mts"
167
- ];
168
377
  const PAGE_METHODS = /* @__PURE__ */ new Set([
169
378
  "loader",
170
379
  "action",
@@ -173,6 +382,8 @@ const PAGE_METHODS = /* @__PURE__ */ new Set([
173
382
  const MAX_REVALIDATE = 31536e3;
174
383
  /** Layout paths already reported; a dev server rescans pages on every file change. */
175
384
  const warnedLayoutPaths = /* @__PURE__ */ new Set();
385
+ /** Unreachable pages already reported, for the same reason. */
386
+ const warnedShadowedPages = /* @__PURE__ */ new Set();
176
387
  function componentLayout(source, filename) {
177
388
  if (!source.includes("layout")) return;
178
389
  for (const script of scriptBlocks(source, filename)) {
@@ -255,6 +466,23 @@ function resolvePageRendering(page, options) {
255
466
  shouldPrerender: prerenderMode === "force" || prerenderMode === "auto" && inferAutoPrerender(page, options)
256
467
  };
257
468
  }
469
+ /**
470
+ * The environment a file under pages/ is limited to, read from its name the way
471
+ * scanPages does: `home.dev.tsx`, `home.dev.island.vue` and `home.dev.server.ts`
472
+ * give 'dev'. Files the scanner skips (`_` segments, other extensions) give null.
473
+ */
474
+ function pageFileEnvironment(relativePath) {
475
+ const segments = toSlash(relativePath).split("/");
476
+ if (segments.some((segment) => segment.startsWith("_"))) return null;
477
+ const file = segments[segments.length - 1];
478
+ const ext = extname(file);
479
+ let base = basename(file, ext);
480
+ if (ROUTE_EXTENSIONS_SET.has(ext) && base.endsWith(".server")) base = base.slice(0, -7);
481
+ else if (COMPONENT_EXTENSIONS.includes(ext.slice(1))) {
482
+ if (base.endsWith(".island")) base = base.slice(0, -7);
483
+ } else return null;
484
+ return base.endsWith(".dev") ? "dev" : base.endsWith(".prod") ? "prod" : null;
485
+ }
258
486
  async function scanPages(root, options) {
259
487
  const pagesDir = options?.pagesDir ?? options?.paths?.pagesDir ?? readProjectPaths(root).pagesDir;
260
488
  if (!existsSync(pagesDir)) return {
@@ -270,11 +498,12 @@ async function scanPages(root, options) {
270
498
  const pages = [];
271
499
  const layouts = [];
272
500
  const namedLayouts = [];
273
- for (const file of files) {
501
+ for (const file of files.sort()) {
274
502
  const segments = file.split("/");
275
503
  if (segments.some((s) => s.startsWith("_") && s !== "_layouts")) continue;
276
504
  const ext = extname(file);
277
505
  let base = basename(file, ext);
506
+ if (base.endsWith(".server") && ROUTE_EXTENSIONS_SET.has(ext)) continue;
278
507
  let island;
279
508
  let hasIslandSuffix = false;
280
509
  if (base.endsWith(".island")) {
@@ -302,8 +531,8 @@ async function scanPages(root, options) {
302
531
  });
303
532
  continue;
304
533
  }
305
- const parseName = hasIslandSuffix ? file.replace(`.island${ext}`, ".ts") : file.replace(ext, ".ts");
306
- const route = parseRouteFilename(parseName);
534
+ const route = parseRouteFilename(hasIslandSuffix ? file.replace(`.island${ext}`, ".ts") : file.replace(ext, ".ts"));
535
+ if (!isRouteEnabledForEnvironment(route, options?.environment)) continue;
307
536
  const componentId = file.replace(ext, "").replace(/\.island$/, "").replace(/\/index$/, "").replace(/^index$/, "") || "index";
308
537
  let serverPath = null;
309
538
  const methods = [];
@@ -312,11 +541,11 @@ async function scanPages(root, options) {
312
541
  let ssr;
313
542
  let hasGetPrerenderPaths;
314
543
  const serverBase = hasIslandSuffix ? file.replace(`.island${ext}`, "") : file.replace(ext, "");
315
- for (const serverExt of SERVER_EXTENSIONS) {
544
+ for (const serverExt of ROUTE_EXTENSIONS) {
316
545
  const candidate = `${serverBase}.server.${serverExt}`;
317
546
  if (existsSync(join(pagesDir, candidate))) {
318
547
  serverPath = candidate;
319
- const metadata = detectPageServerMetadata(readFileSync(join(pagesDir, candidate), "utf-8"), candidate);
548
+ const metadata = deriveFromSource(join(pagesDir, candidate), "page-server", (source) => detectPageServerMetadata(source, candidate));
320
549
  methods.push(...metadata.methods);
321
550
  revalidate = metadata.revalidate;
322
551
  prerender = metadata.prerender;
@@ -338,11 +567,11 @@ async function scanPages(root, options) {
338
567
  if (rendering.shouldPrerender && revalidate === void 0) revalidate = MAX_REVALIDATE;
339
568
  let metadata;
340
569
  let layout;
341
- if (ext === ".md") {
342
- const mdContent = readFileSync(join(pagesDir, file), "utf-8");
343
- metadata = extractFrontmatterMeta(mdContent);
344
- layout = extractFrontmatterLayout(mdContent);
345
- } else layout = componentLayout(readFileSync(join(pagesDir, file), "utf-8"), file);
570
+ if (ext === ".md") ({metadata, layout} = deriveFromSource(join(pagesDir, file), "page-markdown", (source) => ({
571
+ metadata: extractFrontmatterMeta(source),
572
+ layout: extractFrontmatterLayout(source)
573
+ })));
574
+ else layout = deriveFromSource(join(pagesDir, file), "page-layout", (source) => componentLayout(source, file));
346
575
  pages.push({
347
576
  pattern: route.pattern,
348
577
  params: route.params,
@@ -357,8 +586,9 @@ async function scanPages(root, options) {
357
586
  ...rendering,
358
587
  hasGetPrerenderPaths,
359
588
  island,
360
- metadata,
361
- layout
589
+ metadata: metadata ? { ...metadata } : void 0,
590
+ layout,
591
+ ...route.env ? { env: route.env } : {}
362
592
  });
363
593
  }
364
594
  pages.sort((a, b) => {
@@ -367,6 +597,14 @@ async function scanPages(root, options) {
367
597
  if (aDynamic !== b.pattern.includes(":")) return aDynamic ? 1 : -1;
368
598
  return a.pattern.localeCompare(b.pattern);
369
599
  });
600
+ if (options?.checkRoutes !== false) {
601
+ const environments = options?.environment ? [options.environment] : ["dev", "prod"];
602
+ for (const environment of environments) {
603
+ const live = pages.filter((page) => isRouteEnabledForEnvironment({ env: page.env ?? null }, environment));
604
+ assertOnePagePerRoute(live);
605
+ warnShadowedPages(pagesDir, live);
606
+ }
607
+ }
370
608
  for (const page of pages) {
371
609
  if (page.island) continue;
372
610
  const dir = dirname(page.componentPath);
@@ -393,6 +631,47 @@ async function scanPages(root, options) {
393
631
  namedLayouts
394
632
  };
395
633
  }
634
+ function compareText(left, right) {
635
+ return left < right ? -1 : left > right ? 1 : 0;
636
+ }
637
+ /** Group sorted pages by `key`, keeping only groups with more than one page. */
638
+ function pagesSharing(pages, key) {
639
+ const groups = /* @__PURE__ */ new Map();
640
+ for (const page of pages) {
641
+ const group = groups.get(key(page));
642
+ if (group) group.push(page);
643
+ else groups.set(key(page), [page]);
644
+ }
645
+ return [...groups.values()].filter((group) => group.length > 1);
646
+ }
647
+ /**
648
+ * Two files for one path have no stable winner: the server and the client can
649
+ * each pick a different one, and the order can change between runs.
650
+ */
651
+ function assertOnePagePerRoute(pages) {
652
+ assertNoneShare(pages, (page) => page.pattern, "pages: Multiple page files resolve to the same route:", "Keep one page file per route and rename or remove the others.");
653
+ assertNoneShare(pages, (page) => page.componentId, "pages: Multiple page files resolve to the same page id:", "Rename or remove one of them.");
654
+ }
655
+ function assertNoneShare(pages, key, title, hint) {
656
+ const clashes = pagesSharing(pages, key).map((group) => ({
657
+ key: key(group[0]),
658
+ files: group.map((page) => page.componentPath).sort(compareText)
659
+ })).sort((left, right) => compareText(left.key, right.key)).map((clash) => ` ${JSON.stringify(clash.key)}: ${clash.files.map((file) => JSON.stringify(file)).join(", ")}`);
660
+ if (clashes.length > 0) throw new Error([
661
+ title,
662
+ ...clashes,
663
+ hint
664
+ ].join("\n"));
665
+ }
666
+ /** Dynamic routes that match the same URLs, such as [id] and [slug]: only the first is ever used. */
667
+ function warnShadowedPages(pagesDir, pages) {
668
+ for (const [used, ...shadowed] of pagesSharing(pages, (page) => patternToRegex(page.pattern))) for (const page of shadowed) {
669
+ const key = `${pagesDir}\0${used.componentPath}\0${page.componentPath}`;
670
+ if (warnedShadowedPages.has(key)) continue;
671
+ warnedShadowedPages.add(key);
672
+ voidWarn(`pages: Page '${page.componentPath}' (${page.pattern}) is never used: '${used.componentPath}' (${used.pattern}) matches the same URLs first. Remove one of them.`);
673
+ }
674
+ }
396
675
  const LEADING_SCRIPT_RE = /^<script\b[^>]*>[\s\S]*?<\/script>\s*\n?/;
397
676
  /** Return the raw YAML frontmatter of markdown source, after any leading <script> block. */
398
677
  function markdownFrontmatter(source) {
@@ -424,4 +703,4 @@ function extractFrontmatterLayout(source) {
424
703
  return value;
425
704
  }
426
705
  //#endregion
427
- export { resolveNamedLayout as a, findIslandImports as c, resolveLayoutIds as i, findStaticCssImports as l, resolveEffectiveLayoutChain as n, toLayoutId as o, resolveLayoutChain as r, editIslandSource as s, scanPages as t };
706
+ export { resolveLayoutChain as a, editIslandSource as c, deriveFromSource as d, invalidateSourceAnalysis as f, ROUTE_EXTENSIONS as g, parseWebSocketFilename as h, resolveEffectiveLayoutChain as i, findIslandImports as l, parseRouteFilename as m, scanPages as n, resolveLayoutIds as o, isRouteEnabledForEnvironment as p, generateComponentManifest as r, resolveNamedLayout as s, pageFileEnvironment as t, findStaticCssImports as u };
@@ -1,10 +1,10 @@
1
1
  import { n as readDeploymentPlatform, r as readProjectConfig } from "./project-rqDnVsJN.mjs";
2
2
  import { c as getToken } from "./auth-B6iOCjKI.mjs";
3
3
  import { A as confirm, H as outro, L as log, O as cancel, U as password, tt as isCancel } from "./dist-Cor9XGoz.mjs";
4
- import { r as PlatformClient } from "./client-BEkdj1kx.mjs";
4
+ import { r as PlatformClient } from "./client-BEMtySaV.mjs";
5
5
  import { m as printSuccess, o as formatCount, p as note } from "./output-BpgYODYx.mjs";
6
6
  import { a as resolveProjectBySlug, t as getRequestedProjectSlug } from "./resolve-project-Xoi6eTWY.mjs";
7
- import { _ as validateSecretValues } from "./env-validation-Dwq3PJzK.mjs";
7
+ import { _ as validateSecretValues } from "./env-validation-XcukUlFM.mjs";
8
8
  import { readFileSync } from "node:fs";
9
9
  //#region src/cli/secret.ts
10
10
  async function runSecretCommand(root, args) {
@@ -93,7 +93,7 @@ async function resolveSecretBackend(root, args) {
93
93
  }
94
94
  async function resolveCloudflareSecretBackend(root, args) {
95
95
  if (args.projectName) throw new Error("secret: --project selects a Void platform project and is not used for direct Cloudflare apps.");
96
- const { deleteCloudflareSecret, listCloudflareSecrets, putCloudflareSecret, resolveCloudflareOperationContext, syncCloudflareSecrets } = await import("./cloudflare-operations-DsSaw2BT.mjs");
96
+ const { deleteCloudflareSecret, listCloudflareSecrets, putCloudflareSecret, resolveCloudflareOperationContext, syncCloudflareSecrets } = await import("./cloudflare-operations-PCM4wucv.mjs");
97
97
  const context = resolveCloudflareOperationContext(root);
98
98
  return {
99
99
  target: "Cloudflare Worker",
@@ -0,0 +1,32 @@
1
+ //#region src/runtime/static-asset-marker.ts
2
+ const STATIC_ASSET_KEY = "__voidStaticAsset";
3
+ /**
4
+ * Records that the fallback answered with a file from the ASSETS binding: the
5
+ * Cache-Control it carried and its body stream. The value lives on the
6
+ * context, not on the response object: `c.header()` after the handler rebuilds
7
+ * `c.res`, so a response identity check would miss the file. The rebuild keeps
8
+ * the body stream, while a middleware that swaps the body does not.
9
+ */
10
+ function markStaticAsset(c, response) {
11
+ const mark = {
12
+ policy: response.headers.get("cache-control") ?? "",
13
+ body: response.body
14
+ };
15
+ c.set(STATIC_ASSET_KEY, mark);
16
+ return response;
17
+ }
18
+ /**
19
+ * True when the final response is still the marked file: a success status, the
20
+ * same body and Cache-Control the fallback served, and no cookie added by
21
+ * later middleware.
22
+ */
23
+ function isUnchangedStaticAsset(c) {
24
+ const mark = c.get(STATIC_ASSET_KEY);
25
+ return mark !== void 0 && [
26
+ 200,
27
+ 206,
28
+ 304
29
+ ].includes(c.res.status) && c.res.body === mark.body && (c.res.headers.get("cache-control") ?? "") === mark.policy && !c.res.headers.has("set-cookie");
30
+ }
31
+ //#endregion
32
+ export { markStaticAsset as n, isUnchangedStaticAsset as t };
@@ -1,3 +1,6 @@
1
+ //#region src/router/parse-filename.d.ts
2
+ type RouteEnvironment = "dev" | "prod";
3
+ //#endregion
1
4
  //#region src/pages/types.d.ts
2
5
  type ExplicitBoolean = true | false | undefined;
3
6
  type SsrMode = "auto" | "server" | "client";
@@ -43,6 +46,8 @@ type PageDefinition = {
43
46
  };
44
47
  /** Named layout selection: "name", "!name", or false */
45
48
  layout?: string | false;
49
+ /** Environment from a `.dev` / `.prod` file suffix. Unset means both. */
50
+ env?: RouteEnvironment;
46
51
  };
47
52
  type LayoutDefinition = {
48
53
  /** Directory path relative to pages/, e.g. "" (root) or "users" */
@@ -76,4 +81,4 @@ type DevCssAsset = {
76
81
  css: string;
77
82
  };
78
83
  //#endregion
79
- export { PageRenderMode as a, PageDefinition as i, LayoutDefinition as n, PageScanResult as o, NamedLayoutDefinition as r, DevCssAsset as t };
84
+ export { PageRenderMode as a, PageDefinition as i, LayoutDefinition as n, PageScanResult as o, NamedLayoutDefinition as r, RouteEnvironment as s, DevCssAsset as t };
@@ -1,5 +1,5 @@
1
1
  import { a as join } from "./dist-ipQi0Q8y.mjs";
2
- import { l as bindingNamesForField, p as findBindingNameOwner } from "./wrangler-F96NnLyb.mjs";
2
+ import { l as bindingNamesForField, p as findBindingNameOwner } from "./wrangler-CDiEBCdS.mjs";
3
3
  //#region src/shared/untrusted-env.ts
4
4
  /** Authentication inputs that Wrangler may consume from the environment. */
5
5
  const WRANGLER_AUTH_CREDENTIAL_ENV_VARS = [
@@ -0,0 +1,11 @@
1
+ //#region src/cli/worker-conditions.ts
2
+ const WORKER_CONDITIONS = [
3
+ "workerd",
4
+ "worker",
5
+ "browser",
6
+ "module",
7
+ "import",
8
+ "default"
9
+ ];
10
+ //#endregion
11
+ export { WORKER_CONDITIONS as t };
@@ -666,9 +666,10 @@ function writeProvisionedWranglerConfig(root, patch, options) {
666
666
  const matches = [];
667
667
  for (let i = 0; i < currentList.length; i++) if (currentList[i].binding === entry.binding) matches.push(i);
668
668
  if (matches.length > 1) throw new Error(`deploy: cannot update "${configPath}" — queue producer binding ${JSON.stringify(entry.binding)} is declared ${matches.length} times across producers. A producer binding must map to exactly one queue, so wrangler rejects this config. Remove the duplicate producers and retry.`);
669
+ const voidOwned = reconcileManagedQueues && managedProducerBindings.has(String(entry.binding));
669
670
  if (matches.length === 1) {
670
671
  const existing = currentList[matches[0]];
671
- if (existing.queue !== entry.queue) throw new Error(`deploy: cannot update "${configPath}" — queue producer binding ${JSON.stringify(entry.binding)} is already bound to queue ${JSON.stringify(existing.queue)}, but queue ${JSON.stringify(entry.queue)} also requests it. A producer binding must map to exactly one queue. Rename or remove the conflicting producer and retry.`);
672
+ if (existing.queue !== entry.queue && !voidOwned) throw new Error(`deploy: cannot update "${configPath}" — queue producer binding ${JSON.stringify(entry.binding)} is already bound to queue ${JSON.stringify(existing.queue)}, but queue ${JSON.stringify(entry.queue)} also requests it. A producer binding must map to exactly one queue. Rename or remove the conflicting producer and retry.`);
672
673
  }
673
674
  index = matches.length === 1 ? matches[0] : -1;
674
675
  workerBindingOwners ??= collectWorkerBindingNames(parseJsonc(text));
@@ -0,0 +1 @@
1
+ export { b as readRootWranglerConfig } from "./wrangler-CDiEBCdS.mjs";