void 0.7.13 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/dist/{agents-DqkFfc2c.mjs → agents-Dkgafwfr.mjs} +1 -1
  2. package/dist/{auth-cmd-bS88H4Lb.mjs → auth-cmd-B1-7r6ng.mjs} +3 -3
  3. package/dist/{better-auth-shared-D2JaoCs4.mjs → better-auth-shared-CbAF6sOM.mjs} +1 -1
  4. package/dist/{better-auth-shared-HXlHRw02.d.mts → better-auth-shared-Fzyk5yS1.d.mts} +2 -7
  5. package/dist/{cache-DUDCNty6.mjs → cache-CGYC-2LW.mjs} +5 -5
  6. package/dist/{cancel-deploy-DOuSbPwX.mjs → cancel-deploy-B4j31z7d.mjs} +4 -4
  7. package/dist/canonical-json-CEyQaVDa.mjs +13 -0
  8. package/dist/cli/cli.mjs +44 -31
  9. package/dist/{client-C_DYiXeu.mjs → client-C-nH6yz3.mjs} +5 -5
  10. package/dist/{collect-HqAuilH6.mjs → collect-9rO3JFNM.mjs} +1 -1
  11. package/dist/{config-DyUSwbeX.mjs → config--wXmVOoe.mjs} +10 -8
  12. package/dist/{config-CeRQg3Lz.mjs → config-BVEC0lti.mjs} +11 -2
  13. package/dist/{config-CvHtTM0q.mjs → config-hhMYPVRT.mjs} +3 -12
  14. package/dist/{create-project-hvFe6rbI.mjs → create-project-BGnQMy5N.mjs} +44 -18
  15. package/dist/{db-YEYSTfGw.mjs → db-CT5Xg6ds.mjs} +42 -37
  16. package/dist/{delete-XyM_VD9o.mjs → delete-eMGTHHB9.mjs} +5 -5
  17. package/dist/{deploy-CPAEgVQm.mjs → deploy-7EA_lKq9.mjs} +169 -99
  18. package/dist/{discover-CKGQpis8.mjs → discover-C8N1I4tK.mjs} +9 -6
  19. package/dist/{domain-Dvj7u8tr.mjs → domain-UfLrp2vc.mjs} +64 -22
  20. package/dist/{drizzle-Cx7cVwrE.mjs → drizzle-DmaANP4-.mjs} +1 -1
  21. package/dist/{env-Bjl0rzuf.mjs → env-Cvdbbm_N.mjs} +7 -7
  22. package/dist/{env-helpers-Dw95CU8e.d.mts → env-helpers-Bt9yYg5I.d.mts} +1 -1
  23. package/dist/{env-types-BSQghXbx.mjs → env-types-D6qI1ThV.mjs} +8 -19
  24. package/dist/{env-validation-Buy5pe3u.mjs → env-validation-DBJsxZLz.mjs} +4 -4
  25. package/dist/{gen-DU8NIdrH.mjs → gen-Cn2hZ8RR.mjs} +37 -31
  26. package/dist/{handler-DJTuxB10.d.mts → handler-BPhL8AmU.d.mts} +3 -3
  27. package/dist/{headers-CuVHn6Kl.mjs → headers-wAPJigtE.mjs} +3 -3
  28. package/dist/index.d.mts +3 -3
  29. package/dist/index.mjs +273 -104
  30. package/dist/{init-Br5DTaG7.mjs → init-DL6syXuF.mjs} +43 -31
  31. package/dist/{link-DdXqlUiJ.mjs → link-C5x1E-XZ.mjs} +5 -5
  32. package/dist/{list-9Bxa5Odn.mjs → list-ezL7hqDV.mjs} +5 -5
  33. package/dist/{login-C_MfDjhu.mjs → login-CkLr-AaI.mjs} +3 -3
  34. package/dist/{logs-DjqCpEER.mjs → logs-MnGILmLz.mjs} +4 -4
  35. package/dist/{mcp-vA0880_K.mjs → mcp-B84MmVAW.mjs} +3 -3
  36. package/dist/{node-gxRQXIRT.mjs → node-fpywdcbN.mjs} +6 -6
  37. package/dist/{output-D3g5otMC.mjs → output-DeiS4oEX.mjs} +1 -1
  38. package/dist/pages/client.d.mts +1 -1
  39. package/dist/pages/head-client.d.mts +1 -1
  40. package/dist/pages/head.d.mts +1 -1
  41. package/dist/pages/index.d.mts +28 -3
  42. package/dist/pages/index.mjs +6 -5
  43. package/dist/pages/islands-plugin.d.mts +1 -1
  44. package/dist/pages/islands-plugin.mjs +7 -5
  45. package/dist/pages/protocol.d.mts +2 -2
  46. package/dist/pages/protocol.mjs +1 -1
  47. package/dist/{pathe.M-eThtNZ-D-kmWkCS.mjs → pathe.M-eThtNZ-BrPhGF_K.mjs} +1 -1
  48. package/dist/plan-aD3wRDqF.mjs +271 -0
  49. package/dist/{plugin-inference-BexV6LL3.mjs → plugin-inference-Ba1uGdIy.mjs} +26 -20
  50. package/dist/{prepare-BEkH89oX.mjs → prepare-BrAISonG.mjs} +29 -19
  51. package/dist/{preset-CYQh93UF.mjs → preset-BRsCi8ZB.mjs} +10 -8
  52. package/dist/{project-DhB4A8_g.mjs → project-CH9pdo16.mjs} +1 -1
  53. package/dist/{project-cmd-CeXO06hG.mjs → project-cmd-JQUzv3qF.mjs} +10 -10
  54. package/dist/project-paths-CCMrHYQm.mjs +100 -0
  55. package/dist/{project-slug-KRvHQEQI.mjs → project-slug-De4UjtD9.mjs} +0 -1
  56. package/dist/{project-tsconfig-Bfy55qvs.mjs → project-tsconfig-HAGjfY6w.mjs} +10 -5
  57. package/dist/{protocol-D7r_deVZ.d.mts → protocol-mcSsdMij.d.mts} +3 -3
  58. package/dist/providers--_pvxpNN.d.mts +7 -0
  59. package/dist/{resolve-project-DdjLQ2tB.mjs → resolve-project-CNpUbUHd.mjs} +1 -1
  60. package/dist/{rollback-C8OSMxmq.mjs → rollback-CoAAvC18.mjs} +4 -4
  61. package/dist/{route-types-qVL-v-CB.mjs → route-types-jxRfWuCb.mjs} +1 -1
  62. package/dist/{runner-C0d3lJo1.mjs → runner-BkGBfr4e.mjs} +4 -2
  63. package/dist/{runner-pg-Bd_172vF.mjs → runner-pg-BXP0JpHW.mjs} +1 -1
  64. package/dist/runtime/ai.mjs +2 -2
  65. package/dist/runtime/auth.d.mts +1 -1
  66. package/dist/runtime/better-auth-pg.d.mts +1 -1
  67. package/dist/runtime/better-auth-pg.mjs +2 -2
  68. package/dist/runtime/better-auth.d.mts +1 -1
  69. package/dist/runtime/better-auth.mjs +2 -2
  70. package/dist/runtime/client.d.mts +2 -2
  71. package/dist/runtime/client.mjs +1 -1
  72. package/dist/runtime/env-helpers.d.mts +1 -1
  73. package/dist/runtime/env-public-client.d.mts +1 -1
  74. package/dist/runtime/env-public.d.mts +2 -2
  75. package/dist/runtime/env-public.mjs +1 -1
  76. package/dist/runtime/env.mjs +1 -1
  77. package/dist/runtime/fetch-stream.d.mts +1 -1
  78. package/dist/runtime/fetch-stream.mjs +1 -1
  79. package/dist/runtime/fetch.d.mts +1 -1
  80. package/dist/runtime/fetch.mjs +1 -1
  81. package/dist/runtime/handler.d.mts +1 -1
  82. package/dist/runtime/handler.mjs +1 -1
  83. package/dist/runtime/isr.mjs +1 -1
  84. package/dist/runtime/live.d.mts +2 -2
  85. package/dist/runtime/live.mjs +1 -1
  86. package/dist/runtime/migration-handler.d.mts +33 -1
  87. package/dist/runtime/migration-handler.mjs +332 -24
  88. package/dist/runtime/remote/index.mjs +1 -1
  89. package/dist/runtime/sandbox.d.mts +73 -3
  90. package/dist/runtime/sandbox.mjs +239 -3
  91. package/dist/runtime/validator.d.mts +1 -1
  92. package/dist/runtime/ws-server.d.mts +2 -2
  93. package/dist/runtime/ws.d.mts +3 -3
  94. package/dist/{scan-CKpylFj9.mjs → scan-2YmJkYAf.mjs} +4 -3
  95. package/dist/{scan-CkK1Hzpa.mjs → scan-DzzHqtiT.mjs} +82 -43
  96. package/dist/{secret-NDvlqAN2.mjs → secret-mz8t_CML.mjs} +5 -5
  97. package/dist/{skills-SAG0WyVn.mjs → skills-B_ynF4lA.mjs} +3 -3
  98. package/dist/{subcommand-prompt-q9T06dpg.mjs → subcommand-prompt-CPuV7tPW.mjs} +2 -2
  99. package/dist/sveltekit.mjs +1 -1
  100. package/dist/{validate-DW3ViKTA.mjs → validate-CNWm-PsL.mjs} +49 -9
  101. package/dist/{yarn-pnp-6LD6_3Ej.mjs → yarn-pnp-QgEYVC3V.mjs} +1 -1
  102. package/package.json +3 -2
  103. package/schema.json +5 -0
  104. package/skills/void/docs/guide/ai.md +1 -1
  105. package/skills/void/docs/guide/app-types.md +1 -1
  106. package/skills/void/docs/guide/database/postgresql.md +1 -1
  107. package/skills/void/docs/guide/edge/headers.md +1 -1
  108. package/skills/void/docs/guide/edge/static-assets.md +34 -0
  109. package/skills/void/docs/guide/sandboxes.md +3 -2
  110. package/skills/void/docs/guide/ssr.md +25 -2
  111. package/skills/void/docs/integrations/cloudflare.md +5 -3
  112. package/skills/void/docs/integrations/frameworks/overview.md +1 -1
  113. package/skills/void/docs/integrations/nodejs-bun-deno.md +10 -9
  114. package/skills/void/docs/reference/api.md +204 -13
  115. package/skills/void/docs/reference/cli.md +52 -6
  116. package/skills/void/docs/reference/config.md +27 -4
  117. package/skills/void/docs/reference/resource-inference.md +1 -1
  118. /package/dist/{auth-DmuALf16.d.mts → auth-SfRBhXan.d.mts} +0 -0
  119. /package/dist/{auth-migrations-BwLPwRgH.mjs → auth-migrations-BqJoGqGQ.mjs} +0 -0
  120. /package/dist/{cf-access-BW8K93Fm.mjs → cf-access-DKDsgwOU.mjs} +0 -0
  121. /package/dist/{defer-2ARBu8Et.mjs → defer-DkoEwda-.mjs} +0 -0
  122. /package/dist/{dist-q8b2Mjgb.mjs → dist-DR9sIMbM.mjs} +0 -0
  123. /package/dist/{dist-D2L3_KTK.mjs → dist-abzUneor.mjs} +0 -0
  124. /package/dist/{dotenv-HQNhRalS.mjs → dotenv-Bkoqyq9r.mjs} +0 -0
  125. /package/dist/{env-raw-DtfQ9E31.mjs → env-raw-zk5JQKZe.mjs} +0 -0
  126. /package/dist/{fetch-error-DZ868Xq4.d.mts → fetch-error-BbixZ9vW.d.mts} +0 -0
  127. /package/dist/{fetch-error-CEr0ACTl.mjs → fetch-error-rXermVU3.mjs} +0 -0
  128. /package/dist/{head-C7QW7UY1.d.mts → head-CZs8dMxG.d.mts} +0 -0
  129. /package/dist/{log-7ChR5Fbc.mjs → log-CWWZV4V1.mjs} +0 -0
  130. /package/dist/{magic-string.es-DS_lmuBe.mjs → magic-string.es-C1Fb0uxq.mjs} +0 -0
  131. /package/dist/{providers-BlFNPYen.mjs → providers-uC0PJg1c.mjs} +0 -0
  132. /package/dist/{standard-schema-D2qvCEYV.d.mts → standard-schema-WhHcCaqJ.d.mts} +0 -0
  133. /package/dist/{types-DG_Ynnyd.d.mts → types-C8wsi1hv.d.mts} +0 -0
@@ -1,4 +1,4 @@
1
- import { a as join, n as dirname } from "./pathe.M-eThtNZ-D-kmWkCS.mjs";
1
+ import { a as join, n as dirname } from "./pathe.M-eThtNZ-BrPhGF_K.mjs";
2
2
  import { existsSync, readdirSync } from "node:fs";
3
3
  import { pathToFileURL } from "node:url";
4
4
  //#region src/cli/yarn-pnp.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "void",
3
- "version": "0.7.13",
3
+ "version": "0.8.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/voidzero-dev/void.git",
@@ -48,6 +48,7 @@
48
48
  "import": "./dist/index.mjs",
49
49
  "require": "./dist/index.mjs"
50
50
  },
51
+ "./schema.json": "./schema.json",
51
52
  "./handler": {
52
53
  "types": "./dist/runtime/handler.d.mts",
53
54
  "import": "./dist/runtime/handler.mjs",
@@ -332,7 +333,7 @@
332
333
  "valibot": ">=1.0.0-beta.7",
333
334
  "vite": "^8.0.0",
334
335
  "zod": "^3.25.0 || ^4.0.0",
335
- "@void/md": "0.7.13"
336
+ "@void/md": "0.8.0"
336
337
  },
337
338
  "peerDependenciesMeta": {
338
339
  "@void/md": {
package/schema.json CHANGED
@@ -8,6 +8,11 @@
8
8
  "type": "string",
9
9
  "description": "JSON Schema URL for IDE support"
10
10
  },
11
+ "sourceDir": {
12
+ "type": "string",
13
+ "pattern": "^(?!/)(?!\\.\\.?$)(?!\\./$)(?!\\.\\./)(?!.*(?:^|/)\\.\\.(?:/|$))(?!.*\\s$)(?!\\s).+$",
14
+ "description": "Directory containing Void source conventions such as pages, routes, middleware, crons, queues, db, auth.ts, and env.ts. Omit to use the project root."
15
+ },
11
16
  "target": {
12
17
  "type": "string",
13
18
  "enum": ["cloudflare", "node", "bun", "deno"],
@@ -208,7 +208,7 @@ All [AI Gateway providers](https://developers.cloudflare.com/ai-gateway/usage/pr
208
208
  For production, add your API key as a project secret:
209
209
 
210
210
  ```bash
211
- void secrets set OPENAI_API_KEY sk-...
211
+ void secret put OPENAI_API_KEY=sk-...
212
212
  ```
213
213
 
214
214
  For local development, add it to `.env.local` in your project root:
@@ -50,7 +50,7 @@ Void supports deploying Vite-based meta-framework apps with `void deploy`. The f
50
50
  | [Analog](https://analogjs.org/) | `@analogjs/platform` | [Guide](../integrations/frameworks/analog.md) |
51
51
  | [Astro](https://astro.build/) | `astro` | [Guide](../integrations/frameworks/astro.md) |
52
52
 
53
- Add `voidPlugin()` to the framework's Vite config to get binding inference, typed DB generation, migration management, auth, cron jobs, queues, and caching. See the [Meta Frameworks Integration](../integrations/frameworks/overview.md) for the full feature matrix, deploy pipeline, and per-framework setup guides.
53
+ Add `voidPlugin()` to the framework's Vite config to get binding inference, typed DB generation, migration management, cron jobs, queues, and caching. Void-managed auth is not supported in framework mode; use Better Auth's official integration for your framework. See the [Meta Frameworks Integration](../integrations/frameworks/overview.md) for the full feature matrix, deploy pipeline, and per-framework setup guides.
54
54
 
55
55
  **Deploy:** `void deploy` runs the framework build, packages the output, and deploys to Void. The framework still owns routing and SSR, while Void handles resource provisioning, migrations, and edge hosting.
56
56
 
@@ -32,7 +32,7 @@ For local development, add `DATABASE_URL` to `.env.local`:
32
32
  DATABASE_URL=postgres://user:password@host:5432/mydb
33
33
  ```
34
34
 
35
- This connects directly to your Postgres database during `void dev`.
35
+ This connects directly to your Postgres database during local Vite development.
36
36
 
37
37
  ### 3. Deploy
38
38
 
@@ -74,6 +74,6 @@ No configuration is needed. If the framework generates a `_headers` file, it is
74
74
 
75
75
  1. `void deploy` reads header rules from the framework `_headers` file (if present) and `routing.headers` in `void.json`, then includes them in the deploy manifest.
76
76
  2. The platform stores the rules in the KV routing entry for your project.
77
- 3. The dispatch worker applies matching rules to static responses before edge caching.
77
+ 3. The dispatch worker applies matching rules to matching responses before returning them. Cacheable responses are cached with the final headers.
78
78
 
79
79
  Because rules are evaluated at the edge, there is no extra latency cost. Headers are applied inline before the response is returned and cached.
@@ -67,6 +67,40 @@ This happens automatically for all static assets. No configuration is needed.
67
67
 
68
68
  You can override caching headers or add your own for any static asset path using [Custom Headers](./headers).
69
69
 
70
+ ## Request pipeline
71
+
72
+ Static assets can run in front of the worker, behind the worker, or without any worker at all. Void chooses the pipeline from the app shape so static pages stay static unless application code must inspect document navigations.
73
+
74
+ ### Deploy shapes
75
+
76
+ | Shape | Worker deployed | First handler for assets | First handler for document navigations | Miss behavior |
77
+ | --------------------------------------------------------------------------------------- | --------------- | ------------------------ | -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
78
+ | `inference.appType: "static"` | No | Asset platform | Asset platform | Platform 404 page. |
79
+ | Static SPA deploy | No | Asset platform | Asset platform | Platform serves `/index.html` for unmatched navigations. If user `routing.fallbacks` exist, Void ships fallback rules. |
80
+ | Void app with only `/api` routes | Yes | Asset platform | Asset platform | Static navigations keep the platform SPA fallback; API asset misses fall through to the worker route table. |
81
+ | Void app with `middleware/`, managed auth, non-`/api` routes, WebSockets, live bindings | Yes | Worker first | Worker first | Asset misses stay 404, then the worker serves `/index.html` for HTML requests after routes and middleware run. |
82
+ | Pages, SSR, and framework apps | Yes | Worker first | Worker first | Asset misses stay 404. Pages, SSR, or framework rendering owns HTML responses, including intentional HTML 404s. |
83
+
84
+ ### Worker-first Void apps
85
+
86
+ For worker-owned HTML, Void sets Cloudflare assets to `not_found_handling: "none"` and configures `run_worker_first`. The request order is:
87
+
88
+ 1. Platform routing rules that always run before assets, such as redirects and forced rewrites.
89
+ 2. Worker route table, middleware, auth, WebSocket upgrades, Pages, or SSR.
90
+ 3. `env.ASSETS.fetch()` from inside the worker for static files.
91
+ 4. For non-Pages, non-SSR Void apps only, a worker-side SPA fallback to `/index.html` when the original request accepts HTML.
92
+ 5. The worker's original 404.
93
+
94
+ This is the path needed for preview auth and other middleware. Cloudflare's platform SPA fallback can serve `index.html` directly for browser navigations; when that happens, middleware never sees the request. Worker-owned HTML avoids that by moving fallback HTML behind middleware.
95
+
96
+ ### Asset-first Void apps
97
+
98
+ For Void apps with only `/api` routes, Void does not enable `run_worker_first`. Static assets and SPA navigations stay on the asset platform. Requests that do not resolve to an asset and are not handled by the platform SPA fallback, such as `/api/hello`, fall through to the worker.
99
+
100
+ ### Generated config
101
+
102
+ Void owns the generated asset routing policy during dev and build. If a root `wrangler.jsonc` contains stale `not_found_handling` or `run_worker_first` values, Void replaces those fields so generated config cannot accidentally change which layer sees a request first.
103
+
70
104
  ## API routes and SSR pages
71
105
 
72
106
  API responses (`/api/*`) and SSR-rendered pages without file extensions always hit the worker. They are **not** edge-cached by the dispatch layer.
@@ -12,7 +12,7 @@ import { getSandbox } from 'void/sandbox';
12
12
 
13
13
  export const POST = defineHandler(async (c) => {
14
14
  const { command } = await c.req.json<{ command: string }>();
15
- const sandbox = getSandbox('default');
15
+ const sandbox = await getSandbox('default');
16
16
  const result = await sandbox.exec(command);
17
17
 
18
18
  return c.json(result);
@@ -58,7 +58,8 @@ Available fields:
58
58
  ```ts
59
59
  import { getSandbox } from 'void/sandbox';
60
60
 
61
- const sandbox = getSandbox(`user-${user.id}`);
61
+ // inside an async handler
62
+ const sandbox = await getSandbox(`user-${user.id}`);
62
63
  await sandbox.writeFile('/tmp/input.txt', 'hello');
63
64
  const result = await sandbox.exec('cat /tmp/input.txt');
64
65
  ```
@@ -10,6 +10,28 @@ Void supports framework-agnostic SSR via explicit server and client entries. Thi
10
10
  For most apps, [Pages Routing](./pages-routing/overview) handles SSR automatically. You do not need entry files or hydration code.
11
11
  :::
12
12
 
13
+ ## Relationship to Pages Routing
14
+
15
+ Custom SSR is separate from Pages Routing. Use Custom SSR when you want to bring
16
+ your own root component, router, data loading, HTML shell, and hydration logic.
17
+
18
+ The `App` component in the examples below is not a Void convention and it is not
19
+ the same thing as `pages/layout.tsx`. It is just the root component for your
20
+ custom-rendered application:
21
+
22
+ ```tsx
23
+ // src/App.tsx
24
+ export default function App({ url }: { url: string }) {
25
+ return url === '/about' ? <main>About</main> : <main>Home</main>;
26
+ }
27
+ ```
28
+
29
+ If you are using `pages/` with `@void/react`, `@void/vue`, `@void/svelte`, or
30
+ `@void/solid`, do not create `src/main.ssr.*`, `src/main.client.*`, or
31
+ `src/App.*` for Pages mode. The adapter generates the SSR and hydration entries
32
+ and automatically composes your `pages/layout.*`, route components, loaders, and
33
+ actions.
34
+
13
35
  ## Required entries
14
36
 
15
37
  SSR mode is enabled when both of these exist:
@@ -40,8 +62,9 @@ The recommended form is `defineRender(...)` for inferred types.
40
62
 
41
63
  ```ts
42
64
  {
43
- head: string; // styles/modulepreload/Vite client+preamble (dev)
44
- body: string; // main client entry script tag
65
+ css: string; // stylesheet links for <head>
66
+ preloads: string; // modulepreload/Vite client+preamble tags for <head>
67
+ body: string; // main client entry script tag before </body>
45
68
  }
46
69
  ```
47
70
 
@@ -38,7 +38,7 @@ export const GET = defineHandler(async (c) => {
38
38
 
39
39
  ### Via `cloudflare:workers` import
40
40
 
41
- When using framework mode (TanStack Start, React Router, SolidStart), the framework owns routing and you access bindings through the `cloudflare:workers` module instead:
41
+ When using framework mode (TanStack Start or React Router), the framework owns routing and you access bindings through the `cloudflare:workers` module instead:
42
42
 
43
43
  ::: warning ⚠️ Cloudflare env access in meta frameworks
44
44
  Some frameworks, like Nuxt and SvelteKit, do not run in workerd during dev and therefore do not support directly importing from `cloudflare:workers`.
@@ -91,7 +91,7 @@ This augments the `Cloudflare.Env` interface with `DB`, `KV`, `STORAGE`, `AI`, a
91
91
  | `KV` | `KVNamespace` | `env.KV` / `c.env.KV` or `import from "void/kv"` |
92
92
  | `STORAGE` | `R2Bucket` | `env.STORAGE` / `c.env.STORAGE` or `import from "void/storage"` |
93
93
  | `AI` | `Ai` | `env.AI` / `c.env.AI` or `import from "void/ai"` |
94
- | `QUEUE_*` | `Queue<T>` | `defineQueue()` or `import from "void/queue"` |
94
+ | `QUEUE_*` | `Queue<T>` | `defineQueue()` or `import { queues } from "void/queues"` |
95
95
 
96
96
  Bindings are [inferred automatically](../reference/resource-inference.md) by scanning your source files for import and access patterns. You can also set them explicitly in `void.json`:
97
97
 
@@ -120,7 +120,7 @@ You can set non-binding wrangler fields like `compatibility_date` and `compatibi
120
120
  }
121
121
  ```
122
122
 
123
- For environment variables, use `.env` files instead of `worker.vars`. Void automatically loads `.env` files through Vite's `loadEnv` and merges them into the worker's `vars` bindings:
123
+ For environment variables, use `.env` files for local values and secrets. Void automatically loads `.env` files through Vite's `loadEnv` and merges them into the worker's `vars` bindings:
124
124
 
125
125
  ```bash
126
126
  # .env
@@ -129,6 +129,8 @@ API_URL=https://api.example.com
129
129
 
130
130
  Binding arrays such as `d1_databases`, `kv_namespaces`, and `r2_buckets` are not allowed in the `worker` field because Void manages bindings for you. If you need custom bindings with real resource IDs, add a `wrangler.jsonc` to the project root instead. See [Wrangler config merging](#wrangler-config-merging) for details.
131
131
 
132
+ For non-secret plain-text defaults, you can also set `worker.vars` in `void.json`. Values from `.env` files override `worker.vars`.
133
+
132
134
  ## Wrangler config merging
133
135
 
134
136
  By default, Void configures the Cloudflare plugin programmatically, so you don't need a `wrangler.jsonc` for bindings. Void pins a Workers compatibility date in `void.json` `worker.compatibility_date`; if no date is already configured in `void.json` or `wrangler.jsonc`/`wrangler.json`, Void writes the latest known-good date to `void.json`. Bindings are inferred from your source code and provisioned with local placeholder IDs for development.
@@ -57,7 +57,7 @@ Most configuration is inferred automatically. Use `void.json` to override defaul
57
57
 
58
58
  ```json
59
59
  {
60
- "$schema": "https://unpkg.com/void/schema.json",
60
+ "$schema": "./node_modules/void/schema.json",
61
61
  "inference": {
62
62
  "build": "nuxt build",
63
63
  "scanDirs": ["src", "server", "lib"],
@@ -106,18 +106,19 @@ These Void features work identically across all targets:
106
106
 
107
107
  The following imports are **not available** with a non-CF target and produce a compile-time error:
108
108
 
109
- | Import | CF Feature |
110
- | -------------- | ---------------------------- |
111
- | `void/db` | D1 (SQL database) |
112
- | `void/kv` | KV (key-value storage) |
113
- | `void/storage` | R2 (blob storage) |
114
- | `void/auth` | Void-managed Better Auth |
115
- | `void/ai` | Workers AI |
116
- | `void/env` | CF env type augmentation |
117
- | `void/ws` | Durable Objects + WebSockets |
109
+ | Import | CF Feature |
110
+ | -------------- | ------------------------ |
111
+ | `void/db` | D1 (SQL database) |
112
+ | `void/kv` | KV (key-value storage) |
113
+ | `void/storage` | R2 (blob storage) |
114
+ | `void/auth` | Void-managed Better Auth |
115
+ | `void/ai` | Workers AI |
116
+ | `void/env` | CF env type augmentation |
118
117
 
119
118
  If you need a database or storage, use an external provider and connect via standard Node.js libraries.
120
119
 
120
+ Void-managed WebSocket route files (`*.ws.ts`) are still Cloudflare-only because they compile to Durable Objects. The `void/ws` subpath is not compile-time blocked on non-CF targets, so browser-side `connect()` code can still be bundled when a WebSocket runtime is available.
121
+
121
122
  ### No cron job runtime
122
123
 
123
124
  You can still define [cron jobs](../guide/jobs.md) in `crons/` and they will compile into the bundle, but there is no built-in scheduler to invoke them. On Cloudflare, Workers Cron Triggers call the `scheduled` handler automatically. On Node.js, you'll need an external scheduler (e.g. `node-cron`, systemd timers, or your hosting platform's cron) to trigger the exported handler.
@@ -4,7 +4,7 @@ outline: deep
4
4
 
5
5
  # API Reference
6
6
 
7
- This page is the source of truth for public `void` exports. Use it when you already know what feature you want and need the exact import, signature, or return type.
7
+ This page is the source of truth for user-facing `void` exports. Use it when you already know what feature you want and need the exact import, signature, or return type. Some exported subpaths are implementation support for adapters, generated workers, or internal runtime wiring and are intentionally not listed as app APIs.
8
8
 
9
9
  ## Plugin
10
10
 
@@ -193,7 +193,8 @@ function defineRender(
193
193
 
194
194
  ```ts
195
195
  interface RenderAssetTags {
196
- head: string; // Script and style tags for <head>
196
+ css: string; // Stylesheet links for <head>
197
+ preloads: string; // Modulepreload and dev client tags for <head>
197
198
  body: string; // Script tags for before </body>
198
199
  }
199
200
  ```
@@ -533,11 +534,11 @@ The typed client is built on [ofetch](https://github.com/unjs/ofetch) with a typ
533
534
 
534
535
  ## Database
535
536
 
536
- Imported from `"void/db"`. The `db` export is a [Drizzle ORM](https://orm.drizzle.team) instance for [Cloudflare D1](https://developers.cloudflare.com/d1/). See the [Database guide](../guide/database.md) for usage and the [Drizzle docs](https://orm.drizzle.team/docs/select) for the full query API.
537
+ Imported from `"void/db"`. The `db` export is a [Drizzle ORM](https://orm.drizzle.team) instance for the configured database dialect: [Cloudflare D1](https://developers.cloudflare.com/d1/) by default, or PostgreSQL when `void.json` sets `"database": "pg"` / `"postgresql"`. See the [Database guide](../guide/database.md) for usage and the [Drizzle docs](https://orm.drizzle.team/docs/select) for the full query API.
537
538
 
538
539
  ### `db`
539
540
 
540
- Default Drizzle D1 instance, pre-wired with the `env.DB` binding and your schema from `db/schema.ts`.
541
+ Default Drizzle instance, pre-wired with your schema from `db/schema.ts`.
541
542
 
542
543
  ```ts
543
544
  import { db } from 'void/db';
@@ -546,11 +547,18 @@ import { users } from '@schema';
546
547
  const allUsers = await db.select().from(users).all();
547
548
  ```
548
549
 
549
- When the Void plugin is active, `void/db` is served as a virtual module that auto-wires the D1 binding with your schema. The published npm fallback uses a lazy proxy that resolves the `DB` binding at first access.
550
+ When the Void plugin is active, `void/db` is served as a virtual module that auto-wires the active database with your schema.
551
+
552
+ - D1 projects resolve the `DB` binding and expose `DrizzleD1Database<Schema>`.
553
+ - PostgreSQL projects use `DATABASE_URL` during local development and Hyperdrive's `connectionString` in production, exposing `NodePgDatabase<Schema>`.
554
+
555
+ The published npm fallback uses a lazy D1 proxy that resolves the `DB` binding at first access.
550
556
 
551
557
  ### `createDb(database)`
552
558
 
553
- Creates a Drizzle D1 instance from a specific D1 binding. Use this when you have multiple D1 databases or need a non-default binding.
559
+ Creates a Drizzle instance for the active dialect.
560
+
561
+ For D1 projects, pass a specific D1 binding. Use this when you have multiple D1 databases or need a non-default binding.
554
562
 
555
563
  ```ts
556
564
  import { createDb } from 'void/db';
@@ -559,10 +567,22 @@ import { env } from 'cloudflare:workers';
559
567
  const db = createDb(env.MY_OTHER_DB);
560
568
  ```
561
569
 
570
+ For PostgreSQL projects, pass a connection string.
571
+
572
+ ```ts
573
+ import { createDb } from 'void/db';
574
+
575
+ const db = createDb('postgres://user:password@host:5432/app');
576
+ ```
577
+
562
578
  **Signature:**
563
579
 
564
580
  ```ts
565
- function createDb(d1: D1Database): DrizzleD1Database;
581
+ // D1
582
+ function createDb(d1: D1Database): DrizzleD1Database<Schema>;
583
+
584
+ // PostgreSQL
585
+ function createDb(connectionString: string): NodePgDatabase<Schema>;
566
586
  ```
567
587
 
568
588
  ### Query Operators
@@ -602,6 +622,98 @@ The callback receives:
602
622
 
603
623
  Seed modules can export either `default` or a named `seed` function.
604
624
 
625
+ ## KV
626
+
627
+ Imported from `"void/kv"`.
628
+
629
+ ### `kv`
630
+
631
+ Typed JSON-aware client for the inferred `KV` binding.
632
+
633
+ ```ts
634
+ import { kv } from 'void/kv';
635
+
636
+ await kv.put('settings', { theme: 'dark' });
637
+ const settings = await kv.get<{ theme: string }>('settings');
638
+ ```
639
+
640
+ **Key exports:** `kv`, `createKV(namespace)`, `KVClient`, `KVMap`, `PutOptions`, `ListOptions`.
641
+
642
+ `kv.map(prefix)` creates a typed namespaced view where every key is stored under `prefix:`.
643
+
644
+ ## Storage
645
+
646
+ Imported from `"void/storage"`.
647
+
648
+ ### `storage`
649
+
650
+ Default [R2 bucket](https://developers.cloudflare.com/r2/) proxy for the inferred `STORAGE` binding.
651
+
652
+ ```ts
653
+ import { storage } from 'void/storage';
654
+
655
+ await storage.put('avatars/alice.png', file);
656
+ const object = await storage.get('avatars/alice.png');
657
+ ```
658
+
659
+ **Key exports:** `storage`, `createStorage(bucket)`.
660
+
661
+ ## AI
662
+
663
+ Imported from `"void/ai"`.
664
+
665
+ ### `ai`
666
+
667
+ Typed AI client for Workers AI models and AI Gateway-backed third-party providers.
668
+
669
+ ```ts
670
+ import { ai } from 'void/ai';
671
+
672
+ const result = await ai.run('@cf/meta/llama-3.1-8b-instruct', {
673
+ messages: [{ role: 'user', content: 'Summarize this release note.' }],
674
+ });
675
+ ```
676
+
677
+ **Key exports:** `ai`, `VoidAi`, model input/response types. See [AI](../guide/ai.md) for provider setup and streaming examples.
678
+
679
+ ## ISR
680
+
681
+ Imported from `"void/isr"`.
682
+
683
+ ### `revalidate(options)`
684
+
685
+ Revalidate ISR-cached pages on demand. In local development this is a no-op because there is no edge ISR cache.
686
+
687
+ ```ts
688
+ import { revalidate } from 'void/isr';
689
+
690
+ await revalidate({ paths: ['/', '/blog/hello'] });
691
+ await revalidate({ all: true });
692
+ ```
693
+
694
+ **Signature:**
695
+
696
+ ```ts
697
+ function revalidate(options: { paths?: string[]; all?: boolean }): Promise<void>;
698
+ ```
699
+
700
+ ## Logging
701
+
702
+ Imported from `"void/log"`.
703
+
704
+ ### `logger`
705
+
706
+ Structured logger that emits one JSON line per call so deployed logs can be filtered by message and fields.
707
+
708
+ ```ts
709
+ import { logger } from 'void/log';
710
+
711
+ logger.info('checkout completed', { orderId, userId });
712
+ logger.error('webhook failed', { provider: 'stripe', attempt: 3 });
713
+ ```
714
+
715
+ **Methods:** `logger.error(message, fields?)`, `logger.warn(message, fields?)`, `logger.info(message, fields?)`.
716
+
605
717
  ## Types
606
718
 
607
719
  ### `CloudContext`
@@ -691,9 +803,42 @@ Empty stub interface augmented at build time by the generated `.void/routes.d.ts
691
803
  import type { RouteMap } from 'void/routes';
692
804
  ```
693
805
 
694
- ## Environment Types
806
+ ## Environment
807
+
808
+ Imported from `"void/env"`.
809
+
810
+ ### `defineEnv(schema)`
695
811
 
696
- Importing `"void/env"` provides global Cloudflare environment types:
812
+ Register an env schema and return the typed [`env`](#env) proxy. Void auto-discovers `env.ts`, imports it during dev/build/deploy, generates `.void/env.d.ts`, validates production secrets before deploy, and validates values at worker boot.
813
+
814
+ ```ts
815
+ import { defineEnv, string, number, oneOf, url } from 'void/env';
816
+
817
+ export default defineEnv({
818
+ STRIPE_KEY: string().secret(),
819
+ PORT: number().default(3000),
820
+ NODE_ENV: oneOf(['development', 'production']),
821
+ VITE_PUBLIC_URL: url().public(),
822
+ });
823
+ ```
824
+
825
+ ### `env`
826
+
827
+ Typed runtime proxy for declared env keys. Unknown keys and bindings pass through as `unknown`.
828
+
829
+ ```ts
830
+ import { env } from 'void/env';
831
+
832
+ const port = env.PORT;
833
+ ```
834
+
835
+ ### Schema helpers
836
+
837
+ `void/env` includes Standard Schema-compatible helpers: `string()`, `number()`, `boolean()`, `url()`, `email()`, `oneOf([...])`, and `json<T>()`. Each helper supports `.optional()`, `.default(value)`, `.secret()`, and `.public()`.
838
+
839
+ ### Types
840
+
841
+ `void/env` also provides global Cloudflare environment types:
697
842
 
698
843
  ```ts
699
844
  /// <reference types="void/env" />
@@ -732,6 +877,7 @@ function voidVue(options?: VoidVueOptions): Plugin[];
732
877
  ```ts
733
878
  interface VoidVueOptions {
734
879
  vue?: VuePluginOptions; // passed through to @vitejs/plugin-vue
880
+ viewTransitions?: boolean; // enable View Transitions API for navigations
735
881
  }
736
882
  ```
737
883
 
@@ -746,6 +892,8 @@ Imported from `"@void/vue"`.
746
892
  | `useParams()` | Returns dynamic route params for the page currently being rendered. |
747
893
  | `useNavigation()` | Returns pending navigation state: `{ state, location, method }`, where `state` is `"idle"`, `"loading"`, or `"submitting"` and `location` is the pending destination. |
748
894
  | `useForm(url, defaults, options?)` | Typed reactive form helper bound to a page action URL. Returns `{ data, post, put, patch, delete, pending, errors, error, hasChanges, wasSuccessful, recentlySuccessful, reset, clearErrors, clearError }`. |
895
+ | `useIslandForm(defaults)` | Form helper for island components where the action URL is inferred from the current island request. Returns the same form state and submit helpers as `useForm()`. |
896
+ | `action(url, options?)` | Awaitable one-shot page action helper. Uses `POST` by default and accepts `{ data, method, params }`, where `method` can be `"PUT"`, `"PATCH"`, or `"DELETE"`. Returns an `ActionResult`. |
749
897
  | `useShared()` | Returns shared data injected by middleware via `c.set("shared", {...})`. |
750
898
 
751
899
  Vue `Link` GET `data` is merged into the rendered `href` query string. Primitive values are serialized with `String(value)`, arrays become repeated keys, `null` and `undefined` are omitted, and nested objects throw. `prefetch` and `reloadDocument` are GET-only and throw for mutation links.
@@ -794,6 +942,7 @@ Imported from `"@void/react"`.
794
942
  | `useParams()` | Returns dynamic route params for the page currently being rendered. |
795
943
  | `useNavigation()` | Returns pending navigation state: `{ state, location, method }`, where `state` is `"idle"`, `"loading"`, or `"submitting"` and `location` is the pending destination. |
796
944
  | `useForm(url, defaults, options?)` | Form helper hook. Returns `{ data, setData, post, put, patch, delete, pending, errors, error, hasChanges, wasSuccessful, recentlySuccessful, reset, clearErrors, clearError }`. |
945
+ | `useIslandForm(defaults)` | Form helper hook for island components where the action URL is inferred from the current island request. Returns the same form state and submit helpers as `useForm()`. |
797
946
  | `action(url, options?)` | Awaitable one-shot page action helper. Uses `POST` by default and accepts `{ data, method, params }`, where `method` can be `"PUT"`, `"PATCH"`, or `"DELETE"`. Returns an `ActionResult`. |
798
947
  | `useShared()` | Returns shared data injected by middleware via `c.set("shared", {...})`. |
799
948
  | `Deferred<T>` | React-only prop type for `defer()` results. It is `Promise<T>` and is consumed with React `use()`. |
@@ -835,6 +984,10 @@ function voidSvelte(options?: VoidSvelteOptions): Plugin[];
835
984
  interface VoidSvelteOptions {
836
985
  svelte?: SveltePluginOptions; // passed through to @sveltejs/vite-plugin-svelte
837
986
  viewTransitions?: boolean; // enable View Transitions API
987
+ prefetch?: {
988
+ hoverDelay?: number;
989
+ cacheFor?: number | string | [string, string];
990
+ };
838
991
  }
839
992
  ```
840
993
 
@@ -846,6 +999,8 @@ Imported from `"@void/svelte"`.
846
999
  | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
847
1000
  | `Link` | Svelte component for SPA navigation. Renders `<a>` for GET, `<button>` for non-GET methods. Props: `href`, `method`, `data`, `prefetch`, `cacheFor`, `preserveScroll`, `preserveState`, `replace`, `reloadDocument`, `viewTransition`, `onNavigate`. |
848
1001
  | `useForm(url, defaults, options?)` | Form helper using Svelte 5 runes. Returns `{ data, post, put, patch, delete, pending, errors, error, hasChanges, wasSuccessful, recentlySuccessful, reset, clearErrors, clearError }`. |
1002
+ | `useIslandForm(defaults)` | Form helper for island components where the action URL is inferred from the current island request. Returns the same form state and submit helpers as `useForm()`. |
1003
+ | `action(url, options?)` | Awaitable one-shot page action helper. Uses `POST` by default and accepts `{ data, method, params }`, where `method` can be `"PUT"`, `"PATCH"`, or `"DELETE"`. Returns an `ActionResult`. |
849
1004
  | `useShared()` | Returns shared data injected by middleware via `c.set("shared", {...})`. |
850
1005
  | `useRouter()` | Returns the Void Router with current route state (`url`, `path`, `query`, `params`) and navigation methods: `visit`, `refresh`, awaitable `prefetch`, `flush`, `flushAll`. |
851
1006
  | `useParams()` | Returns dynamic route params for the page currently being rendered. |
@@ -879,6 +1034,10 @@ function voidSolid(options?: VoidSolidOptions): Plugin[];
879
1034
  interface VoidSolidOptions {
880
1035
  solid?: SolidPluginOptions; // passed through to vite-plugin-solid
881
1036
  viewTransitions?: boolean; // enable View Transitions API
1037
+ prefetch?: {
1038
+ hoverDelay?: number;
1039
+ cacheFor?: number | string | [string, string];
1040
+ };
882
1041
  }
883
1042
  ```
884
1043
 
@@ -890,6 +1049,8 @@ Imported from `"@void/solid"`.
890
1049
  | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
891
1050
  | `Link` | Solid component for SPA navigation. Renders `<a>` for GET, `<button>` for non-GET methods. Props: `href`, `method`, `data`, `prefetch`, `cacheFor`, `preserveScroll`, `preserveState`, `replace`, `reloadDocument`, `viewTransition`, `onNavigate`. |
892
1051
  | `useForm(url, defaults, options?)` | Form helper using Solid stores. Returns `{ data, setData, post, put, patch, delete, pending, errors, error, hasChanges, wasSuccessful, recentlySuccessful, reset, clearErrors, clearError }`. |
1052
+ | `useIslandForm(defaults)` | Form helper for island components where the action URL is inferred from the current island request. Returns the same form state and submit helpers as `useForm()`. |
1053
+ | `action(url, options?)` | Awaitable one-shot page action helper. Uses `POST` by default and accepts `{ data, method, params }`, where `method` can be `"PUT"`, `"PATCH"`, or `"DELETE"`. Returns an `ActionResult`. |
893
1054
  | `useShared()` | Returns shared data injected by middleware via `c.set("shared", {...})`. |
894
1055
  | `useRouter()` | Returns the Void Router with current route state (`url`, `path`, `query`, `params`) and navigation methods: `visit`, `refresh`, awaitable `prefetch`, `flush`, `flushAll`. |
895
1056
  | `useParams()` | Returns dynamic route params for the page currently being rendered. |
@@ -897,11 +1058,35 @@ Imported from `"@void/solid"`.
897
1058
 
898
1059
  Solid `Link` GET `data` is merged into the rendered `href` query string. Primitive values are serialized with `String(value)`, arrays become repeated keys, `null` and `undefined` are omitted, and nested objects throw. `prefetch` and `reloadDocument` are GET-only and throw for mutation links.
899
1060
 
900
- ## Subpath Exports
1061
+ ## Markdown Package
1062
+
1063
+ The optional `@void/md` package adds Markdown pages to Pages Routing. Install it alongside a Pages adapter and add `voidMarkdown()` to your Vite plugins.
1064
+
1065
+ ```ts
1066
+ import { voidMarkdown } from '@void/md/plugin';
1067
+
1068
+ export default defineConfig({
1069
+ plugins: [voidPlugin(), voidReact(), voidMarkdown()],
1070
+ });
1071
+ ```
1072
+
1073
+ | Import path | Contents |
1074
+ | ---------------------------- | ---------------------------------------------------------------------------------------- |
1075
+ | `@void/md/plugin` | `voidMarkdown(options?)`, `MarkdownOptions`, `MdPage` |
1076
+ | `@void/md` | `useFrontmatter()`, `FrontmatterContext`, `setFrontmatter()`, `MdPage` |
1077
+ | `@void/md/pages` | Generated metadata for Markdown pages, used for navigation, sidebars, and search indexes |
1078
+ | `@void/md/theme.css` | Full Markdown theme styles |
1079
+ | `@void/md/theme-content.css` | Content-only Markdown styles for apps that provide their own shell/layout |
1080
+
1081
+ See [Markdown Pages](../guide/pages-routing/markdown.md) for setup and framework-specific examples.
1082
+
1083
+ ## User-Facing Imports
1084
+
1085
+ This table lists app-facing imports. Exported implementation subpaths such as `void/pages*`, `void/runtime/*`, and `void/remote*` are used by adapters, generated entries, or internal runtime wiring and are not documented as application APIs.
901
1086
 
902
1087
  | Import path | Contents |
903
1088
  | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
904
- | `void` | `voidPlugin` named export + all handler/type re-exports |
1089
+ | `void` | `voidPlugin`, handler/type re-exports, `defer`, `Deferred`, `DeferredState`, `InferProps`, `HeadDescriptor` |
905
1090
  | `void/handler` | `defineHandler`, `defineMiddleware`, `defineScheduled`, `defineQueue`, `defineRender`, `defineHead`, types |
906
1091
  | `void/auth` | `defineAuth`, `getUser`, `getSession`, `requireAuth`, `AuthUser`, `AuthSession`, `AuthState` |
907
1092
  | `void/client` | `fetch`, `fetchStream`, `FetchError`, `auth`, `createAuthClient`, `AuthUser`, `AuthSession`, `AuthState` |
@@ -917,9 +1102,15 @@ Solid `Link` GET `data` is merged into the rendered `href` query string. Primiti
917
1102
  | `void/drizzle-arktype` | Re-exports [`drizzle-arktype`](https://orm.drizzle.team/docs/arktype) for schema-derived ArkType validators for Drizzle tables |
918
1103
  | `void/schema-d1` | Re-exports [`drizzle-orm/sqlite-core`](https://orm.drizzle.team/docs/column-types/sqlite) for D1 table and column builders |
919
1104
  | `void/schema-pg` | Re-exports [`drizzle-orm/pg-core`](https://orm.drizzle.team/docs/column-types/pg) for PostgreSQL table and column builders |
920
- | `void/db` | `db` ([Drizzle D1](https://orm.drizzle.team/docs/get-started/d1-new) instance), `createDb`, query operators (`eq`, `and`, `or`, `desc`, `like`, `inArray`, etc.) |
1105
+ | `void/db` | `db` (Drizzle D1 or PostgreSQL instance for the active dialect), `createDb`, query operators (`eq`, `and`, `or`, `desc`, `like`, `inArray`, etc.) |
921
1106
  | `void/seed` | `defineSeed`, `SeedContext`, `SeedFn` for programmatic `void db seed` modules |
1107
+ | `void/kv` | `kv`, `createKV`, typed KV client/map types |
1108
+ | `void/storage` | `storage`, `createStorage` for the inferred R2 binding or a specific `R2Bucket` |
1109
+ | `void/ai` | `ai`, `VoidAi`, model input and response types |
1110
+ | `void/isr` | `revalidate(options)` for on-demand ISR cache invalidation |
1111
+ | `void/log` | `logger` structured logging helper |
922
1112
  | `void/routes` | `RouteMap` and `WebSocketRouteMap` stubs (types only) |
923
1113
  | `void/queues` | `queues` proxy for sending messages to typed queues |
924
1114
  | `void/sandbox` | `getSandbox`, `sandbox`, `Sandbox`, and sandbox option types from the Cloudflare Sandbox SDK. `getSandbox(id)` resolves to the same Durable Object instance for a given `id` across all deploys and rollbacks. DO-level storage (`ctx.storage`) is durable; the container filesystem, processes, and exposed ports are tied to a single container lifetime and are lost on idle (`sleepAfter`, default `10m`), crash, or platform restart. See [Sandboxes › State persistence](../guide/sandboxes.md#state-persistence). |
925
- | `void/env` | Global Cloudflare env types (types only) |
1115
+ | `void/env` | `defineEnv`, `env`, schema helpers (`string`, `number`, `boolean`, `url`, `email`, `oneOf`, `json`), and global Cloudflare env types |
1116
+ | `void/sveltekit` | SvelteKit integration helpers: `withVoidTSConfig()` and `mergeVoidSvelteKitTsconfig()` |