void 1.1.12 → 1.2.1

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 (193) hide show
  1. package/dist/{account-cmd-Cj6sCMTk.mjs → account-cmd-CdUll_35.mjs} +5 -5
  2. package/dist/action-key-XZ9HkWAO.mjs +26 -0
  3. package/dist/{application-analysis-D7nNmNJb.mjs → application-analysis-fEqoSeMp.mjs} +11 -11
  4. package/dist/{application-routing-CZH66gXn.mjs → application-routing-DAhNP4u3.mjs} +1 -1
  5. package/dist/{ast-CPGPjb0V.mjs → ast-CsZ_q_gc.mjs} +6 -1
  6. package/dist/ast-bindings-C3yaPs1y.mjs +296 -0
  7. package/dist/{auth-link-Dj7lAC_K.mjs → auth-link-C87vGXM-.mjs} +5 -5
  8. package/dist/{auth-router-CNsMOFCa.mjs → auth-router-6I81r-ix.mjs} +3 -3
  9. package/dist/{better-auth-shared-Bv18bB-l.d.mts → better-auth-shared-DVk2DkTW.d.mts} +1 -1
  10. package/dist/{build-cmd-ByhegwRC.mjs → build-cmd-ex1g-j_e.mjs} +4 -4
  11. package/dist/{cache-CEFb5ban.mjs → cache-oHzrnY3z.mjs} +4 -4
  12. package/dist/{cancel-deploy-CaARY26n.mjs → cancel-deploy-viAMD0Q_.mjs} +3 -3
  13. package/dist/cf-build-output-BJHuSsVN.mjs +1 -0
  14. package/dist/{cf-build-output-ChEKWan2.mjs → cf-build-output-BhVxldCw.mjs} +4 -3
  15. package/dist/{cf-command-values-b8OqDoo9.mjs → cf-command-values-ByHk0xg4.mjs} +2 -1
  16. package/dist/cf-worker-settings-BECvvTVd.mjs +37 -0
  17. package/dist/cli/cli.mjs +32 -32
  18. package/dist/cli/cloudflare-operation-process.mjs +23 -13
  19. package/dist/cli/env-schema-probe.d.mts +1 -1
  20. package/dist/cli/env-schema-probe.mjs +3 -3
  21. package/dist/{client-BdzxubTS.mjs → client-BEkdj1kx.mjs} +1 -1
  22. package/dist/client-BiRDZTSd.mjs +1 -0
  23. package/dist/{cloudflare-auth-DSvBc1Gu.mjs → cloudflare-auth-Byo_0_N9.mjs} +1 -1
  24. package/dist/{cloudflare-cmd-D_2-Q-_i.mjs → cloudflare-cmd-DMzCv12s.mjs} +5 -5
  25. package/dist/{cloudflare-config-rdFOys4X.mjs → cloudflare-config-DchHxPTo.mjs} +1 -1
  26. package/dist/{cloudflare-connect-BN-k2kD-.mjs → cloudflare-connect-CCRTVg-I.mjs} +3 -3
  27. package/dist/{cloudflare-operations-D5PLrOqD.mjs → cloudflare-operations-Dh9dEHJj.mjs} +6 -6
  28. package/dist/{cloudflare-operations-BFLCpUCV.mjs → cloudflare-operations-DsSaw2BT.mjs} +1 -1
  29. package/dist/{cloudflare-process-CZJ4viYl.mjs → cloudflare-process-8jEYIeim.mjs} +3 -2
  30. package/dist/{config-DC5llZaI.mjs → config-BIaXIkkv.mjs} +8 -3
  31. package/dist/{config-DYJV8aEH.mjs → config-BU6hMu1W.mjs} +1 -1
  32. package/dist/{config-D26zcdKy.mjs → config-DHgSEWT7.mjs} +39 -6
  33. package/dist/{config-7qoq2p9v.d.mts → config-DQfHOKh9.d.mts} +10 -1
  34. package/dist/config-entry.d.mts +1 -1
  35. package/dist/{connect-C4_m2moF.mjs → connect-k7R2rPVA.mjs} +6 -6
  36. package/dist/{create-project-CvuYDD-l.mjs → create-project-DTuy-l0z.mjs} +1 -1
  37. package/dist/{create-project-D8jQTwVQ.mjs → create-project-DV71ol5d.mjs} +4 -4
  38. package/dist/{db-BsiOAa0A.mjs → db-DVOkLH5X.mjs} +30 -24
  39. package/dist/{delete-CAma7nFi.mjs → delete-BbP5eopu.mjs} +4 -4
  40. package/dist/{deploy-D1gIPiAq.mjs → deploy-7H32EnUs.mjs} +114 -71
  41. package/dist/deploy-CE0Ev0Ob.mjs +2 -0
  42. package/dist/{deploy-managed-static-B9KVxY3X.mjs → deploy-managed-static-DlvcvnQT.mjs} +15 -15
  43. package/dist/{deploy-transport-B3mtEi_q.mjs → deploy-transport-BzGEj0Ge.mjs} +2 -2
  44. package/dist/deploy.mjs +7 -7
  45. package/dist/{dev-inbox-Rd6j_8vM.mjs → dev-inbox-D0jxye_D.mjs} +1 -1
  46. package/dist/{dispatch-BAbbn3jg.mjs → dispatch-DoUnxTNo.mjs} +15 -11
  47. package/dist/{dist-CfgIkieS.mjs → dist-B1PLt4_8.mjs} +1 -1
  48. package/dist/{dist-BVdsO7Py.mjs → dist-Cor9XGoz.mjs} +94 -200
  49. package/dist/{dist-Bn8Kodjp.mjs → dist-D15hFhP0.mjs} +1 -1
  50. package/dist/{domain-BAdwm-QS.mjs → domain-CA2wBgra.mjs} +5 -5
  51. package/dist/drizzle-9TubSZvI.mjs +1 -0
  52. package/dist/{email-BcjSyAL0.mjs → email-B9ayYQEG.mjs} +1 -1
  53. package/dist/{email-MwjA7kaL.mjs → email-DXpCc77w.mjs} +10 -10
  54. package/dist/{email-cloudflare-etpKiITL.mjs → email-cloudflare-D03g2TkS.mjs} +7 -7
  55. package/dist/{entry-B_0IhV64.mjs → entry-BEM8ZuGP.mjs} +40 -12
  56. package/dist/{env-B163-G1s.mjs → env-DgOQ9_8S.mjs} +6 -6
  57. package/dist/{env-public-CCdykygU.d.mts → env-public-6lqiSD2b.d.mts} +1 -0
  58. package/dist/{env-types-GRchm5dw.mjs → env-types-BicfKBhV.mjs} +1 -1
  59. package/dist/{env-validation-CuGfWRJd.mjs → env-validation-BmsdCZEk.mjs} +1 -1
  60. package/dist/{env-validation-D_KyMdab.mjs → env-validation-Dwq3PJzK.mjs} +3 -3
  61. package/dist/{gen-CYN3wiov.mjs → gen-BfmcIi2g.mjs} +5 -5
  62. package/dist/gen-NrOlWZaG.mjs +1 -0
  63. package/dist/{github-cmd-C8QsnJQs.mjs → github-cmd-CY9LUqLh.mjs} +4 -4
  64. package/dist/{handler-D5K_yP6T.d.mts → handler-BbkSPzGF.d.mts} +90 -8
  65. package/dist/{headers-Bi4bOAwp.mjs → headers-D522zd0A.mjs} +2 -2
  66. package/dist/help-BeAFFE5C.mjs +1 -0
  67. package/dist/{help-B2sFwn9b.mjs → help-CxSlPpzJ.mjs} +40 -10
  68. package/dist/{inbound-BuTfm11U.mjs → inbound-VrOLqwZY.mjs} +1 -1
  69. package/dist/index.d.mts +1 -1
  70. package/dist/index.mjs +91 -57
  71. package/dist/{info-Bxunp14X.mjs → info-7VDlhtyy.mjs} +4 -4
  72. package/dist/{init-DGFQMnbk.mjs → init-DxYyOs4-.mjs} +103 -43
  73. package/dist/{link-CwrfpjIM.mjs → link-Ddmod1dZ.mjs} +5 -5
  74. package/dist/{list-hKoW5z-b.mjs → list-MogaugiO.mjs} +5 -5
  75. package/dist/{live-JheIDZKc.d.mts → live-Bt8Y_0bg.d.mts} +1 -1
  76. package/dist/{local-d1-CpaPbd_L.mjs → local-d1-BHBnKWRb.mjs} +1 -1
  77. package/dist/{log-vqY3pqwI.mjs → log-BMwmN5Ae.mjs} +2 -2
  78. package/dist/{login-f2eu2TQh.mjs → login-Cttnagmm.mjs} +4 -4
  79. package/dist/login-DgDwlKc_.mjs +1 -0
  80. package/dist/{logs-CEWqD-_B.mjs → logs-CAszUWZI.mjs} +4 -4
  81. package/dist/{migrate-DYfdWBXt.mjs → migrate-DyT2jJ8y.mjs} +5 -5
  82. package/dist/migrate-n49ZeS1X.mjs +1 -0
  83. package/dist/{mime-srOklVVv.mjs → mime-BAyHPskU.mjs} +1 -1
  84. package/dist/nitro.mjs +3 -3
  85. package/dist/{node-uN8_zxJr.mjs → node-WB7c2N4L.mjs} +2 -2
  86. package/dist/operator-cmd-d2MvJOrl.mjs +1 -0
  87. package/dist/{operator-cmd-DCr_QGMH.mjs → operator-cmd-skshjMGl.mjs} +4 -4
  88. package/dist/output-BW9uK099.mjs +1 -0
  89. package/dist/{output-CKguMgr7.mjs → output-BpgYODYx.mjs} +3 -3
  90. package/dist/pages/client.d.mts +5 -1
  91. package/dist/pages/client.mjs +47 -30
  92. package/dist/pages/index.d.mts +1 -1
  93. package/dist/pages/index.mjs +3 -3
  94. package/dist/pages/islands-plugin.mjs +2 -1
  95. package/dist/pages/protocol.d.mts +2 -2
  96. package/dist/pages/protocol.mjs +1 -1
  97. package/dist/{parse-filename-CUbj-1MP.mjs → parse-filename-DioPHiR9.mjs} +1 -35
  98. package/dist/{picocolors-BTps1_gs.mjs → picocolors-BsDfhxIw.mjs} +1 -1
  99. package/dist/{platform-args-B7ke06up.mjs → platform-args-DVbVClZl.mjs} +12 -4
  100. package/dist/platform-args-kQrgxScY.mjs +1 -0
  101. package/dist/{platform-auth-config-qGvEuns3.mjs → platform-auth-config-C-pm5Qzx.mjs} +6 -6
  102. package/dist/{platform-auth-protection-CyLcD6ot.mjs → platform-auth-protection-SHhvim1L.mjs} +4 -4
  103. package/dist/{platform-auth-recovery-B2LKI8V2.mjs → platform-auth-recovery-DXVWs-wA.mjs} +4 -4
  104. package/dist/{platform-cmd-CX7phm7V.mjs → platform-cmd-D5I1beUX.mjs} +7 -7
  105. package/dist/{platform-cmd-B2ec5eFg.mjs → platform-cmd-PiNRkopU.mjs} +1 -1
  106. package/dist/{platform-domain-DDNK2y-4.mjs → platform-domain-jpmBfZeb.mjs} +4 -4
  107. package/dist/{platform-lifecycle-CWc5gr6c.mjs → platform-lifecycle-DH3Yr1qQ.mjs} +1 -1
  108. package/dist/{platform-lifecycle-3CR98Tg2.mjs → platform-lifecycle-DyKmuNY6.mjs} +28 -17
  109. package/dist/{platform-management-o3LCCeE4.mjs → platform-management--vDwSn35.mjs} +11 -5
  110. package/dist/{platform-management-DAE6g2QU.mjs → platform-management-7m-PLaPJ.mjs} +1 -1
  111. package/dist/{platform-plans-config-CBMZxCep.mjs → platform-plans-config-CeydDSj0.mjs} +2 -2
  112. package/dist/{platform-recovery-Dmsg7lWA.mjs → platform-recovery-BiNpZZab.mjs} +2 -2
  113. package/dist/{platform-setup-hFbnWAVQ.mjs → platform-setup-Ca53gtt0.mjs} +3 -2
  114. package/dist/{plugin-inference-Bekzjuqw.mjs → plugin-inference-DUjCd55H.mjs} +145 -218
  115. package/dist/{prepare-HKo7Rh5V.mjs → prepare-BcAE5Sdj.mjs} +3 -3
  116. package/dist/prepare-C4I0f--h.mjs +1 -0
  117. package/dist/{prepare-DepAGBcV.mjs → prepare-DA-17DhO.mjs} +5 -5
  118. package/dist/{prerender-render-Bfsumdkv.mjs → prerender-render-Cijv7UFo.mjs} +11 -6
  119. package/dist/prerender-render.mjs +1 -1
  120. package/dist/{project-cmd-8ylYGx-O.mjs → project-cmd-DA4K5faU.mjs} +17 -17
  121. package/dist/{project-team-Bvpl78we.mjs → project-team-CQBNveX3.mjs} +4 -4
  122. package/dist/{project-token-QWHoJH2t.mjs → project-token-CCalFyQf.mjs} +4 -4
  123. package/dist/{project-zero-trust-8tJ-RFvu.mjs → project-zero-trust-DPnkiEuT.mjs} +4 -4
  124. package/dist/{protocol-Ssc_LhHj.d.mts → protocol-BBDpJz3G.d.mts} +3 -1
  125. package/dist/{protocol-bAUUkx70.mjs → protocol-DimNxVRr.mjs} +41 -16
  126. package/dist/{provision-BgXFDv0d.mjs → provision-BFLCrnUp.mjs} +1 -1
  127. package/dist/{provision-DZKYCEJg.mjs → provision-DtROpNNI.mjs} +3 -3
  128. package/dist/{requests-Vk5Zyhcy.mjs → requests-BpH0kImL.mjs} +3 -3
  129. package/dist/resolve-project-DD1vu8s9.mjs +1 -0
  130. package/dist/{resolve-project-WpwkCB_c.mjs → resolve-project-Xoi6eTWY.mjs} +1 -1
  131. package/dist/{rollback-CH4yMQys.mjs → rollback-CXS1tAa-.mjs} +4 -4
  132. package/dist/{rolldown-runtime-DXIUcv95.mjs → rolldown-runtime-3h0WiCiA.mjs} +1 -1
  133. package/dist/{routing-assets-VkrKIbxE.mjs → routing-assets-DdSFxoLp.mjs} +10 -4
  134. package/dist/runtime/better-auth-mysql.d.mts +1 -1
  135. package/dist/runtime/better-auth-pg.d.mts +1 -1
  136. package/dist/runtime/better-auth.d.mts +1 -1
  137. package/dist/runtime/email/testing.mjs +4 -4
  138. package/dist/runtime/email.mjs +3 -3
  139. package/dist/runtime/env-public.d.mts +1 -1
  140. package/dist/runtime/handler.d.mts +1 -1
  141. package/dist/runtime/live-client.d.mts +1 -1
  142. package/dist/runtime/live.d.mts +1 -1
  143. package/dist/runtime/routing.d.mts +17 -76
  144. package/dist/runtime/routing.mjs +277 -216
  145. package/dist/runtime/validator.d.mts +1 -1
  146. package/dist/runtime/ws-server.d.mts +2 -2
  147. package/dist/runtime/ws.d.mts +1 -1
  148. package/dist/{scan-D2-FcLHs.mjs → scan-8IzYXiU_.mjs} +12 -11
  149. package/dist/{secret-wr6Sn4Xa.mjs → secret-BbXHfLAt.mjs} +6 -6
  150. package/dist/{skills-C_yRTg0g.mjs → skills-CrUO3PJ0.mjs} +1 -1
  151. package/dist/{subcommand-prompt-CNZc4XUd.mjs → subcommand-prompt-D9OhhbGG.mjs} +2 -2
  152. package/dist/{version-metadata-B1Bm2wSq.mjs → version-metadata-tS39iW09.mjs} +1 -1
  153. package/dist/wrangler-BLb3_luP.mjs +1 -0
  154. package/dist/{wrangler-C9XSzrju.mjs → wrangler-F96NnLyb.mjs} +13 -5
  155. package/dist/{wrapper-DGsYwNi6.mjs → wrapper-D3sZyh2C.mjs} +3 -3
  156. package/dist/{ws-nnFnAyQb.d.mts → ws-BH-im_tX.d.mts} +1 -1
  157. package/docs/guide/ai.md +1 -1
  158. package/docs/guide/database/postgresql.md +1 -1
  159. package/docs/guide/database.md +26 -0
  160. package/docs/guide/email/domains.md +1 -1
  161. package/docs/guide/pages-routing/actions-and-forms.md +1 -1
  162. package/docs/guide/pages-routing/overview.md +1 -1
  163. package/docs/guide/platform/installation/credentials.md +1 -1
  164. package/docs/guide/platform/installation/domains.md +16 -0
  165. package/docs/guide/quickstart.md +26 -1
  166. package/docs/guide/sandboxes.md +2 -2
  167. package/docs/guide/self-hosted-platform.md +1 -1
  168. package/docs/guide/server-routing.md +1 -1
  169. package/docs/integrations/cloudflare.md +1 -0
  170. package/docs/reference/api/env.md +1 -1
  171. package/docs/reference/api/rewrites.md +1 -1
  172. package/docs/reference/api/types.md +1 -0
  173. package/docs/reference/cli/platform-installation.md +3 -2
  174. package/docs/reference/cli/setup.md +17 -0
  175. package/docs/reference/cli.md +1 -1
  176. package/docs/reference/config.md +13 -0
  177. package/docs/reference/resource-inference.md +4 -0
  178. package/package.json +22 -22
  179. package/sandbox.Dockerfile +2 -2
  180. package/schema.json +23 -3
  181. package/dist/cf-build-output-Dcmxa-Zm.mjs +0 -1
  182. package/dist/cf-user-agent-BkEHPDLA.mjs +0 -16
  183. package/dist/client-DAnfyMe9.mjs +0 -1
  184. package/dist/deploy-Dc0XsCQj.mjs +0 -2
  185. package/dist/gen-Cf-RBVg4.mjs +0 -1
  186. package/dist/help-w-xlx_kq.mjs +0 -1
  187. package/dist/login-08mBwZfI.mjs +0 -1
  188. package/dist/migrate-Di-4EuoE.mjs +0 -1
  189. package/dist/operator-cmd-Bv20yLu2.mjs +0 -1
  190. package/dist/platform-args-B_LrqEZB.mjs +0 -1
  191. package/dist/prepare-EVEbQ9n2.mjs +0 -1
  192. package/dist/resolve-project-PnhzMtY6.mjs +0 -1
  193. package/dist/wrangler-DAdxHEzh.mjs +0 -1
@@ -1,5 +1,5 @@
1
1
  import { a as join } from "./dist-ipQi0Q8y.mjs";
2
- import { l as bindingNamesForField, p as findBindingNameOwner } from "./wrangler-C9XSzrju.mjs";
2
+ import { l as bindingNamesForField, p as findBindingNameOwner } from "./wrangler-F96NnLyb.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 @@
1
+ export { b as readRootWranglerConfig } from "./wrangler-F96NnLyb.mjs";
@@ -1,7 +1,7 @@
1
- import { a as join, n as dirname, o as normalize, t as basename } from "./dist-ipQi0Q8y.mjs";
1
+ import { a as join, c as resolve, n as dirname, o as normalize, t as basename } from "./dist-ipQi0Q8y.mjs";
2
2
  import "./project-paths-DGu_QZ_Q.mjs";
3
- import { d as readConfig } from "./config-D26zcdKy.mjs";
4
- import { i as persistCloudflareConfig, r as materializeCloudflareConfig } from "./cloudflare-config-rdFOys4X.mjs";
3
+ import { p as readConfig } from "./config-DHgSEWT7.mjs";
4
+ import { i as persistCloudflareConfig, r as materializeCloudflareConfig } from "./cloudflare-config-DchHxPTo.mjs";
5
5
  import { existsSync, readFileSync, writeFileSync } from "node:fs";
6
6
  import { appendSqliteClassMigration, isRecord } from "@void/deploy-core";
7
7
  import { createHash } from "node:crypto";
@@ -640,7 +640,7 @@ function writeProvisionedWranglerConfig(root, patch, options) {
640
640
  const existingDir = d1Entries[index].migrations_dir;
641
641
  if (existingDir !== void 0 && typeof existingDir !== "string") throw new Error(`deploy: cannot update "${configPath}" — the D1 entry for binding ${JSON.stringify(patch.d1MigrationsDir.binding)} has a non-string "migrations_dir" value; expected a string. Fix the config and retry.`);
642
642
  if (typeof existingDir === "string") {
643
- if (normalizeMigrationsPath(existingDir) !== normalizeMigrationsPath(patch.d1MigrationsDir.dir)) throw new Error(`deploy: cannot update "${configPath}" — the D1 entry for binding ${JSON.stringify(patch.d1MigrationsDir.binding)} already sets "migrations_dir": ${JSON.stringify(existingDir)}, but Void keeps this database's migrations in ${JSON.stringify(patch.d1MigrationsDir.dir)}. Refusing to overwrite an explicit different migrations directory. Either remove "migrations_dir" from the entry (or set it to ${JSON.stringify(patch.d1MigrationsDir.dir)}) to let Void manage it, or move the migrations and keep your directory, then retry.`);
643
+ if (!sameMigrationsDir(configPath, existingDir, patch.d1MigrationsDir.dir)) throw new Error(`deploy: cannot update "${configPath}" — the D1 entry for binding ${JSON.stringify(patch.d1MigrationsDir.binding)} already sets "migrations_dir": ${JSON.stringify(existingDir)}, but Void keeps this database's migrations in ${JSON.stringify(patch.d1MigrationsDir.dir)}. Refusing to overwrite an explicit different migrations directory. Either remove "migrations_dir" from the entry (or set it to ${JSON.stringify(patch.d1MigrationsDir.dir)}) to let Void manage it, or move the migrations and keep your directory, then retry.`);
644
644
  } else {
645
645
  if (existingPattern !== void 0 && !migrationsPatternMatchesDir(existingPattern, patch.d1MigrationsDir.dir)) throw new Error(`deploy: cannot update "${configPath}" — the D1 entry for binding ${JSON.stringify(patch.d1MigrationsDir.binding)} has "migrations_pattern": ${JSON.stringify(existingPattern)}, which is not under the requested "migrations_dir": ${JSON.stringify(patch.d1MigrationsDir.dir)}. Wrangler requires the pattern to start with the migrations dir, so this change would break \`wrangler d1 migrations\`. Align "migrations_pattern" with the dir (or remove it) and retry.`);
646
646
  set([
@@ -1379,6 +1379,14 @@ function strictBindingEntries(members, keyField, field) {
1379
1379
  function bindingSetError(problem, hidden) {
1380
1380
  return /* @__PURE__ */ new Error(`deploy: cannot verify binding-name uniqueness — ${problem}. Refusing to proceed on a partially-readable binding set (a ${hidden} could hide a real collision). Fix the wrangler config and retry.`);
1381
1381
  }
1382
+ /**
1383
+ * Whether two `migrations_dir` values name the same folder. Wrangler resolves the value
1384
+ * against the config file's directory and accepts either slash.
1385
+ */
1386
+ function sameMigrationsDir(configPath, a, b) {
1387
+ const base = dirname(configPath);
1388
+ return resolve(base, a.replaceAll("\\", "/")) === resolve(base, b.replaceAll("\\", "/"));
1389
+ }
1382
1390
  /** Wrangler's rule: the normalized pattern starts with `<dir>/`, unless the dir is ".". */
1383
1391
  function migrationsPatternMatchesDir(pattern, dir) {
1384
1392
  const normalizedDir = normalizeMigrationsPath(dir);
@@ -1391,4 +1399,4 @@ function normalizeMigrationsPath(p) {
1391
1399
  return normalized.endsWith("/") ? normalized.slice(0, -1) : normalized;
1392
1400
  }
1393
1401
  //#endregion
1394
- export { updateWranglerCustomDomain as A, readWranglerManagedQueueCleanupCandidates as C, syncWranglerBindings as D, resolveLiveBindingConfig as E, writeWranglerPublishedTrafficSnapshot as M, syncWranglerDurableObjects as O, readWranglerCustomDomains as S, readWranglerWebSocketTombstones as T, persistMaterializedWranglerConfig as _, LIVE_MIGRATION_TAG as a, readRootWranglerConfig as b, bindingEntriesForField as c, ensureWranglerCompatibilityDate as d, ensureWranglerNodejsAlsFlag as f, normalizeWranglerCompatibilityFlags as g, nextDurableObjectMigrationTag as h, LATEST_KNOWN_COMPAT_DATE as i, writeProvisionedWranglerConfig as j, syncWranglerWebSockets as k, bindingNamesForField as l, hasDurableObjectSqliteMigration as m, DEFAULT_LIVE_CLASS as n, acknowledgeWranglerManagedQueueRemovals as o, findBindingNameOwner as p, FRIENDLY_BINDING_NAMES as r, assertNoDuplicateMembers as s, DEFAULT_LIVE_BINDING as t, ensureWranglerCompat as u, readExistingLiveBindingConfig as v, readWranglerPublishedTrafficSnapshot as w, readWranglerCompat as x, readProvisionedBindingEntry as y };
1402
+ export { syncWranglerWebSockets as A, readWranglerManagedQueueCleanupCandidates as C, sameMigrationsDir as D, resolveLiveBindingConfig as E, writeProvisionedWranglerConfig as M, writeWranglerPublishedTrafficSnapshot as N, syncWranglerBindings as O, readWranglerCustomDomains as S, readWranglerWebSocketTombstones as T, persistMaterializedWranglerConfig as _, LIVE_MIGRATION_TAG as a, readRootWranglerConfig as b, bindingEntriesForField as c, ensureWranglerCompatibilityDate as d, ensureWranglerNodejsAlsFlag as f, normalizeWranglerCompatibilityFlags as g, nextDurableObjectMigrationTag as h, LATEST_KNOWN_COMPAT_DATE as i, updateWranglerCustomDomain as j, syncWranglerDurableObjects as k, bindingNamesForField as l, hasDurableObjectSqliteMigration as m, DEFAULT_LIVE_CLASS as n, acknowledgeWranglerManagedQueueRemovals as o, findBindingNameOwner as p, FRIENDLY_BINDING_NAMES as r, assertNoDuplicateMembers as s, DEFAULT_LIVE_BINDING as t, ensureWranglerCompat as u, readExistingLiveBindingConfig as v, readWranglerPublishedTrafficSnapshot as w, readWranglerCompat as x, readProvisionedBindingEntry as y };
@@ -1,9 +1,9 @@
1
1
  import { a as join, l as toSlash, n as dirname, r as extname } from "./dist-ipQi0Q8y.mjs";
2
2
  import { n as readProjectPaths } from "./project-paths-DGu_QZ_Q.mjs";
3
- import { d as readConfig, s as getDatabaseDialect } from "./config-D26zcdKy.mjs";
4
- import { n as isIdentifier, r as isLiteral } from "./ast-CPGPjb0V.mjs";
3
+ import { l as getDatabaseDialect, p as readConfig } from "./config-DHgSEWT7.mjs";
4
+ import { n as isIdentifier, r as isLiteral } from "./ast-CsZ_q_gc.mjs";
5
5
  import { t as MagicString } from "./dist-Cegxq8gs.mjs";
6
- import { r as voidDbBundlerPlugin, t as generateQueueResolverSource } from "./dispatch-BAbbn3jg.mjs";
6
+ import { r as voidDbBundlerPlugin, t as generateQueueResolverSource } from "./dispatch-DoUnxTNo.mjs";
7
7
  import { createRequire } from "node:module";
8
8
  import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
9
9
  import { fileURLToPath } from "node:url";
@@ -1,6 +1,6 @@
1
1
  import { t as StandardSchemaV1 } from "./standard-schema-Fo_vCAZh.mjs";
2
2
  import { r as AuthUser } from "./auth-DkcFflXV.mjs";
3
- import { a as CloudEnv } from "./handler-D5K_yP6T.mjs";
3
+ import { a as CloudEnv } from "./handler-BbkSPzGF.mjs";
4
4
  import { WebSocketRouteMap } from "void/routes";
5
5
  //#region src/runtime/ws.d.ts
6
6
  type MaybePromise<T> = T | Promise<T>;
package/docs/guide/ai.md CHANGED
@@ -261,7 +261,7 @@ void secret put OPENAI_API_KEY=sk-...
261
261
 
262
262
  For local development, add it to `.env` in your project root:
263
263
 
264
- ```
264
+ ```dotenv
265
265
  OPENAI_API_KEY=sk-...
266
266
  ```
267
267
 
@@ -28,7 +28,7 @@ Add to your `void.config.ts`:
28
28
 
29
29
  For local development, add `DATABASE_URL` to `.env`:
30
30
 
31
- ```
31
+ ```dotenv
32
32
  DATABASE_URL=postgresql://user:password@host:5432/mydb?sslmode=require
33
33
  ```
34
34
 
@@ -114,6 +114,32 @@ export * from "./schema/users";
114
114
  export * from "./schema/posts";
115
115
  ```
116
116
 
117
+ ### Column casing
118
+
119
+ By default, a column declared without a name, such as `createdAt: timestamp()`, uses its key as the column name. Set `database.casing` to `'snake_case'` to store these columns as `created_at` instead. It applies to `void/db` queries and to `void db` commands such as `generate`, `push`, and `seed`. Columns with an explicit name, such as `text('created_at')`, keep that name.
120
+
121
+ ```ts
122
+ // void.config.ts
123
+ import { defineConfig } from 'void/config';
124
+
125
+ export default defineConfig({
126
+ database: { dialect: 'pg', casing: 'snake_case' },
127
+ });
128
+ ```
129
+
130
+ ```ts
131
+ // db/schema.ts
132
+ import { pgTable, serial, text, timestamp } from 'void/schema-pg';
133
+
134
+ export const posts = pgTable('posts', {
135
+ id: serial().primaryKey(),
136
+ title: text().notNull(),
137
+ createdAt: timestamp().notNull().defaultNow(), // created_at
138
+ });
139
+ ```
140
+
141
+ Omit `dialect` for D1. If your database already has tables, run `void db generate` after you change `casing` and review the migration before you apply it.
142
+
117
143
  ## Querying
118
144
 
119
145
  Void re-exports all common [Drizzle query operators](https://orm.drizzle.team/docs/select) from `void/db` so you don't need to install `drizzle-orm` separately. Import `db` from `void/db` and your tables from `@schema`:
@@ -16,7 +16,7 @@ void email domain add acme.com
16
16
 
17
17
  `add` opens a Cloudflare API-token template. Restrict the token to the selected account and mail zone before creating it; Workers Scripts permission applies across that account. The CLI accepts a masked paste or a newly copied token and asks you to confirm those restrictions. The platform encrypts the credential for the zone connection, so projects sharing that zone do not need separate ingress Workers.
18
18
 
19
- Platform-managed custom inbound email requires the apex of a Cloudflare zone. Cloudflare’s catch-all only covers that apex, so a subdomain of the selected zone cannot receive arbitrary addresses. Choose an apex without another mail provider, or use the platform’s shared mail address. Void preserves foreign MX records and enabled catch-alls. Each custom apex belongs to one project; a project can register more than one apex.
19
+ Platform-managed custom inbound email requires the apex of a Cloudflare zone. Cloudflare’s catch-all only covers that apex, so a subdomain of the selected zone cannot receive arbitrary addresses. `add` refuses to register a new apex that already has MX records, or whose catch-all already routes elsewhere, so it never takes over mail hosted with another provider such as Microsoft 365 or Google Workspace. Use an apex that has no mail yet, or the platform’s shared mail address. Running `add` again for a registered apex, for example to renew its token, keeps working. Each custom apex belongs to one project; a project can register more than one apex.
20
20
 
21
21
  If setup is interrupted, use `void email domain status <domain>` to inspect the saved operation before retrying.
22
22
 
@@ -197,7 +197,7 @@ export const actions = {
197
197
  };
198
198
  ```
199
199
 
200
- Named actions are dispatched via a `?actionName` suffix on the URL (e.g. `/users/42?update`). The client primitives `useForm` and `action()` handle this automatically.
200
+ Named actions are dispatched via a `?actionName` suffix on the URL (e.g. `/users/42?update`). The client primitives `useForm` and `action()` handle this automatically. The action key stays out of the page URL. When `POST /users/42?update&tab=profile` renders the page again, `useForm` and `action()` leave the address bar at `/users/42?tab=profile`, and `c.redirect('/users/42')` goes to `/users/42?tab=profile`.
201
201
 
202
202
  Use `action` or `actions` in a file, not both.
203
203
 
@@ -208,7 +208,7 @@ import { useRouter } from '@void/vue'; // or "@void/react", "@void/svelte", "@vo
208
208
 
209
209
  const router = useRouter();
210
210
  router.visit('/users');
211
- router.refresh(); // re-fetch current page props
211
+ router.refresh(); // re-fetch current page props, keeping the same history entry
212
212
  router.visit('/logout', { method: 'POST' }); // non-GET navigation
213
213
  ```
214
214
 
@@ -60,7 +60,7 @@ Use the following permissions for the core platform. Cloudflare may label write
60
60
 
61
61
  When Void configures Access in the installation account, the initial management-token link also selects **Account → Access: Apps and Policies → Edit** and **Account → Access: Organizations, Identity Providers, and Groups → Read**. Protection adds **Account → Access: Service Tokens → Edit**. When the authentication configuration or saved setup selects existing applications, the link requests Read access instead of Edit. These permissions belong to the management token; the runtime token does not need them.
62
62
 
63
- The management token also needs **Zone Edit** with authority to create zones if you ask Void to create the zone. If it already exists, use the selected zone with Zone Read and DNS Edit. Nested application domains additionally need **SSL and Certificates: Read** on the management token. A custom runtime that enables custom project domains needs **SSL and Certificates: Edit** on the runtime token; the core runtime does not enable that feature.
63
+ The management token also needs **Zone Edit** with authority to create zones if you ask Void to create the zone. If it already exists, use the selected zone with Zone Read and DNS Edit. Nested application domains additionally need **SSL and Certificates: Read** on the management token. An installation with [project custom domains](/guide/platform/installation/domains#project-custom-domains) needs **SSL and Certificates: Edit** on the runtime token.
64
64
 
65
65
  Void checks access before provisioning. If it reports a missing permission, update the token's permissions for the selected account or zone and retry.
66
66
 
@@ -53,6 +53,22 @@ The management token needs **SSL and Certificates: Read** (or Edit) on that zone
53
53
 
54
54
  :::
55
55
 
56
+ ## Project Custom Domains
57
+
58
+ Projects can serve their own domains, such as `www.example.com`, through Cloudflare for SaaS custom hostnames. This needs a dedicated application zone. Turn it on when installing, or later with an upgrade:
59
+
60
+ ```sh
61
+ void platform install --application-domain example.app --zone example.app --dedicated-zone --custom-domains
62
+ void platform upgrade <installation-id> --custom-domains
63
+ ```
64
+
65
+ The runtime token needs **SSL and Certificates: Edit** on the application zone. Void includes it in the runtime token's creation link and checks it before deploying; a token created before custom domains were on needs it added. Before adding the first domain, set up Cloudflare for SaaS on that zone once:
66
+
67
+ 1. Create a proxied DNS record for `cname.<application domain>`, for example an `AAAA` record pointing to `100::`.
68
+ 2. Open **SSL/TLS > Custom Hostnames**, enable Cloudflare for SaaS, and set `cname.<application domain>` as the fallback origin.
69
+
70
+ A project owner then runs `void domain add <hostname>`. Void prints the CNAME target, `cname.<application domain>`, and the TXT records that prove ownership. Once the records resolve and the certificate is issued, the dedicated zone's catch-all routes send the hostname to the project.
71
+
56
72
  ## Optional Dashboard
57
73
 
58
74
  The API's `/admin/` pages are included in the core installation. You can deploy
@@ -32,6 +32,11 @@ bun add -D void
32
32
  bunx void init
33
33
  ```
34
34
 
35
+ ```sh [vite+]
36
+ vp add -D void
37
+ vpx void init
38
+ ```
39
+
35
40
  :::
36
41
 
37
42
  Choose your UI framework, a starter, and a deployment target. Vite+ is the default build tool. D1 is a good first database: it runs locally without a separate database server. Choose Cloudflare to deploy to your own account, or skip deployment setup for now.
@@ -42,10 +47,30 @@ With pnpm, `pnpm create void my-app` also creates the project directory and conf
42
47
 
43
48
  ## Run locally
44
49
 
45
- ```sh
50
+ ::: code-group
51
+
52
+ ```sh [npm]
46
53
  npm run dev
47
54
  ```
48
55
 
56
+ ```sh [pnpm]
57
+ pnpm run dev
58
+ ```
59
+
60
+ ```sh [yarn]
61
+ yarn run dev
62
+ ```
63
+
64
+ ```sh [bun]
65
+ bun run dev
66
+ ```
67
+
68
+ ```sh [vite+]
69
+ vpr dev
70
+ ```
71
+
72
+ :::
73
+
49
74
  Open `http://localhost:5173`. In a Pages starter, `pages/` contains your UI and companion `.server.ts` files contain its server loaders and actions. Loaders return data to page components as typed props.
50
75
 
51
76
  ## Call a server route
@@ -120,8 +120,8 @@ See the [configuration reference](../reference/config.md#sandbox) for binding na
120
120
  Custom images must include the helper matching Void's installed Sandbox SDK version. The SDK image supplies this binary, but is not a runnable environment itself:
121
121
 
122
122
  ```dockerfile
123
- FROM node:26.10.0-trixie-slim
124
- COPY --from=docker.io/cloudflare/sandbox:1.0.1 /usr/local/bin/sandbox-shim /usr/local/bin/sandbox-shim
123
+ FROM node:26.12.1-trixie-slim
124
+ COPY --from=docker.io/cloudflare/sandbox:1.0.2 /usr/local/bin/sandbox-shim /usr/local/bin/sandbox-shim
125
125
  WORKDIR /workspace
126
126
  CMD ["sleep", "infinity"]
127
127
  ```
@@ -10,7 +10,7 @@ If you're deploying an app for yourself, [deploy directly to Cloudflare](/integr
10
10
 
11
11
  The core platform supports GitHub, Google, generic OIDC, and Cloudflare Access login, CLI deploys, D1, KV, R2, Queues, cron jobs, Workers AI, WebSockets, SSE, ISR, routing, logs, and rollback.
12
12
 
13
- The core installation includes managed Sandboxes and an email gateway; email is enabled when you configure a shared mail domain and zone. The user dashboard, GitHub builds and webhooks, build Containers, and custom project domains aren't part of the core installation. Source-built platforms that add the optional GitHub services should follow the [isolated webhook ingress setup](/guide/platform/development/runtime#optional-github-webhook-ingress-for-access-protected-apis) when Access protects the API.
13
+ The core installation includes managed Sandboxes and an email gateway; email is enabled when you configure a shared mail domain and zone. The user dashboard, GitHub builds and webhooks, and build Containers aren't part of the core installation. [Project custom domains](/guide/platform/installation/domains#project-custom-domains) are opt-in with `--custom-domains`. Source-built platforms that add the optional GitHub services should follow the [isolated webhook ingress setup](/guide/platform/development/runtime#optional-github-webhook-ingress-for-access-protected-apis) when Access protects the API.
14
14
 
15
15
  ## Deployment features
16
16
 
@@ -12,7 +12,7 @@ Create route handlers in `routes/**/*.ts`. Each file maps to a URL path based on
12
12
 
13
13
  <RoutesFileTree />
14
14
 
15
- Dynamic segments use brackets: `[id]` becomes a route parameter and `[...slug]` becomes a catch-all. Files or directories starting with `_` are ignored. Directories wrapped in parentheses like `(admin)` are route groups. They help organize files without changing the URL.
15
+ Dynamic segments use brackets: `[id]` becomes a route parameter and `[...slug]` becomes a catch-all. Files or directories starting with `_` are ignored, and so are those starting with `.`, except `.well-known`. Directories wrapped in parentheses like `(admin)` are route groups. They help organize files without changing the URL.
16
16
 
17
17
  ### Environment-only routes
18
18
 
@@ -52,6 +52,7 @@ This provides binding types and Workers runtime types.
52
52
  | `KV` | KV | `c.env.KV` or `void/kv` |
53
53
  | `STORAGE` | R2 | `c.env.STORAGE` or `void/storage` |
54
54
  | `AI` | Workers AI | `c.env.AI` or `void/ai` |
55
+ | `ASSETS` | Static assets | `c.env.ASSETS.fetch(request)` |
55
56
  | `QUEUE_*` | Queues | `defineQueue()` or `void/queues` |
56
57
  | Filename-derived | Durable Objects | A module in `durable-objects/` |
57
58
 
@@ -45,6 +45,6 @@ Non-client keys are server values and use remote secret storage in production. `
45
45
  /// <reference types="void/env" />
46
46
  ```
47
47
 
48
- Declares the `Cloudflare.Env` namespace with `DB`, `KV`, `STORAGE`, `AI`, and `SANDBOX` binding types.
48
+ Declares the `Cloudflare.Env` namespace with `DB`, `KV`, `STORAGE`, `AI`, `SANDBOX`, and `ASSETS` binding types.
49
49
 
50
50
  For handler context variables such as `c.set()` and `c.get()`, augment [`CloudContextVariables`](./types.md#cloudcontextvariables). This is separate from `Cloudflare.Env`, which types worker bindings. Framework adapters such as `@void/vue`, `@void/react`, and `@void/svelte` also augment `CloudContextVariables` to add the `shared` key used by `useShared()`.
@@ -10,7 +10,7 @@ URL rewrites re-dispatch a request at a different internal path without changing
10
10
 
11
11
  Re-dispatches the current request at `destination` and returns the resulting `Response`. The browser URL does not change — this is a server-side hop. If `destination` has no query string, the original request query is preserved. If `destination` includes a query string, it replaces the original query. `destination` must start with `/`; known generated routes autocomplete via [`RewriteDestination`](#rewritedestination), while arbitrary strings remain accepted for dynamic paths.
12
12
 
13
- `c.redirect()` also preserves request query params for internal destinations, but it merges rather than replaces: destination params win on collision, and request-only params are appended.
13
+ `c.redirect()` also preserves request query params for internal destinations, but it merges rather than replaces: destination params win on collision, and request-only params are appended. On a request to a [named action](../../guide/pages-routing/actions-and-forms.md#named-actions), the action key (`?delete` in `POST /users/42?delete`) is not carried over, whether the action or middleware redirects. A redirect after which the browser sends the same request again keeps it: `307` and `308`, and `301` or `302` after a `PUT`, `PATCH` or `DELETE`.
14
14
 
15
15
  ```ts
16
16
  import { defineHandler } from 'void';
@@ -24,6 +24,7 @@ interface CloudEnv extends Env {
24
24
  STORAGE: R2Bucket;
25
25
  AI: Ai;
26
26
  SANDBOX: DurableObjectNamespace<import('void/sandbox').VoidPlatformSandbox>;
27
+ ASSETS: { fetch(request: Request): Promise<Response> };
27
28
  [key: string]: unknown;
28
29
  };
29
30
  Variables: CloudContextVariables;
@@ -24,6 +24,7 @@ void platform install [options] [--yes]
24
24
  | `--zone <domain>` | Cloudflare zone containing the application domain |
25
25
  | `--dedicated-zone` | Add zone-wide catch-all routes; valid only when the app domain is the whole zone |
26
26
  | `--no-dedicated-zone` | Skip zone-wide application catch-all routes |
27
+ | `--custom-domains` | Let projects add their own domains; needs a dedicated zone |
27
28
  | `--control-plane-domain <domain>` | Optional API custom hostname; defaults to `workers.dev` |
28
29
  | `--no-control-plane-domain` | Use the default `workers.dev` API hostname |
29
30
  | `--dashboard-url <origin>` | HTTPS origin of an optional dashboard deployed separately |
@@ -100,9 +101,9 @@ Use these commands to recover, update, pause, or remove an installation:
100
101
 
101
102
  ```sh
102
103
  void platform discover [--account <id>] [--installation <id-or-name>]
103
- void platform upgrade [id] [--runtime <path>] [--dashboard-url <origin>] [--plan] [--yes]
104
+ void platform upgrade [id] [--runtime <path>] [--dashboard-url <origin>] [--custom-domains] [--plan] [--yes]
104
105
  void platform rollback [id] --runtime <earlier-path> [--from-runtime <current-path>] [--plan] [--yes]
105
- void platform repair [id] [--runtime <path>] [--dashboard-url <origin>] [--auth-config <path>] [--plan] [--yes]
106
+ void platform repair [id] [--runtime <path>] [--dashboard-url <origin>] [--custom-domains] [--auth-config <path>] [--plan] [--yes]
106
107
  void platform disable [id] [--plan] [--yes]
107
108
  void platform enable [id] [--runtime <path>] [--plan] [--yes]
108
109
  void platform uninstall [id] [--plan] [--purge-data | --purge-resources] [--yes]
@@ -29,10 +29,27 @@ Resources recorded in `void.lock.json` without a matching definition appear sepa
29
29
 
30
30
  ```sh
31
31
  void init [--tsconfig] [--github] [--git | --no-git]
32
+ [--toolchain <name>] [--framework <name>] [--starter <name>] [--deploy <target>]
32
33
  ```
33
34
 
34
35
  Set up a new or existing Void project. In an empty directory, choose Vite+ or Vite, a framework, and a D1, PostgreSQL, MySQL, or Static Pages starter.
35
36
 
37
+ To scaffold without prompts, for example from a script or a coding agent, pass the choices as flags. Without an interactive terminal, init stops and names the flag it needs instead of prompting.
38
+
39
+ | Flag | Values |
40
+ | ------------- | ----------------------------------------- |
41
+ | `--toolchain` | `vite-plus`, `vite` |
42
+ | `--framework` | `react`, `vue`, `svelte`, `solid` |
43
+ | `--starter` | `sqlite`, `postgresql`, `mysql`, `static` |
44
+ | `--deploy` | `cloudflare`, `void`, `none` |
45
+
46
+ ```sh
47
+ void init --toolchain vite-plus --framework react --starter sqlite --deploy none
48
+ npm create void@latest my-app -- --toolchain vite-plus --framework react --starter sqlite --deploy none
49
+ ```
50
+
51
+ Cloudflare and Void platform setup still sign in interactively. Without a terminal, choose `--deploy none` and run `void connect` later.
52
+
36
53
  Vite+ projects install dependencies through `vp install`; no global Vite+ installation is required. Void preserves existing package-manager versions and lockfiles. New Vite+ projects without a package-manager configuration use pnpm without pinning a version.
37
54
 
38
55
  In an existing app, Void adds missing dependencies and scripts and updates the Vite config. If it cannot edit your config, it prints the snippet to add.
@@ -79,7 +79,7 @@ Use this page as a command reference. If you are setting up a project for the fi
79
79
 
80
80
  ## Binary Invocation {#binary-invocation}
81
81
 
82
- The docs use `void` for brevity. Outside package scripts, run it with your package manager: `npx void`, `pnpm void`, `yarn void`, or `bunx void`.
82
+ The docs use `void` for brevity. Outside package scripts, run it with your package manager: `npx void`, `pnpm void`, `yarn void`, `bunx void`, or `vpx void`.
83
83
 
84
84
  Alternatively, you can add `./node_modules/.bin` to your `PATH` so that you can invoke `void` directly when you are in the root directory of your app.
85
85
 
@@ -141,6 +141,19 @@ Database backend. Omit for D1/SQLite (default). Set to `"pg"` or `"mysql"` for a
141
141
  | `"pg"` | PostgreSQL via Hyperdrive; bring your own database |
142
142
  | `"mysql"` | MySQL via Hyperdrive; bring your own database |
143
143
 
144
+ Use an object to also set how Drizzle names columns declared without a name:
145
+
146
+ ```json
147
+ {
148
+ "database": { "dialect": "pg", "casing": "snake_case" }
149
+ }
150
+ ```
151
+
152
+ | Key | Values | Description |
153
+ | --------- | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
154
+ | `dialect` | `"sqlite"` (default), `"pg"`, `"mysql"` | Database backend. `"sqlite"` is D1 |
155
+ | `casing` | `"snake_case"`, `"camelCase"` | [Drizzle casing](https://orm.drizzle.team/docs/sql-schema-declaration#camel-and-snake-casing) for `void/db` queries and `void db` commands. Omit to use each key as its column name |
156
+
144
157
  When using an external database:
145
158
 
146
159
  - Add `DATABASE_URL` to `.env` for local development
@@ -22,6 +22,10 @@ Void automatically detects which Cloudflare resources your project uses by scann
22
22
 
23
23
  Auth detection also triggers when importing the `auth` specifier from `void/client` or a framework-specific client subpath such as `void/client/react` (but not when importing only `fetch`).
24
24
 
25
+ Static bracket access such as `c.env['KV']` and destructured properties such as
26
+ `const { DB, KV: cache } = c.env` are also detected. For keys chosen at runtime,
27
+ use [explicit binding overrides](#explicit-binding-overrides).
28
+
25
29
  Durable state is inferred from files in `durable-objects/`. For example, `durable-objects/shopping-cart.ts` creates the `SHOPPING_CART` binding, exports `ShoppingCartDurableObject`, and records its migration. See [Durable State](../guide/durable-state.md).
26
30
 
27
31
  ## Scanned Directories
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "void",
3
- "version": "1.1.12",
3
+ "version": "1.2.1",
4
4
  "description": "Full-stack framework and deployment CLI for Cloudflare Workers, powered by Vite.",
5
5
  "homepage": "https://void.cloud",
6
6
  "bugs": {
@@ -340,23 +340,23 @@
340
340
  }
341
341
  },
342
342
  "dependencies": {
343
- "@cloudflare/build-output-utils": "^0.9.2",
344
- "@cloudflare/codemods": "^0.5.0",
345
- "@cloudflare/config": "^0.26.0",
346
- "@cloudflare/sandbox": "^1.0.1",
343
+ "@cloudflare/build-output-utils": "^0.9.3",
344
+ "@cloudflare/codemods": "^0.5.1",
345
+ "@cloudflare/config": "^0.27.0",
346
+ "@cloudflare/sandbox": "^1.0.2",
347
347
  "@cloudflare/vite-plugin": "^1.64.0",
348
- "@cloudflare/workers-auth": "^0.14.0",
349
- "@cloudflare/workers-types": "^5.20261014.1",
350
- "@napi-rs/keyring": "^2.1.1",
351
- "@void/deploy-cloudflare": "1.1.12",
352
- "@void/deploy-core": "1.1.12",
353
- "@void/edge": "1.1.12",
354
- "@void/isr": "1.1.12",
355
- "@void/platform": "1.1.12",
356
- "better-auth": "^1.7.7",
348
+ "@cloudflare/workers-auth": "^0.14.1",
349
+ "@cloudflare/workers-types": "^5.20261019.1",
350
+ "@napi-rs/keyring": "^2.1.2",
351
+ "@void/deploy-cloudflare": "1.2.1",
352
+ "@void/deploy-core": "1.2.1",
353
+ "@void/edge": "1.2.1",
354
+ "@void/isr": "1.2.1",
355
+ "@void/platform": "1.2.1",
356
+ "better-auth": "^1.7.11",
357
357
  "better-sqlite3": "^13.0.3",
358
358
  "blake3-jit": "^1.1.0",
359
- "cf": "^1.0.0-beta.17",
359
+ "cf": ">=1.0.0-beta.18 <1.0.0-beta.19",
360
360
  "drizzle-arktype": "^0.1.3",
361
361
  "drizzle-kit": "^0.31.11",
362
362
  "drizzle-orm": "^0.45.4",
@@ -368,22 +368,22 @@
368
368
  "jiti": "^2.7.0",
369
369
  "jsonc-parser": "^3.3.1",
370
370
  "mime": "^4.1.1",
371
- "miniflare": "5.20261012.0-beta",
371
+ "miniflare": "^5.20261012.1-beta",
372
372
  "minimatch": "^10.2.6",
373
373
  "mysql2": "^3.24.6",
374
374
  "pg": "^8.23.1",
375
- "postal-mime": "^4.0.5",
375
+ "postal-mime": "^4.0.11",
376
376
  "proper-lockfile": "^4.1.2",
377
377
  "terminal-link": "^5.0.0",
378
378
  "yaml": "^2.9.1"
379
379
  },
380
380
  "devDependencies": {
381
- "@electric-sql/pglite": "0.5.9",
381
+ "@electric-sql/pglite": "0.5.10",
382
382
  "@types/better-sqlite3": "^9.6.0",
383
383
  "@types/node": "^26.6.5",
384
384
  "@types/pg": "^8.23.1",
385
385
  "@types/proper-lockfile": "^4.1.4",
386
- "@voidzero-dev/vite-plus-prompts": "1.2.0",
386
+ "@voidzero-dev/vite-plus-prompts": "1.3.0",
387
387
  "arktype": "^2.2.8",
388
388
  "ci-info": "^4.4.0",
389
389
  "estree-walker": "^3.0.3",
@@ -396,12 +396,12 @@
396
396
  "tinyglobby": "^0.2.17",
397
397
  "typescript": "7.0.2",
398
398
  "valibot": "^1.5.0",
399
- "vite": "npm:@voidzero-dev/vite-plus-core@1.2.0",
400
- "vite-plus": "1.2.0",
399
+ "vite": "npm:@voidzero-dev/vite-plus-core@1.3.0",
400
+ "vite-plus": "1.3.0",
401
401
  "zod": "^4.6.7"
402
402
  },
403
403
  "peerDependencies": {
404
- "@void/md": "1.1.12",
404
+ "@void/md": "1.2.1",
405
405
  "arktype": ">=2.0.0",
406
406
  "valibot": ">=1.0.0-beta.7",
407
407
  "vite": "^8.0.0",
@@ -1,4 +1,4 @@
1
- FROM node:26.10.0-trixie-slim
2
- COPY --from=docker.io/cloudflare/sandbox:1.0.1 /usr/local/bin/sandbox-shim /usr/local/bin/sandbox-shim
1
+ FROM node:26.12.1-trixie-slim
2
+ COPY --from=docker.io/cloudflare/sandbox:1.0.2 /usr/local/bin/sandbox-shim /usr/local/bin/sandbox-shim
3
3
  WORKDIR /workspace
4
4
  CMD ["sleep", "infinity"]
package/schema.json CHANGED
@@ -392,9 +392,29 @@
392
392
  "additionalProperties": false
393
393
  },
394
394
  "database": {
395
- "type": "string",
396
- "enum": ["pg", "mysql"],
397
- "description": "Database backend. Omit for D1 (SQLite, default). Set to \"pg\" for PostgreSQL or \"mysql\" for MySQL via Hyperdrive."
395
+ "description": "Database backend. Omit for D1 (SQLite, default). Set to \"pg\" for PostgreSQL or \"mysql\" for MySQL via Hyperdrive, or use an object to also set the column casing.",
396
+ "oneOf": [
397
+ {
398
+ "type": "string",
399
+ "enum": ["pg", "mysql"]
400
+ },
401
+ {
402
+ "type": "object",
403
+ "properties": {
404
+ "dialect": {
405
+ "type": "string",
406
+ "enum": ["sqlite", "pg", "mysql"],
407
+ "description": "Database backend. Defaults to \"sqlite\" (D1)."
408
+ },
409
+ "casing": {
410
+ "type": "string",
411
+ "enum": ["snake_case", "camelCase"],
412
+ "description": "Drizzle casing: how columns declared without a name are named in the database, for queries and generated migrations."
413
+ }
414
+ },
415
+ "additionalProperties": false
416
+ }
417
+ ]
398
418
  },
399
419
  "ai": {
400
420
  "type": "object",
@@ -1 +0,0 @@
1
- export { t as prepareCfBuildOutput } from "./cf-build-output-ChEKWan2.mjs";
@@ -1,16 +0,0 @@
1
- import { n as getOwnVersion } from "./agents-CuNtT0D_.mjs";
2
- import { readFileSync } from "node:fs";
3
- //#region src/cli/cf-user-agent.ts
4
- let voidUserAgent;
5
- let cfCliVersion;
6
- function getVoidUserAgent() {
7
- if (voidUserAgent === void 0) voidUserAgent = `void/${getOwnVersion()}`;
8
- return voidUserAgent;
9
- }
10
- /** cf prepends `cf-cli/` to CLI_VERSION for both API requests and uploads. */
11
- function getCfCliVersion(attribution) {
12
- if (cfCliVersion === void 0) cfCliVersion = `${JSON.parse(readFileSync(new URL(import.meta.resolve("cf/package.json")), "utf8")).version} ${getVoidUserAgent()}`;
13
- return attribution ? `${cfCliVersion} ${attribution}` : cfCliVersion;
14
- }
15
- //#endregion
16
- export { getVoidUserAgent as n, getCfCliVersion as t };
@@ -1 +0,0 @@
1
- export { r as PlatformClient } from "./client-BdzxubTS.mjs";
@@ -1,2 +0,0 @@
1
- import "./deploy-transport-B3mtEi_q.mjs";
2
- export { i as checkWranglerMigrationApplySet, t as parseRootWranglerConfig, r as runDeploy } from "./deploy-D1gIPiAq.mjs";
@@ -1 +0,0 @@
1
- export { r as runGenCommand } from "./gen-CYN3wiov.mjs";
@@ -1 +0,0 @@
1
- export { r as printHelpPage } from "./help-B2sFwn9b.mjs";
@@ -1 +0,0 @@
1
- export { r as selectPlatformLoginMethod } from "./login-f2eu2TQh.mjs";
@@ -1 +0,0 @@
1
- export { n as runMigrateCommand } from "./migrate-DYfdWBXt.mjs";
@@ -1 +0,0 @@
1
- export { a as runOperatorCommand } from "./operator-cmd-DCr_QGMH.mjs";
@@ -1 +0,0 @@
1
- export { t as parsePlatformArgs } from "./platform-args-B7ke06up.mjs";
@@ -1 +0,0 @@
1
- export { t as prepareProject } from "./prepare-DepAGBcV.mjs";
@@ -1 +0,0 @@
1
- export { n as inferDefaultSlug } from "./resolve-project-WpwkCB_c.mjs";
@@ -1 +0,0 @@
1
- export { b as readRootWranglerConfig } from "./wrangler-C9XSzrju.mjs";