void 0.21.2 → 0.21.4

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 (184) hide show
  1. package/dist/{account-cmd-D8OC-U7y.mjs → account-cmd-DGt9cpRe.mjs} +4 -4
  2. package/dist/{agents-gni4eqBu.mjs → agents-B_pX_HmQ.mjs} +1 -1
  3. package/dist/ast-CPGPjb0V.mjs +18 -0
  4. package/dist/{auth-CAw7zHqj.mjs → auth-CZuiVsFh.mjs} +1 -1
  5. package/dist/{auth-B9_D6ygs.mjs → auth-DLNN0D3Z.mjs} +4 -4
  6. package/dist/{auth-link-BYFeMJAp.mjs → auth-link-Cl9vOuf7.mjs} +4 -4
  7. package/dist/{auth-router-OHZNmrb_.mjs → auth-router-D4ZcMUSf.mjs} +6 -6
  8. package/dist/{better-auth-shared-BoVwA5Vm.d.mts → better-auth-shared-BVkjZ3vM.d.mts} +1 -0
  9. package/dist/{better-auth-shared-syGYYmnY.mjs → better-auth-shared-rsBGBvWJ.mjs} +3 -6
  10. package/dist/{build-cmd-Bft7EY51.mjs → build-cmd-Dpt0jd-x.mjs} +4 -4
  11. package/dist/{cache-CKV1Gz2w.mjs → cache-7_UeZdTk.mjs} +4 -4
  12. package/dist/{cancel-deploy-BAKmkX4f.mjs → cancel-deploy-D23R1RXT.mjs} +3 -3
  13. package/dist/{cf-access-rAZxzMkL.mjs → cf-access-P0iZnu0q.mjs} +1 -1
  14. package/dist/{cf-build-output-CTdlo6Rt.mjs → cf-build-output-CGT03qCD.mjs} +2 -2
  15. package/dist/cli/cf-compat.mjs +2 -2
  16. package/dist/cli/cli.mjs +47 -43
  17. package/dist/cli/env-schema-probe.mjs +3 -3
  18. package/dist/client-4cDVv7BO.mjs +2 -0
  19. package/dist/{client-PdAJ-F0t.mjs → client-QTl6ko_D.mjs} +28 -5
  20. package/dist/{cloudflare-auth-BCmTc1X_.mjs → cloudflare-auth-B9jPCkV2.mjs} +1 -1
  21. package/dist/{cloudflare-cmd-D6PrKn7o.mjs → cloudflare-cmd-BjNxR1XF.mjs} +3 -3
  22. package/dist/{cloudflare-connect-DloREDlc.mjs → cloudflare-connect-CCUozPOe.mjs} +3 -3
  23. package/dist/{cloudflare-operations-BHNJVDbN.mjs → cloudflare-operations-BipGMJ5O.mjs} +1 -1
  24. package/dist/{cloudflare-operations-CPEdHYhM.mjs → cloudflare-operations-sMZXpk_S.mjs} +4 -4
  25. package/dist/collect-DLyFDiKW.mjs +2 -0
  26. package/dist/{collect-DXHNWHcT.mjs → collect-DiTn9yr6.mjs} +1 -1
  27. package/dist/config-0acf1oys.mjs +2 -0
  28. package/dist/{config-DywxBLQC.d.mts → config-CF69HgXc.d.mts} +7 -0
  29. package/dist/{config-Dxr6cTXn.mjs → config-CafTW6Cz.mjs} +12 -1
  30. package/dist/{config-BSe70f4T.mjs → config-D8MOgiQV.mjs} +3 -3
  31. package/dist/config-DPByhVck.mjs +32 -0
  32. package/dist/config-entry.d.mts +1 -1
  33. package/dist/{config--T87TD8T.mjs → config-s7Xj7tPb.mjs} +1 -1
  34. package/dist/{config-write-y3CBI_ux.mjs → config-write-BSduPMY8.mjs} +3 -3
  35. package/dist/{connect-DLx1pRYk.mjs → connect-4Ph5Y0QE.mjs} +7 -7
  36. package/dist/{create-project-JV9-6ICF.mjs → create-project-BniEV0OW.mjs} +1 -1
  37. package/dist/{create-project-BZBl_gQ0.mjs → create-project-DBfFSZKY.mjs} +4 -4
  38. package/dist/{db-B98_UV4H.mjs → db-CTXIWD42.mjs} +123 -55
  39. package/dist/{delete-BEEyqlwd.mjs → delete-D6dZ9B6B.mjs} +4 -4
  40. package/dist/deploy-BVwow28d.mjs +2 -0
  41. package/dist/{deploy-Bsymb0_c.mjs → deploy-F1exK5F4.mjs} +567 -263
  42. package/dist/discover-AMCBXivQ.mjs +2 -0
  43. package/dist/{discover-C4O6YxVS.mjs → discover-BcPPiF1o.mjs} +2 -2
  44. package/dist/{dist-4WkAWhWx.mjs → dist-BVqXeR_h.mjs} +9 -1
  45. package/dist/dist-_UUlL6bg.mjs +2 -0
  46. package/dist/{domain-Av2AkLQP.mjs → domain-Dmhvb2oU.mjs} +4 -4
  47. package/dist/{email-C5kaZXzJ.mjs → email--tEtMoj_.mjs} +1 -1
  48. package/dist/{email-CUqa6TtH.mjs → email-BxHabktK.mjs} +9 -9
  49. package/dist/{entry-DdRFGK0y.mjs → entry-CF5wvH4w.mjs} +4 -21
  50. package/dist/{env-D4RIGEzz.mjs → env-Csi-tMbT.mjs} +7 -7
  51. package/dist/{env-Yz4HcvHs.mjs → env-D5liuQYR.mjs} +5 -2
  52. package/dist/{env-DX_v-Q-v.mjs → env-_v349JBd.mjs} +1 -1
  53. package/dist/{env-types-CWDtqHgw.mjs → env-types-C2_bIk_b.mjs} +2 -2
  54. package/dist/{env-validation-BsFEXps5.mjs → env-validation-BB4GkLxn.mjs} +4 -4
  55. package/dist/{env-validation-DIDGM7h4.mjs → env-validation-BXge7uyK.mjs} +1 -1
  56. package/dist/{gen-pg-Ojg8Y.mjs → gen-Dz3X1Qab.mjs} +8 -8
  57. package/dist/gen-Vnv2f65C.mjs +2 -0
  58. package/dist/{generate-C0VY6RVf.mjs → generate-GDbL7sUr.mjs} +2 -2
  59. package/dist/{github-cmd-BEK4VprE.mjs → github-cmd-BED3_9JD.mjs} +4 -4
  60. package/dist/{headers-B_HBMgi0.mjs → headers-BOg_velo.mjs} +2 -2
  61. package/dist/{help-iQOt7WHk.mjs → help-DC7gdz7L.mjs} +7 -3
  62. package/dist/help-DQMfeKMz.mjs +2 -0
  63. package/dist/index.mjs +132 -158
  64. package/dist/{init-D5niUPAz.mjs → init-CRGDXzVC.mjs} +105 -289
  65. package/dist/{link-3lGrfXzd.mjs → link-CsHOinF7.mjs} +5 -5
  66. package/dist/{list-CVjGr_C6.mjs → list-CDb-4bZ1.mjs} +5 -5
  67. package/dist/{local-d1-DzykTWY8.mjs → local-d1-CC8sKFGu.mjs} +3 -3
  68. package/dist/{login-BgQJzxAl.mjs → login-BQyISZuW.mjs} +3 -3
  69. package/dist/login-r2gL8l7B.mjs +2 -0
  70. package/dist/{logs-DbzD-QDf.mjs → logs-BdfiOezj.mjs} +4 -4
  71. package/dist/{migrate-BV8qHiCb.mjs → migrate-B8KuoYsO.mjs} +69 -44
  72. package/dist/migrate-TsHGBnDA.mjs +2 -0
  73. package/dist/{node-Cupyf7-s.mjs → node-BM43oz4G.mjs} +5 -5
  74. package/dist/{operator-auth-BkVgJqv-.mjs → operator-auth-8KnOVXVd.mjs} +2 -2
  75. package/dist/{operator-client-A0iex2yi.mjs → operator-client-DUwumHpQ.mjs} +2 -2
  76. package/dist/{operator-cmd-CR6Lxzt0.mjs → operator-cmd-Co-PeaeD.mjs} +6 -6
  77. package/dist/{package-json-iCbMg5XF.mjs → package-json-DXfiT1jV.mjs} +1 -1
  78. package/dist/pages/index.d.mts +1 -1
  79. package/dist/pages/index.mjs +11 -6
  80. package/dist/pages/islands-plugin.d.mts +271 -1
  81. package/dist/pages/islands-plugin.mjs +95 -18
  82. package/dist/parse-filename-DioPHiR9.mjs +77 -0
  83. package/dist/{platform-auth-config-De7BqRJm.mjs → platform-auth-config-TSw8edHw.mjs} +5 -5
  84. package/dist/{platform-auth-protection-Dcat-6zu.mjs → platform-auth-protection-Ba1XqGhn.mjs} +6 -6
  85. package/dist/{platform-auth-recovery-C9gsM640.mjs → platform-auth-recovery-BkT3EsF2.mjs} +5 -5
  86. package/dist/{platform-cmd-Cl9Uhzru.mjs → platform-cmd-C8OqhqPt.mjs} +1 -1
  87. package/dist/{platform-cmd-CudokNIg.mjs → platform-cmd-CRSKfu8k.mjs} +5 -5
  88. package/dist/{platform-domain-Ckpd2kXw.mjs → platform-domain-j9YCXRm6.mjs} +3 -3
  89. package/dist/{platform-lifecycle-DVzM2T4j.mjs → platform-lifecycle-78H0XQUA.mjs} +277 -229
  90. package/dist/{platform-lifecycle-DlpiGcjr.mjs → platform-lifecycle-DDc9zCeJ.mjs} +1 -1
  91. package/dist/{platform-management-ibuS1as0.mjs → platform-management-6w8-DUjC.mjs} +2 -2
  92. package/dist/{platform-management-44Bxd3YC.mjs → platform-management-DzKNsMlt.mjs} +1 -1
  93. package/dist/{platform-recovery-D_KmvdSk.mjs → platform-recovery-Do8VOyDE.mjs} +3 -3
  94. package/dist/{platform-registry-BJbgZLS1.mjs → platform-registry-QBa4DK32.mjs} +1 -1
  95. package/dist/{plugin-inference-DsvtJLll.mjs → plugin-inference-BMfKRSqE.mjs} +188 -85
  96. package/dist/prepare-BZXkjdNe.mjs +2 -0
  97. package/dist/{prepare-pcWcxSCh.mjs → prepare-C3kt3Rst.mjs} +11 -11
  98. package/dist/{prepare-_T-Haxrr.mjs → prepare-DyZ-Yok5.mjs} +1 -1
  99. package/dist/{prerender-render-Cf_WDE9W.mjs → prerender-render-D9qbLs2f.mjs} +1 -1
  100. package/dist/prerender-render.mjs +1 -1
  101. package/dist/{preset-Dowh9tTt.mjs → preset-UHj9ARyP.mjs} +4 -4
  102. package/dist/{project-BEBFDFLz.mjs → project-BuUwfj6f.mjs} +1 -1
  103. package/dist/{project-CWNIPoXc.mjs → project-C0Fqu05O.mjs} +2 -2
  104. package/dist/{project-cmd-BuF9doku.mjs → project-cmd-B44I8J_W.mjs} +15 -15
  105. package/dist/{project-paths-CKQ-Q5JS.mjs → project-paths-GgcMozYz.mjs} +1 -1
  106. package/dist/{project-team-B1Tia8vd.mjs → project-team-BkbYIsXN.mjs} +4 -4
  107. package/dist/{project-token-Bwxjf4y6.mjs → project-token-C8xEEQnB.mjs} +4 -4
  108. package/dist/{project-tsconfig-CwfqUnVp.mjs → project-tsconfig-B8GeM0RM.mjs} +2 -2
  109. package/dist/{provision-Cck2m3jJ.mjs → provision-BhreDAOS.mjs} +141 -78
  110. package/dist/provision-DNtrtaVD.mjs +3 -0
  111. package/dist/{requests-CphRF98D.mjs → requests-DFyhBMaf.mjs} +3 -3
  112. package/dist/{resolve-project-Xvis70DG.mjs → resolve-project-BG5ORGID.mjs} +1 -1
  113. package/dist/resolve-project-DtbidV4y.mjs +2 -0
  114. package/dist/{rollback-BYHJV2yD.mjs → rollback-DHHxXZiS.mjs} +4 -4
  115. package/dist/{route-types-Id82-veQ.mjs → route-types-Clm4WD0B.mjs} +39 -16
  116. package/dist/{runner-CQs_cDSG.mjs → runner-B8wXwWlo.mjs} +1 -1
  117. package/dist/{runner-mysql-1o47achK.mjs → runner-mysql-CEG5JozK.mjs} +1 -1
  118. package/dist/{runner-mysql-BhwMk2Bm.mjs → runner-mysql-DmWchSWJ.mjs} +1 -1
  119. package/dist/{runner-BGVsGgkb.mjs → runner-p-dMs2UN.mjs} +3 -3
  120. package/dist/{runner-pg-D7z01mQS.mjs → runner-pg-Bh4AgZdj.mjs} +1 -1
  121. package/dist/{runner-pg-CJ_JeGF6.mjs → runner-pg-D4OPlil-.mjs} +1 -1
  122. package/dist/runtime/better-auth-mysql.d.mts +1 -1
  123. package/dist/runtime/better-auth-mysql.mjs +1 -1
  124. package/dist/runtime/better-auth-pg.d.mts +1 -1
  125. package/dist/runtime/better-auth-pg.mjs +1 -1
  126. package/dist/runtime/better-auth.d.mts +1 -1
  127. package/dist/runtime/better-auth.mjs +2 -2
  128. package/dist/runtime/db.mjs +8 -5
  129. package/dist/runtime/durable.mjs +1 -1
  130. package/dist/runtime/email/testing.mjs +1 -1
  131. package/dist/runtime/env-public.mjs +1 -1
  132. package/dist/runtime/env.d.mts +1 -1
  133. package/dist/runtime/env.mjs +1 -1
  134. package/dist/runtime/kv.mjs +1 -1
  135. package/dist/runtime/live-server.mjs +38 -23
  136. package/dist/runtime/queues.mjs +1 -1
  137. package/dist/runtime/sandbox.mjs +1 -1
  138. package/dist/runtime/storage.mjs +1 -1
  139. package/dist/runtime/ws-server.d.mts +1 -1
  140. package/dist/runtime/ws-server.mjs +1 -1
  141. package/dist/{scan-DJbooZm2.mjs → scan-4tfN-PSn.mjs} +113 -99
  142. package/dist/{scan-DdDvRCU1.mjs → scan-ClYmX3sa.mjs} +35 -137
  143. package/dist/{secret-Rt9c4Ttw.mjs → secret-DN9sSNiV.mjs} +6 -6
  144. package/dist/{skills-B-690E7h.mjs → skills-O6FUaizK.mjs} +2 -2
  145. package/dist/sveltekit.mjs +1 -1
  146. package/dist/{validate-qNhV00PD.mjs → validate-CIUwFpjB.mjs} +2 -2
  147. package/dist/validate-EKmJWxmy.mjs +2 -0
  148. package/dist/{wrangler-D01qs6VB.mjs → wrangler-BymcxrRa.mjs} +3 -3
  149. package/dist/{yarn-pnp-CVEc3gE7.mjs → yarn-pnp-BV4AzNul.mjs} +1 -1
  150. package/package.json +7 -7
  151. package/schema.json +18 -0
  152. package/skills/void/docs/guide/app-types.md +1 -1
  153. package/skills/void/docs/guide/auth.md +2 -2
  154. package/skills/void/docs/guide/database/d1.md +6 -0
  155. package/skills/void/docs/guide/durable-state.md +1 -1
  156. package/skills/void/docs/guide/edge/rewrites.md +2 -3
  157. package/skills/void/docs/guide/env-migration.md +1 -1
  158. package/skills/void/docs/guide/pages-routing/markdown.md +1 -1
  159. package/skills/void/docs/guide/platform/development/local.md +1 -1
  160. package/skills/void/docs/guide/platform/installation/prerequisites.md +2 -2
  161. package/skills/void/docs/guide/platform/installation/setup.md +1 -1
  162. package/skills/void/docs/guide/server-routing.md +2 -3
  163. package/skills/void/docs/guide/ssr.md +4 -10
  164. package/skills/void/docs/guide/websockets.md +1 -1
  165. package/skills/void/docs/integrations/cloudflare.md +3 -0
  166. package/skills/void/docs/reference/api.md +1 -1
  167. package/skills/void/docs/reference/cli.md +10 -3
  168. package/skills/void/docs/reference/config.md +11 -0
  169. package/skills/void/docs/reference/resource-inference.md +1 -1
  170. package/dist/client-DAAivdid.mjs +0 -2
  171. package/dist/collect-DAUItMDS.mjs +0 -2
  172. package/dist/config-DDIFxQYx.mjs +0 -2
  173. package/dist/config-uP7ZDtVZ.mjs +0 -21
  174. package/dist/deploy-CsjbRNyv.mjs +0 -2
  175. package/dist/discover-BBzDZe_o.mjs +0 -2
  176. package/dist/dist-D7-nEOXi.mjs +0 -2
  177. package/dist/gen-B87rlalt.mjs +0 -2
  178. package/dist/help-r_vrpH_d.mjs +0 -2
  179. package/dist/login-Bz0zEPoy.mjs +0 -2
  180. package/dist/migrate-BXY3B3m7.mjs +0 -2
  181. package/dist/prepare-D4CkM3_v.mjs +0 -2
  182. package/dist/provision-CNgEBkVA.mjs +0 -3
  183. package/dist/resolve-project-BTotl8Nn.mjs +0 -2
  184. package/dist/validate-DqJ33oHj.mjs +0 -2
@@ -1,8 +1,8 @@
1
- import { a as join, n as dirname, o as normalize, t as basename, u as resolve$2 } from "./dist-4WkAWhWx.mjs";
2
- import { R as persistCloudflareConfig, _ as readProvisionedBindingEntry, k as writeProvisionedWranglerConfig, s as assertNoDuplicateMembers } from "./wrangler-D01qs6VB.mjs";
1
+ import { a as join, n as dirname, o as normalize, t as basename, u as resolve$2 } from "./dist-BVqXeR_h.mjs";
2
+ import { R as persistCloudflareConfig, _ as readProvisionedBindingEntry, k as writeProvisionedWranglerConfig, s as assertNoDuplicateMembers } from "./wrangler-BymcxrRa.mjs";
3
3
  import { i as voidWarn, r as voidLog } from "./log-ChfPKsVd.mjs";
4
4
  import { r as scanWranglerDotenvKeys } from "./dotenv-VQxupEUv.mjs";
5
- import { o as resolveWranglerArgv } from "./preset-Dowh9tTt.mjs";
5
+ import { o as resolveWranglerArgv } from "./preset-UHj9ARyP.mjs";
6
6
  import { createRequire } from "node:module";
7
7
  import { closeSync, existsSync, fsyncSync, lstatSync, openSync, readFileSync, readlinkSync, realpathSync, renameSync, unlinkSync, writeSync } from "node:fs";
8
8
  import { randomUUID } from "node:crypto";
@@ -20,7 +20,7 @@ import lockfile from "proper-lockfile";
20
20
  * identifier — the SAME predicate the provisioner's read-first uses:
21
21
  * - D1 `database_id` is a real UUID ({@link isRealD1Id}, not `'local'`);
22
22
  * - KV `id` is a real 32-hex ({@link isRealKvId}, not `'local'`);
23
- * - R2 `bucket_name` names a real bucket ({@link isRealStoredR2BucketName}, not `'default'`);
23
+ * - R2 `bucket_name` names a real bucket ({@link isRealStoredR2BucketName});
24
24
  * - Hyperdrive `id` is a real 32-hex ({@link isRealHyperdriveId}).
25
25
  *
26
26
  * Queues are NAME-bearing (no id in the config), so they are NOT part of this
@@ -51,7 +51,7 @@ function checkCloudflareProvisionDrift(configPath, desired) {
51
51
  name: kv.title
52
52
  });
53
53
  if (desired.r2) {
54
- if (!isProvisioned("r2_buckets", desired.r2.binding, (e) => isRealStoredR2BucketName(e.bucket_name))) missing.push({
54
+ if (!isProvisioned("r2_buckets", desired.r2.binding, (e) => isRealStoredR2BucketName(e.bucket_name, desired.r2?.bucketName))) missing.push({
55
55
  binding: desired.r2.binding,
56
56
  kind: "r2",
57
57
  name: desired.r2.bucketName
@@ -104,12 +104,13 @@ function isValidR2BucketNameFormat(value) {
104
104
  }
105
105
  /**
106
106
  * A STORED R2 `bucket_name` that names a REAL bucket, i.e. any non-empty string
107
- * that is not R2's own placeholder (`default`). `local` IS a real name here. Grammar is
107
+ * other than the placeholder (`default`), unless `default` itself is desired.
108
+ * `local` IS a real name here. Grammar is
108
109
  * deliberately not required: a grammar-invalid stored name that contradicts the desired
109
110
  * bucket must still fail closed as a contradiction, never be silently rewritten.
110
111
  */
111
- function isRealStoredR2BucketName(value) {
112
- return typeof value === "string" && value.length > 0 && value !== R2_BUCKET_NAME_PLACEHOLDER;
112
+ function isRealStoredR2BucketName(value, desiredName) {
113
+ return typeof value === "string" && value.length > 0 && (value !== R2_BUCKET_NAME_PLACEHOLDER || value === desiredName);
113
114
  }
114
115
  const defaultLogger = {
115
116
  info: (msg) => voidLog(msg),
@@ -626,10 +627,13 @@ function createDefaultRunWrangler(root, options) {
626
627
  const child = spawn(command, [...prefix, ...args], {
627
628
  cwd: opts.cwd ?? root,
628
629
  shell: false,
629
- env: provisionEnv({
630
- accountId: opts.accountId,
631
- apiBaseUrl: opts.apiBaseUrl
632
- }),
630
+ env: {
631
+ ...provisionEnv({
632
+ accountId: opts.accountId,
633
+ apiBaseUrl: opts.apiBaseUrl
634
+ }),
635
+ ...opts.suppressLogs ? { WRANGLER_WRITE_LOGS: "false" } : {}
636
+ },
633
637
  stdio: [
634
638
  "ignore",
635
639
  "pipe",
@@ -2114,71 +2118,20 @@ async function provisionWithProcessSlot(root, rootWranglerPath, desired, opts) {
2114
2118
  await lock.release();
2115
2119
  return result;
2116
2120
  }
2117
- /**
2118
- * The provision body, run entirely UNDER the whole-provision lock (see
2119
- * {@link provisionCloudflareResources}). `configPath` is the ONE resolved absolute
2120
- * config path the lock is keyed on — threaded through read-first, wrangler `-c`, and
2121
- * the writer so reads/writes can never hit different files.
2122
- */
2123
- async function provisionCloudflareResourcesLocked(root, configPath, desired, opts) {
2124
- if (existsSync(configPath)) {
2125
- const raw = readFileSync(configPath, "utf-8");
2126
- const content = raw.startsWith(UTF8_BOM) ? raw.slice(1) : raw;
2127
- assertNoDuplicateMembers(content, configPath);
2128
- }
2129
- if (desired.d1) assertValidResourceName("d1", desired.d1.name);
2130
- for (const { title } of desired.kvNamespaces) assertValidResourceName("kvTitle", title);
2131
- if (desired.r2) assertValidResourceName("r2", desired.r2.bucketName);
2132
- if (desired.hyperdrive) assertValidResourceName("hyperdrive", desired.hyperdrive.name);
2133
- for (const queueName of desired.queues) assertValidResourceName("queue", queueName);
2134
- const rootConfig = readRootConfig(configPath);
2135
- const rawConfigAccountId = rootConfig.account_id;
2136
- const configAccountId = typeof rawConfigAccountId === "string" && rawConfigAccountId.length > 0 ? rawConfigAccountId : void 0;
2137
- const rawComplianceRegion = rootConfig.compliance_region;
2138
- if (rawComplianceRegion !== void 0 && typeof rawComplianceRegion !== "string") throw new Error(`provision: "${configPath}" has a non-string "compliance_region"; it must be "public" or "fedramp_high". Fix the config and retry.`);
2139
- const configComplianceRegion = typeof rawComplianceRegion === "string" ? rawComplianceRegion : void 0;
2140
- if (configAccountId && opts?.accountId && configAccountId !== opts.accountId) throw new Error(`provision: Cloudflare account mismatch — "${configPath}" pins account_id ${JSON.stringify(configAccountId)} but deploy requested ${JSON.stringify(opts.accountId)}. Reconcile them (correct or remove the config's account_id, or deploy to the pinned account) and retry.`);
2141
- const ambientAccountId = typeof process.env.CLOUDFLARE_ACCOUNT_ID === "string" && process.env.CLOUDFLARE_ACCOUNT_ID.length > 0 ? process.env.CLOUDFLARE_ACCOUNT_ID : void 0;
2142
- const effectiveAccountId = configAccountId ?? opts?.accountId ?? ambientAccountId;
2143
- const log = opts?.log ?? defaultLogger;
2144
- const resources = [];
2145
- const write = (patch) => writeProvisionedWranglerConfig(root, patch, { configPath });
2146
- const persistCreatedConfig = () => {
2147
- if (basename(configPath) === ".void-wrangler.jsonc") persistCloudflareConfig(dirname(configPath));
2148
- };
2149
- const hasRemoteWork = !!desired.d1 || desired.kvNamespaces.length > 0 || !!desired.r2 || !!desired.hyperdrive || desired.queues.length > 0;
2150
- if (hasRemoteWork && !effectiveAccountId) throw new Error("provision: no Cloudflare account is resolvable — set \"account_id\" in your root wrangler config or export CLOUDFLARE_ACCOUNT_ID before deploying. Refusing to provision resources without a pinned account (wrangler would otherwise fall back to an ambient/interactive account that is never persisted, so a later retry could rebind them elsewhere).");
2151
- if (hasRemoteWork) assertNoTransportRedirectInProjectDotenv(root);
2152
- if (desired.hyperdrive && !opts?.listHyperdriveConfigs) {
2153
- const { binding, name, connectionString } = desired.hyperdrive;
2154
- const entry = readBindingEntry(configPath, "hyperdrive", binding);
2155
- if (!(entry !== void 0 && isRealHyperdriveId(entry.id)) && !resolveHyperdriveApiToken(opts?.apiToken)) {
2156
- if (connectionString) throw new Error(`provision: Hyperdrive config ${JSON.stringify(name)} is not in "${configPath}" yet, and creating it needs a Cloudflare API token. wrangler exposes no machine-readable Hyperdrive list, so Void checks the account over the Cloudflare REST API, which a Cloudflare browser OAuth cannot authenticate. Without that check a create would silently duplicate an existing same-named config, so nothing was provisioned. Either (a) export CLOUDFLARE_API_TOKEN with Hyperdrive edit permission and rerun, or (b) create the Hyperdrive config yourself (dashboard / "wrangler hyperdrive create") and add its id to the ${JSON.stringify(binding)} hyperdrive binding in "${configPath}" — deploying an already-provisioned Hyperdrive needs no token.`);
2157
- throw new Error(`provision: Hyperdrive config ${JSON.stringify(name)} is not in "${configPath}" yet, and there is no DATABASE_URL to create it from. Nothing was provisioned. Either (a) export DATABASE_URL with your PostgreSQL connection string and rerun (Void reads it from the shell — a value in .env/.env.local is NOT used here, so it never ships as a plaintext worker var), or (b) create the Hyperdrive config yourself (dashboard / "wrangler hyperdrive create") and add its id to the ${JSON.stringify(binding)} hyperdrive binding in "${configPath}" — deploying an already-provisioned Hyperdrive needs neither DATABASE_URL nor an API token.`);
2158
- }
2159
- }
2160
- let accountIdWritten = false;
2161
- if (effectiveAccountId && configAccountId !== effectiveAccountId) {
2162
- write({ accountId: effectiveAccountId });
2163
- accountIdWritten = true;
2164
- }
2165
- const transportAccountId = effectiveAccountId;
2166
- const transportApiBaseUrl = resolvePinnedApiBaseUrl(process.env, configComplianceRegion);
2167
- const selectedRunWrangler = opts?.runWrangler ?? createDefaultRunWrangler(root);
2168
- const redactSecrets = createSecretRedactor(desired.hyperdrive?.connectionString);
2169
- const redactResult = (result) => ({
2170
- ...result,
2171
- stdout: redactSecrets(result.stdout),
2172
- stderr: redactSecrets(result.stderr),
2173
- error: result.error != null ? redactSecrets(result.error) : result.error
2174
- });
2175
- const runWrangler = (args, callOpts) => Promise.resolve(selectedRunWrangler(args, {
2176
- ...callOpts,
2177
- accountId: transportAccountId,
2178
- apiBaseUrl: transportApiBaseUrl
2179
- })).then(redactResult, (error) => {
2180
- throw redactRejection(error, redactSecrets);
2121
+ async function enableD1ReadReplicationViaApi(context, token, fetchImpl = fetch) {
2122
+ const response = await fetchImpl(`${context.apiBaseUrl}/accounts/${context.accountId}/d1/database/${context.databaseId}`, {
2123
+ method: "PUT",
2124
+ headers: {
2125
+ Authorization: `Bearer ${token}`,
2126
+ "Content-Type": "application/json"
2127
+ },
2128
+ body: JSON.stringify({ read_replication: { mode: "auto" } }),
2129
+ signal: AbortSignal.timeout(15e3)
2181
2130
  });
2131
+ const envelope = await response.json().catch(() => null);
2132
+ if (!response.ok || envelope?.success !== true) throw new Error(`provision: could not enable D1 read replication for database ${context.databaseId} (Cloudflare API status ${response.status}). The credential needs D1 Edit permission.`);
2133
+ }
2134
+ async function reconcileD1(desired, configPath, runWrangler, write, persistCreatedConfig, resources, log, transportAccountId, transportApiBaseUrl, opts) {
2182
2135
  if (desired.d1) {
2183
2136
  const { binding, name } = desired.d1;
2184
2137
  const migrationsDir = desired.d1.migrationsDir ?? D1_MIGRATIONS_DIR;
@@ -2301,7 +2254,40 @@ async function provisionCloudflareResourcesLocked(root, configPath, desired, opt
2301
2254
  } else throw new Error(`provision: "wrangler d1 create ${name}" failed: ${created.stderr || created.stdout}`);
2302
2255
  }
2303
2256
  }
2257
+ const databaseId = readBindingEntry(configPath, "d1_databases", binding)?.database_id;
2258
+ if (!isRealD1Id(databaseId)) throw new Error(`provision: D1 binding ${binding} has no real database id after setup.`);
2259
+ const context = {
2260
+ databaseId,
2261
+ accountId: transportAccountId,
2262
+ apiBaseUrl: transportApiBaseUrl
2263
+ };
2264
+ if (opts?.enableD1ReadReplication) await opts.enableD1ReadReplication(context);
2265
+ else {
2266
+ let token = opts?.apiToken ?? process.env.CLOUDFLARE_API_TOKEN;
2267
+ if (!token) {
2268
+ const auth = await runWrangler([
2269
+ "auth",
2270
+ "token",
2271
+ "--json",
2272
+ ...wranglerConfigArgs(configPath)
2273
+ ], {
2274
+ captureJson: true,
2275
+ suppressLogs: true
2276
+ });
2277
+ const start = auth.stdout.indexOf("{");
2278
+ const end = auth.stdout.lastIndexOf("}");
2279
+ let parsed;
2280
+ if (isCleanSuccess(auth) && start >= 0 && end > start) try {
2281
+ parsed = JSON.parse(auth.stdout.slice(start, end + 1));
2282
+ } catch {}
2283
+ if ((parsed?.type === "oauth" || parsed?.type === "api_token") && typeof parsed.token === "string") token = parsed.token;
2284
+ }
2285
+ if (!token) throw new Error("provision: D1 read replication requires a Cloudflare API bearer with D1 Edit permission. Log in with `wrangler login` or set CLOUDFLARE_API_TOKEN, then retry.");
2286
+ await enableD1ReadReplicationViaApi(context, token);
2287
+ }
2304
2288
  }
2289
+ }
2290
+ async function reconcileKv(desired, configPath, runWrangler, write, persistCreatedConfig, resources, log) {
2305
2291
  for (const { binding, title } of desired.kvNamespaces) {
2306
2292
  const entry = readBindingEntry(configPath, "kv_namespaces", binding);
2307
2293
  if (entry && isRealKvId(entry.id)) {
@@ -2374,11 +2360,13 @@ async function provisionCloudflareResourcesLocked(root, configPath, desired, opt
2374
2360
  });
2375
2361
  }
2376
2362
  }
2363
+ }
2364
+ async function reconcileR2(desired, configPath, runWrangler, write, persistCreatedConfig, resources, log) {
2377
2365
  if (desired.r2) {
2378
2366
  const { binding, bucketName } = desired.r2;
2379
2367
  const entry = readBindingEntry(configPath, "r2_buckets", binding);
2380
2368
  const storedBucketName = entry?.bucket_name;
2381
- if (entry && isRealStoredR2BucketName(storedBucketName)) {
2369
+ if (entry && isRealStoredR2BucketName(storedBucketName, bucketName)) {
2382
2370
  if (storedBucketName !== bucketName) throw new Error(`provision: R2 binding ${JSON.stringify(binding)} in "${configPath}" stores bucket_name ${JSON.stringify(storedBucketName)}, but this deploy wants bucket ${JSON.stringify(bucketName)}. bucket_name IS the R2 identity, so this entry contradicts the desired bucket. Fix "${configPath}" — correct the entry's bucket_name (or remove the entry to re-provision) — or rename the desired bucket, then retry.`);
2383
2371
  resources.push({
2384
2372
  kind: "r2",
@@ -2451,6 +2439,8 @@ async function provisionCloudflareResourcesLocked(root, configPath, desired, opt
2451
2439
  } else throw new Error(`provision: "wrangler r2 bucket info ${bucketName}" failed: ${info.stderr || info.stdout}. Cannot determine whether the bucket exists; refusing to create a possible duplicate.`);
2452
2440
  }
2453
2441
  }
2442
+ }
2443
+ async function reconcileHyperdrive(desired, configPath, runWrangler, write, persistCreatedConfig, resources, log, transportAccountId, transportApiBaseUrl, redactSecrets, opts) {
2454
2444
  if (desired.hyperdrive) {
2455
2445
  const { binding, name, connectionString } = desired.hyperdrive;
2456
2446
  const entry = readBindingEntry(configPath, "hyperdrive", binding);
@@ -2533,6 +2523,8 @@ async function provisionCloudflareResourcesLocked(root, configPath, desired, opt
2533
2523
  }
2534
2524
  }
2535
2525
  }
2526
+ }
2527
+ async function reconcileQueues(desired, configPath, runWrangler, resources) {
2536
2528
  for (const name of desired.queues) {
2537
2529
  const info = await runWrangler([
2538
2530
  "queues",
@@ -2568,6 +2560,77 @@ async function provisionCloudflareResourcesLocked(root, configPath, desired, opt
2568
2560
  action: "created"
2569
2561
  });
2570
2562
  }
2563
+ }
2564
+ /**
2565
+ * The provision body, run entirely UNDER the whole-provision lock (see
2566
+ * {@link provisionCloudflareResources}). `configPath` is the ONE resolved absolute
2567
+ * config path the lock is keyed on — threaded through read-first, wrangler `-c`, and
2568
+ * the writer so reads/writes can never hit different files.
2569
+ */
2570
+ async function provisionCloudflareResourcesLocked(root, configPath, desired, opts) {
2571
+ if (existsSync(configPath)) {
2572
+ const raw = readFileSync(configPath, "utf-8");
2573
+ const content = raw.startsWith(UTF8_BOM) ? raw.slice(1) : raw;
2574
+ assertNoDuplicateMembers(content, configPath);
2575
+ }
2576
+ if (desired.d1) assertValidResourceName("d1", desired.d1.name);
2577
+ for (const { title } of desired.kvNamespaces) assertValidResourceName("kvTitle", title);
2578
+ if (desired.r2) assertValidResourceName("r2", desired.r2.bucketName);
2579
+ if (desired.hyperdrive) assertValidResourceName("hyperdrive", desired.hyperdrive.name);
2580
+ for (const queueName of desired.queues) assertValidResourceName("queue", queueName);
2581
+ const rootConfig = readRootConfig(configPath);
2582
+ const rawConfigAccountId = rootConfig.account_id;
2583
+ const configAccountId = typeof rawConfigAccountId === "string" && rawConfigAccountId.length > 0 ? rawConfigAccountId : void 0;
2584
+ const rawComplianceRegion = rootConfig.compliance_region;
2585
+ if (rawComplianceRegion !== void 0 && typeof rawComplianceRegion !== "string") throw new Error(`provision: "${configPath}" has a non-string "compliance_region"; it must be "public" or "fedramp_high". Fix the config and retry.`);
2586
+ const configComplianceRegion = typeof rawComplianceRegion === "string" ? rawComplianceRegion : void 0;
2587
+ if (configAccountId && opts?.accountId && configAccountId !== opts.accountId) throw new Error(`provision: Cloudflare account mismatch — "${configPath}" pins account_id ${JSON.stringify(configAccountId)} but deploy requested ${JSON.stringify(opts.accountId)}. Reconcile them (correct or remove the config's account_id, or deploy to the pinned account) and retry.`);
2588
+ const ambientAccountId = typeof process.env.CLOUDFLARE_ACCOUNT_ID === "string" && process.env.CLOUDFLARE_ACCOUNT_ID.length > 0 ? process.env.CLOUDFLARE_ACCOUNT_ID : void 0;
2589
+ const effectiveAccountId = configAccountId ?? opts?.accountId ?? ambientAccountId;
2590
+ const log = opts?.log ?? defaultLogger;
2591
+ const resources = [];
2592
+ const write = (patch) => writeProvisionedWranglerConfig(root, patch, { configPath });
2593
+ const persistCreatedConfig = () => {
2594
+ if (basename(configPath) === ".void-wrangler.jsonc") persistCloudflareConfig(dirname(configPath));
2595
+ };
2596
+ const hasRemoteWork = !!desired.d1 || desired.kvNamespaces.length > 0 || !!desired.r2 || !!desired.hyperdrive || desired.queues.length > 0;
2597
+ if (hasRemoteWork && !effectiveAccountId) throw new Error("provision: no Cloudflare account is resolvable — set \"account_id\" in your root wrangler config or export CLOUDFLARE_ACCOUNT_ID before deploying. Refusing to provision resources without a pinned account (wrangler would otherwise fall back to an ambient/interactive account that is never persisted, so a later retry could rebind them elsewhere).");
2598
+ if (hasRemoteWork) assertNoTransportRedirectInProjectDotenv(root);
2599
+ if (desired.hyperdrive && !opts?.listHyperdriveConfigs) {
2600
+ const { binding, name, connectionString } = desired.hyperdrive;
2601
+ const entry = readBindingEntry(configPath, "hyperdrive", binding);
2602
+ if (!(entry !== void 0 && isRealHyperdriveId(entry.id)) && !resolveHyperdriveApiToken(opts?.apiToken)) {
2603
+ if (connectionString) throw new Error(`provision: Hyperdrive config ${JSON.stringify(name)} is not in "${configPath}" yet, and creating it needs a Cloudflare API token. wrangler exposes no machine-readable Hyperdrive list, so Void checks the account over the Cloudflare REST API, which a Cloudflare browser OAuth cannot authenticate. Without that check a create would silently duplicate an existing same-named config, so nothing was provisioned. Either (a) export CLOUDFLARE_API_TOKEN with Hyperdrive edit permission and rerun, or (b) create the Hyperdrive config yourself (dashboard / "wrangler hyperdrive create") and add its id to the ${JSON.stringify(binding)} hyperdrive binding in "${configPath}" — deploying an already-provisioned Hyperdrive needs no token.`);
2604
+ throw new Error(`provision: Hyperdrive config ${JSON.stringify(name)} is not in "${configPath}" yet, and there is no DATABASE_URL to create it from. Nothing was provisioned. Either (a) export DATABASE_URL with your PostgreSQL connection string and rerun (Void reads it from the shell — a value in .env/.env.local is NOT used here, so it never ships as a plaintext worker var), or (b) create the Hyperdrive config yourself (dashboard / "wrangler hyperdrive create") and add its id to the ${JSON.stringify(binding)} hyperdrive binding in "${configPath}" — deploying an already-provisioned Hyperdrive needs neither DATABASE_URL nor an API token.`);
2605
+ }
2606
+ }
2607
+ let accountIdWritten = false;
2608
+ if (effectiveAccountId && configAccountId !== effectiveAccountId) {
2609
+ write({ accountId: effectiveAccountId });
2610
+ accountIdWritten = true;
2611
+ }
2612
+ const transportAccountId = effectiveAccountId;
2613
+ const transportApiBaseUrl = resolvePinnedApiBaseUrl(process.env, configComplianceRegion);
2614
+ const selectedRunWrangler = opts?.runWrangler ?? createDefaultRunWrangler(root);
2615
+ const redactSecrets = createSecretRedactor(desired.hyperdrive?.connectionString);
2616
+ const redactResult = (result) => ({
2617
+ ...result,
2618
+ stdout: redactSecrets(result.stdout),
2619
+ stderr: redactSecrets(result.stderr),
2620
+ error: result.error != null ? redactSecrets(result.error) : result.error
2621
+ });
2622
+ const runWrangler = (args, callOpts) => Promise.resolve(selectedRunWrangler(args, {
2623
+ ...callOpts,
2624
+ accountId: transportAccountId,
2625
+ apiBaseUrl: transportApiBaseUrl
2626
+ })).then(redactResult, (error) => {
2627
+ throw redactRejection(error, redactSecrets);
2628
+ });
2629
+ await reconcileD1(desired, configPath, runWrangler, write, persistCreatedConfig, resources, log, transportAccountId, transportApiBaseUrl, opts);
2630
+ await reconcileKv(desired, configPath, runWrangler, write, persistCreatedConfig, resources, log);
2631
+ await reconcileR2(desired, configPath, runWrangler, write, persistCreatedConfig, resources, log);
2632
+ await reconcileHyperdrive(desired, configPath, runWrangler, write, persistCreatedConfig, resources, log, transportAccountId, transportApiBaseUrl, redactSecrets, opts);
2633
+ await reconcileQueues(desired, configPath, runWrangler, resources);
2571
2634
  return {
2572
2635
  resources,
2573
2636
  configPath,
@@ -2575,4 +2638,4 @@ async function provisionCloudflareResourcesLocked(root, configPath, desired, opt
2575
2638
  };
2576
2639
  }
2577
2640
  //#endregion
2578
- export { resolveProperLockfileKey as _, checkCloudflareProvisionDrift as a, isAlreadyGoneKillError as c, isRealD1Id as d, isRealKvId as f, resolvePinnedApiBaseUrl as g, provisionEnv as h, assertValidResourceName as i, isQuarantineError as l, provisionCloudflareResources as m, acquireProvisionLock as n, createDefaultRunWrangler as o, normalizeRunWranglerResult as p, assertNoTransportRedirectInProjectDotenv as r, deleteEnvVarCaseAware as s, WranglerQuarantineError as t, isQueueConfirmedAbsent as u };
2641
+ export { resolvePinnedApiBaseUrl as _, checkCloudflareProvisionDrift as a, enableD1ReadReplicationViaApi as c, isQueueConfirmedAbsent as d, isRealD1Id as f, provisionEnv as g, provisionCloudflareResources as h, assertValidResourceName as i, isAlreadyGoneKillError as l, normalizeRunWranglerResult as m, acquireProvisionLock as n, createDefaultRunWrangler as o, isRealKvId as p, assertNoTransportRedirectInProjectDotenv as r, deleteEnvVarCaseAware as s, WranglerQuarantineError as t, isQuarantineError as u, resolveProperLockfileKey as v };
@@ -0,0 +1,3 @@
1
+ import { r as scanWranglerDotenvKeys } from "./dotenv-VQxupEUv.mjs";
2
+ import { _ as resolvePinnedApiBaseUrl, a as checkCloudflareProvisionDrift, c as enableD1ReadReplicationViaApi, d as isQueueConfirmedAbsent, f as isRealD1Id, g as provisionEnv, h as provisionCloudflareResources, i as assertValidResourceName, l as isAlreadyGoneKillError, m as normalizeRunWranglerResult, n as acquireProvisionLock, o as createDefaultRunWrangler, p as isRealKvId, r as assertNoTransportRedirectInProjectDotenv, s as deleteEnvVarCaseAware, t as WranglerQuarantineError, u as isQuarantineError, v as resolveProperLockfileKey } from "./provision-BhreDAOS.mjs";
3
+ export { WranglerQuarantineError, acquireProvisionLock, assertNoTransportRedirectInProjectDotenv, assertValidResourceName, checkCloudflareProvisionDrift, createDefaultRunWrangler, deleteEnvVarCaseAware, enableD1ReadReplicationViaApi, isAlreadyGoneKillError, isQuarantineError, isQueueConfirmedAbsent, isRealD1Id, isRealKvId, normalizeRunWranglerResult, provisionCloudflareResources, provisionEnv, resolvePinnedApiBaseUrl, resolveProperLockfileKey, scanWranglerDotenvKeys };
@@ -1,8 +1,8 @@
1
1
  import { a as dim, c as import_picocolors, r as cliTitle } from "./output-CCH48AMM.mjs";
2
- import { c as getToken } from "./auth-B9_D6ygs.mjs";
3
- import { o as readProjectConfig } from "./project-CWNIPoXc.mjs";
2
+ import { c as getToken } from "./auth-DLNN0D3Z.mjs";
3
+ import { o as readProjectConfig } from "./project-C0Fqu05O.mjs";
4
4
  import { O as intro, P as outro, j as log } from "./dist-Dn6nn2IU.mjs";
5
- import { n as PlatformClient } from "./client-PdAJ-F0t.mjs";
5
+ import { n as PlatformClient } from "./client-QTl6ko_D.mjs";
6
6
  //#region src/cli/requests.ts
7
7
  async function runRequestsCommand(root, range, status) {
8
8
  console.log();
@@ -1,4 +1,4 @@
1
- import { a as join } from "./dist-4WkAWhWx.mjs";
1
+ import { a as join } from "./dist-BVqXeR_h.mjs";
2
2
  import { readFileSync } from "node:fs";
3
3
  //#region src/cli/resolve-project.ts
4
4
  function getRequestedProjectSlug(options) {
@@ -0,0 +1,2 @@
1
+ import { n as inferDefaultSlug } from "./resolve-project-BG5ORGID.mjs";
2
+ export { inferDefaultSlug };
@@ -1,8 +1,8 @@
1
1
  import { a as dim, c as import_picocolors, i as createSpinner, o as ensureUtc, r as cliTitle } from "./output-CCH48AMM.mjs";
2
- import { c as getToken } from "./auth-B9_D6ygs.mjs";
3
- import { i as readDeploymentPlatform, o as readProjectConfig } from "./project-CWNIPoXc.mjs";
2
+ import { c as getToken } from "./auth-DLNN0D3Z.mjs";
3
+ import { i as readDeploymentPlatform, o as readProjectConfig } from "./project-C0Fqu05O.mjs";
4
4
  import { E as confirm, I as select, O as intro, P as outro, T as cancel, W as isCancel, j as log } from "./dist-Dn6nn2IU.mjs";
5
- import { n as PlatformClient } from "./client-PdAJ-F0t.mjs";
5
+ import { n as PlatformClient } from "./client-QTl6ko_D.mjs";
6
6
  //#region src/cli/rollback.ts
7
7
  async function runRollbackCommand(root, deployId) {
8
8
  console.log();
@@ -83,7 +83,7 @@ async function runRollbackCommand(root, deployId) {
83
83
  outro(dim("Traffic is now serving the rolled-back deployment."));
84
84
  }
85
85
  async function runCloudflareRollback(root, deployId) {
86
- const { activateCloudflareExistingVersion, readCloudflareWorkerStatus, resolveCloudflareOperationContext } = await import("./cloudflare-operations-BHNJVDbN.mjs");
86
+ const { activateCloudflareExistingVersion, readCloudflareWorkerStatus, resolveCloudflareOperationContext } = await import("./cloudflare-operations-BipGMJ5O.mjs");
87
87
  const context = resolveCloudflareOperationContext(root);
88
88
  const status = await readCloudflareWorkerStatus(context);
89
89
  const deployedVersionIds = new Set(status.deployedVersionIds);
@@ -1,5 +1,5 @@
1
- import { a as join, l as relative } from "./dist-4WkAWhWx.mjs";
2
- import { r as writeFileIfChanged } from "./project-tsconfig-CwfqUnVp.mjs";
1
+ import { a as join, l as relative } from "./dist-BVqXeR_h.mjs";
2
+ import { r as writeFileIfChanged } from "./project-tsconfig-B8GeM0RM.mjs";
3
3
  import { mkdirSync } from "node:fs";
4
4
  //#region src/codegen/db-types.ts
5
5
  const DRIZZLE_OPERATORS = "sql, eq, ne, gt, gte, lt, lte, and, or, not, desc, asc, like, ilike, notLike, inArray, notInArray, isNull, isNotNull, between, notBetween, exists, notExists, count, sum, avg, min, max";
@@ -214,15 +214,30 @@ function generateRouteTypes(scan, routesDir, outDir, pagesDir) {
214
214
  lines.push(" }[keyof PageActionMap]");
215
215
  lines.push("");
216
216
  lines.push(" interface RouteMap {");
217
- for (const route of scan.routes) {
218
- if (route.methods.length === 0) continue;
219
- const absRoutePath = `${routesDir}/${route.filePath}`;
220
- const importPath = relative(outDir, absRoutePath);
221
- lines.push(` ${JSON.stringify(route.pattern)}: {`);
222
- for (const method of route.methods) {
217
+ const routesByPattern = /* @__PURE__ */ new Map();
218
+ for (const route of scan.routes) for (const method of route.methods) {
219
+ let methods = routesByPattern.get(route.pattern);
220
+ if (!methods) {
221
+ methods = /* @__PURE__ */ new Map();
222
+ routesByPattern.set(route.pattern, methods);
223
+ }
224
+ let sources = methods.get(method);
225
+ if (!sources) {
226
+ sources = [];
227
+ methods.set(method, sources);
228
+ }
229
+ sources.push(route);
230
+ }
231
+ for (const [pattern, methods] of routesByPattern) {
232
+ lines.push(` ${JSON.stringify(pattern)}: {`);
233
+ for (const [method, sources] of methods) {
234
+ const imports = sources.map((route) => {
235
+ const importPath = relative(outDir, `${routesDir}/${route.filePath}`);
236
+ return `(typeof import(${JSON.stringify(importPath)}))["${method}"]`;
237
+ });
223
238
  lines.push(` ${method}: {`);
224
- lines.push(` input: ExtractInput<(typeof import(${JSON.stringify(importPath)}))["${method}"]["__validators"]>;`);
225
- lines.push(` output: Serialize<Awaited<(typeof import(${JSON.stringify(importPath)}))["${method}"]["__output"]>>;`);
239
+ lines.push(` input: ${imports.map((source) => `ExtractInput<${source}["__validators"]>`).join(" & ")};`);
240
+ lines.push(` output: ${imports.map((source) => `Serialize<Awaited<${source}["__output"]>>`).join(" | ")};`);
226
241
  lines.push(" };");
227
242
  }
228
243
  lines.push(" };");
@@ -230,13 +245,21 @@ function generateRouteTypes(scan, routesDir, outDir, pagesDir) {
230
245
  lines.push(" }");
231
246
  lines.push("");
232
247
  lines.push(" interface WebSocketRouteMap {");
248
+ const websocketsByPattern = /* @__PURE__ */ new Map();
233
249
  for (const route of scan.websockets ?? []) {
234
- const absRoutePath = `${routesDir}/${route.filePath}`;
235
- const importPath = relative(outDir, absRoutePath);
236
- lines.push(` ${JSON.stringify(route.pattern)}: {`);
237
- lines.push(` params: RouteParams<${JSON.stringify(route.params)}>;`);
238
- lines.push(` client: ExtractInput<(typeof import(${JSON.stringify(importPath)}))["default"]["messages"]["client"]>;`);
239
- lines.push(` server: ExtractOutput<(typeof import(${JSON.stringify(importPath)}))["default"]["messages"]["server"]>;`);
250
+ const sources = websocketsByPattern.get(route.pattern) ?? [];
251
+ sources.push(route);
252
+ websocketsByPattern.set(route.pattern, sources);
253
+ }
254
+ for (const [pattern, sources] of websocketsByPattern) {
255
+ const imports = sources.map((route) => {
256
+ const importPath = relative(outDir, `${routesDir}/${route.filePath}`);
257
+ return `(typeof import(${JSON.stringify(importPath)}))["default"]["messages"]`;
258
+ });
259
+ lines.push(` ${JSON.stringify(pattern)}: {`);
260
+ lines.push(` params: RouteParams<${JSON.stringify(sources[0].params)}>;`);
261
+ lines.push(` client: ${imports.map((source) => `ExtractInput<${source}["client"]>`).join(" & ")};`);
262
+ lines.push(` server: ${imports.map((source) => `ExtractOutput<${source}["server"]>`).join(" | ")};`);
240
263
  lines.push(" };");
241
264
  }
242
265
  lines.push(" }");
@@ -1,2 +1,2 @@
1
- import { i as openSqliteDatabase, n as getAppliedMigrations, o as runMigrations, r as getMiniflareDatabasePath, t as getApplicationTables } from "./runner-BGVsGgkb.mjs";
1
+ import { i as openSqliteDatabase, n as getAppliedMigrations, o as runMigrations, r as getMiniflareDatabasePath, t as getApplicationTables } from "./runner-p-dMs2UN.mjs";
2
2
  export { getApplicationTables, getAppliedMigrations, getMiniflareDatabasePath, openSqliteDatabase, runMigrations };
@@ -1,2 +1,2 @@
1
- import { i as runMySqlMigrations, n as getMySqlAppliedMigrations, t as applyMySqlMigrations } from "./runner-mysql-BhwMk2Bm.mjs";
1
+ import { i as runMySqlMigrations, n as getMySqlAppliedMigrations, t as applyMySqlMigrations } from "./runner-mysql-DmWchSWJ.mjs";
2
2
  export { applyMySqlMigrations, getMySqlAppliedMigrations, runMySqlMigrations };
@@ -1,4 +1,4 @@
1
- import { t as collectMigrations } from "./collect-DXHNWHcT.mjs";
1
+ import { t as collectMigrations } from "./collect-DiTn9yr6.mjs";
2
2
  //#region src/migrations/runner-mysql.ts
3
3
  async function readMySqlAppliedMigrations(client) {
4
4
  try {
@@ -1,6 +1,6 @@
1
- import { a as join, n as dirname } from "./dist-4WkAWhWx.mjs";
2
- import { n as hasPackageDependency, r as readNearestPackageJson } from "./package-json-iCbMg5XF.mjs";
3
- import { t as collectMigrations } from "./collect-DXHNWHcT.mjs";
1
+ import { a as join, n as dirname } from "./dist-BVqXeR_h.mjs";
2
+ import { n as hasPackageDependency, r as readNearestPackageJson } from "./package-json-DXfiT1jV.mjs";
3
+ import { t as collectMigrations } from "./collect-DiTn9yr6.mjs";
4
4
  import { a as classifyMigration } from "./plan-BEZ8VJW0.mjs";
5
5
  import { existsSync, mkdirSync } from "node:fs";
6
6
  import { createHash, createHmac } from "node:crypto";
@@ -1,2 +1,2 @@
1
- import { i as runPgMigrations, n as getPgAppliedMigrations, t as applyPgMigrations } from "./runner-pg-CJ_JeGF6.mjs";
1
+ import { i as runPgMigrations, n as getPgAppliedMigrations, t as applyPgMigrations } from "./runner-pg-D4OPlil-.mjs";
2
2
  export { applyPgMigrations, getPgAppliedMigrations, runPgMigrations };
@@ -1,4 +1,4 @@
1
- import { t as collectMigrations } from "./collect-DXHNWHcT.mjs";
1
+ import { t as collectMigrations } from "./collect-DiTn9yr6.mjs";
2
2
  //#region src/migrations/runner-pg.ts
3
3
  async function readPgAppliedMigrations(client) {
4
4
  try {
@@ -1,4 +1,4 @@
1
- import { i as VoidAuthRuntimeOptions, n as VoidAuthEnv, r as VoidAuthRuntimeApi, t as VoidAuthDialect } from "../better-auth-shared-BoVwA5Vm.mjs";
1
+ import { i as VoidAuthRuntimeOptions, n as VoidAuthEnv, r as VoidAuthRuntimeApi, t as VoidAuthDialect } from "../better-auth-shared-BVkjZ3vM.mjs";
2
2
  //#region src/runtime/better-auth-mysql.d.ts
3
3
  export declare const resolveVoidAuthOptions: VoidAuthRuntimeApi["resolveVoidAuthOptions"];
4
4
  export declare const createVoidAuth: VoidAuthRuntimeApi["createVoidAuth"];
@@ -1,5 +1,5 @@
1
1
  import { t as applyMySqlAuthMigrations } from "../auth-migrations-9vif1uj8.mjs";
2
- import { t as createVoidAuthRuntime } from "../better-auth-shared-syGYYmnY.mjs";
2
+ import { t as createVoidAuthRuntime } from "../better-auth-shared-rsBGBvWJ.mjs";
3
3
  //#region src/runtime/better-auth-mysql.ts
4
4
  function resolveConnectionString(env) {
5
5
  const connectionString = typeof env.DATABASE_URL === "string" && env.DATABASE_URL.length > 0 ? env.DATABASE_URL : typeof env.HYPERDRIVE?.connectionString === "string" && env.HYPERDRIVE.connectionString.length > 0 ? env.HYPERDRIVE.connectionString : void 0;
@@ -1,4 +1,4 @@
1
- import { i as VoidAuthRuntimeOptions, n as VoidAuthEnv, r as VoidAuthRuntimeApi, t as VoidAuthDialect } from "../better-auth-shared-BoVwA5Vm.mjs";
1
+ import { i as VoidAuthRuntimeOptions, n as VoidAuthEnv, r as VoidAuthRuntimeApi, t as VoidAuthDialect } from "../better-auth-shared-BVkjZ3vM.mjs";
2
2
  //#region src/runtime/better-auth-pg.d.ts
3
3
  export declare const resolveVoidAuthOptions: VoidAuthRuntimeApi["resolveVoidAuthOptions"];
4
4
  export declare const createVoidAuth: VoidAuthRuntimeApi["createVoidAuth"];
@@ -1,5 +1,5 @@
1
1
  import { n as applyPgAuthMigrations } from "../auth-migrations-9vif1uj8.mjs";
2
- import { t as createVoidAuthRuntime } from "../better-auth-shared-syGYYmnY.mjs";
2
+ import { t as createVoidAuthRuntime } from "../better-auth-shared-rsBGBvWJ.mjs";
3
3
  import { t as disablePgPassFallback } from "../pg-J2HbZIkX.mjs";
4
4
  //#region src/runtime/better-auth-pg.ts
5
5
  function resolveConnectionString(env) {
@@ -1,4 +1,4 @@
1
- import { i as VoidAuthRuntimeOptions, n as VoidAuthEnv, r as VoidAuthRuntimeApi, t as VoidAuthDialect } from "../better-auth-shared-BoVwA5Vm.mjs";
1
+ import { i as VoidAuthRuntimeOptions, n as VoidAuthEnv, r as VoidAuthRuntimeApi, t as VoidAuthDialect } from "../better-auth-shared-BVkjZ3vM.mjs";
2
2
  //#region src/runtime/better-auth.d.ts
3
3
  export declare const resolveVoidAuthOptions: VoidAuthRuntimeApi["resolveVoidAuthOptions"];
4
4
  export declare const createVoidAuth: VoidAuthRuntimeApi["createVoidAuth"];
@@ -1,10 +1,10 @@
1
1
  import { r as applySqliteAuthMigrations } from "../auth-migrations-9vif1uj8.mjs";
2
- import { t as createVoidAuthRuntime } from "../better-auth-shared-syGYYmnY.mjs";
2
+ import { t as createVoidAuthRuntime } from "../better-auth-shared-rsBGBvWJ.mjs";
3
3
  //#region src/runtime/better-auth.ts
4
4
  async function resolveDatabase(env) {
5
5
  if (!env.DB) throw new Error("auth: Better Auth requires the \"DB\" D1 binding for sqlite apps.");
6
6
  return {
7
- database: env.DB,
7
+ database: env.DB.withSession("first-primary"),
8
8
  async dispose() {}
9
9
  };
10
10
  }
@@ -1,4 +1,4 @@
1
- import { a as requireRuntimeBinding } from "../env-Yz4HcvHs.mjs";
1
+ import { a as requireRuntimeBinding, r as getRuntimeRequestResource } from "../env-D5liuQYR.mjs";
2
2
  import { drizzle } from "drizzle-orm/d1";
3
3
  import { and, asc, avg, between, count, desc, eq, exists, gt, gte, ilike, inArray, isNotNull, isNull, like, lt, lte, max, min, ne, not, notBetween, notExists, notInArray, notLike, or, sql, sum } from "drizzle-orm";
4
4
  //#region src/runtime/db.ts
@@ -14,17 +14,20 @@ import { and, asc, avg, between, count, desc, eq, exists, gt, gte, ilike, inArra
14
14
  * Use this when you have multiple D1 databases or need a non-default binding.
15
15
  */
16
16
  function createDb(d1) {
17
- return drizzle(d1);
17
+ return drizzle(d1.withSession("first-unconstrained"));
18
18
  }
19
- let _instance;
19
+ function createPrimaryDb(d1) {
20
+ return drizzle(d1.withSession("first-primary"));
21
+ }
22
+ const requestDbKey = {};
20
23
  /**
21
24
  * Default Drizzle D1 instance — resolves the `DB` binding from the runtime
22
25
  * environment. When the Void plugin is active, this is replaced with a
23
26
  * schema-aware instance via virtual module.
24
27
  */
25
28
  const db = new Proxy({}, { get(_, prop) {
26
- _instance ??= drizzle(requireRuntimeBinding("DB"));
27
- return Reflect.get(_instance, prop);
29
+ const instance = getRuntimeRequestResource(requestDbKey, () => createDb(requireRuntimeBinding("DB")), () => createPrimaryDb(requireRuntimeBinding("DB")));
30
+ return Reflect.get(instance, prop);
28
31
  } });
29
32
  //#endregion
30
33
  export { and, asc, avg, between, count, createDb, db, desc, eq, exists, gt, gte, ilike, inArray, isNotNull, isNull, like, lt, lte, max, min, ne, not, notBetween, notExists, notInArray, notLike, or, sql, sum };
@@ -1,4 +1,4 @@
1
- import { a as requireRuntimeBinding, o as withRuntimeEnv } from "../env-Yz4HcvHs.mjs";
1
+ import { a as requireRuntimeBinding, o as withRuntimeEnv } from "../env-D5liuQYR.mjs";
2
2
  import { DurableObject } from "cloudflare:workers";
3
3
  //#region src/runtime/durable.ts
4
4
  const DEFAULT_STORAGE_KEY = "__void_durable_state";
@@ -1,6 +1,6 @@
1
1
  import { i as normalizeEmail, r as buildMime } from "../../mime-D5Nmdzf7.mjs";
2
2
  import { y as registerEmailSink } from "../../dev-inbox-P0u4tM8Y.mjs";
3
- import { n as compileEmailPattern, t as compareEmailRoutes } from "../../email-C5kaZXzJ.mjs";
3
+ import { n as compileEmailPattern, t as compareEmailRoutes } from "../../email--tEtMoj_.mjs";
4
4
  import { i as createMessageProxy, n as MAX_INBOUND_HEADERS, t as MAX_INBOUND_BYTES } from "../../inbound-aVHEUhKo.mjs";
5
5
  //#region src/runtime/email/testing.ts
6
6
  /**
@@ -1,5 +1,5 @@
1
1
  import { a as getRawRuntimeEnv } from "../env-raw-Cx8ElDdj.mjs";
2
- import { i as isInternalBinding, n as getRuntimeEnv } from "../env-Yz4HcvHs.mjs";
2
+ import { i as isInternalBinding, n as getRuntimeEnv } from "../env-D5liuQYR.mjs";
3
3
  import { a as oneOf, i as number, n as email, o as string, r as json, s as url, t as boolean } from "../env-helpers--wFmQ_5Q.mjs";
4
4
  //#region src/shared/env-mask.ts
5
5
  /**
@@ -4,7 +4,7 @@ type RuntimeEnv = Record<string, unknown>;
4
4
  //#endregion
5
5
  //#region src/runtime/env.d.ts
6
6
  /** @internal Reuse a resource only within the current runtime request. */
7
- export declare function getRuntimeRequestResource<T>(key: object, initialize: () => T): T;
7
+ export declare function getRuntimeRequestResource<T>(key: object, initialize: () => T, outsideScope?: () => T): T;
8
8
  export declare function withRuntimeEnv<T>(env: unknown, fn: () => T): T;
9
9
  /**
10
10
  * Shared internal-binding predicate. A binding is framework-internal — and must
@@ -1,2 +1,2 @@
1
- import { a as requireRuntimeBinding, i as isInternalBinding, n as getRuntimeEnv, o as withRuntimeEnv, r as getRuntimeRequestResource, t as getRuntimeBinding } from "../env-Yz4HcvHs.mjs";
1
+ import { a as requireRuntimeBinding, i as isInternalBinding, n as getRuntimeEnv, o as withRuntimeEnv, r as getRuntimeRequestResource, t as getRuntimeBinding } from "../env-D5liuQYR.mjs";
2
2
  export { getRuntimeBinding, getRuntimeEnv, getRuntimeRequestResource, isInternalBinding, requireRuntimeBinding, withRuntimeEnv };
@@ -1,4 +1,4 @@
1
- import { a as requireRuntimeBinding } from "../env-Yz4HcvHs.mjs";
1
+ import { a as requireRuntimeBinding } from "../env-D5liuQYR.mjs";
2
2
  //#region src/runtime/kv.ts
3
3
  function parseValue(raw) {
4
4
  if (raw === null) return null;