void 0.24.0 → 0.26.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.
- package/README.md +19 -106
- package/dist/{account-cmd-vJhh5lrb.mjs → account-cmd-CDry3B5V.mjs} +5 -5
- package/dist/{application-analysis-BVsVqc11.mjs → application-analysis-DC2yPvzY.mjs} +1 -1
- package/dist/{application-routing-B7QEjqSR.mjs → application-routing-C9khgLiS.mjs} +1 -1
- package/dist/{auth-DX3JURcX.mjs → auth-B60QDbjg.mjs} +1 -1
- package/dist/{auth-CQkSDS50.mjs → auth-D52yG7hl.mjs} +3 -3
- package/dist/{auth-link-D75t9wO2.mjs → auth-link-DjeOptYi.mjs} +5 -6
- package/dist/{auth-router-ClfhL1J7.mjs → auth-router-BRxIuqDi.mjs} +7 -7
- package/dist/{build-cmd-zMi1iFnS.mjs → build-cmd-Ce3C8huo.mjs} +6 -7
- package/dist/{cache-ZtQmyxVV.mjs → cache-CS8Yxr5a.mjs} +6 -7
- package/dist/{cancel-deploy-Box0kkEV.mjs → cancel-deploy-mZsD88Xa.mjs} +4 -6
- package/dist/{cf-access-BGe5sWXF.mjs → cf-access-YTlqvAsk.mjs} +1 -1
- package/dist/cf-build-output-ChY6-XWP.mjs +2 -0
- package/dist/cli/cli.mjs +45 -45
- package/dist/cli/cloudflare-operation-process.mjs +3 -3
- package/dist/cli/env-schema-probe.d.mts +1 -1
- package/dist/cli/env-schema-probe.mjs +2 -2
- package/dist/client-BxVixJBI.mjs +2 -0
- package/dist/{client-DKAsFA4X.mjs → client-mC-dFGDD.mjs} +103 -25
- package/dist/{cloudflare-cmd-CmY8dGkd.mjs → cloudflare-cmd-bhwCxAN6.mjs} +2 -2
- package/dist/{cloudflare-connect-IiR3ZieC.mjs → cloudflare-connect-CuhRgk3k.mjs} +2 -2
- package/dist/{cloudflare-operations-DzH-A966.mjs → cloudflare-operations-DYa3coIk.mjs} +2 -2
- package/dist/{cloudflare-operations-BCdXSsmo.mjs → cloudflare-operations-DoQrVHAt.mjs} +1 -1
- package/dist/{connect-B-usTnlF.mjs → connect-H6EvP62X.mjs} +12 -9
- package/dist/{create-project-CYOOAYcn.mjs → create-project-B2kk9Q0o.mjs} +6 -6
- package/dist/{create-project-FWbf5Olo.mjs → create-project-Dbb4uiN-.mjs} +1 -1
- package/dist/{db-Ck2eZ2iB.mjs → db-DpCKZto0.mjs} +35 -38
- package/dist/{delete-sK56qtzZ.mjs → delete-CxlSvsvW.mjs} +6 -7
- package/dist/{deploy-gCVaiJbS.mjs → deploy-CeEbnv4b.mjs} +9249 -8925
- package/dist/deploy-qmiLE1G1.mjs +2 -0
- package/dist/{dev-inbox-P0u4tM8Y.mjs → dev-inbox-D64ZKUod.mjs} +5 -6
- package/dist/{domain-DFfQE8jg.mjs → domain-B_9VgOm6.mjs} +8 -8
- package/dist/{email-CdnhUHvJ.mjs → email-BokHgjKj.mjs} +7 -7
- package/dist/{env-DmGdHi5i.mjs → env-BdTc-K2L.mjs} +7 -8
- package/dist/{env-public-BX_r8HR6.d.mts → env-public-DR7ZM6d-.d.mts} +1 -1
- package/dist/{env-validation-zZOCcQVZ.mjs → env-validation-cZBvGWaP.mjs} +1 -1
- package/dist/{fetch-stream-IvCYKyQL.mjs → fetch-stream-Nm3hkZbT.mjs} +8 -1
- package/dist/{gen-CshAkukR.mjs → gen-BhDlTpwW.mjs} +2 -4
- package/dist/gen-qCBwH3fZ.mjs +2 -0
- package/dist/{github-cmd-DftuEvIt.mjs → github-cmd-hhkTzlGS.mjs} +7 -16
- package/dist/{handler-CZ4nAylQ.d.mts → handler-BeK3weD4.d.mts} +1 -1
- package/dist/{help-Dotbf6iz.mjs → help-Bv44e2tm.mjs} +13 -9
- package/dist/help-Dw5f9Xrg.mjs +2 -0
- package/dist/index.d.mts +19 -15
- package/dist/index.mjs +2225 -2142
- package/dist/{info-B97bTX9N.mjs → info-DhtTKh65.mjs} +2 -4
- package/dist/{init-BTQEZZGJ.mjs → init-BMf4T03q.mjs} +17 -18
- package/dist/{limits-Bq5LG8Id.d.mts → limits-CFsDKQvU.d.mts} +1 -10
- package/dist/{limits-Cjuk2VPm.mjs → limits-D0vD1M9A.mjs} +1 -22
- package/dist/{link-B46sYH0K.mjs → link-BqYsSS_I.mjs} +6 -7
- package/dist/{list-BnPrIsU_.mjs → list-_kBToO-l.mjs} +10 -10
- package/dist/{live-Chw1eIMv.d.mts → live-iAuEH1hd.d.mts} +1 -1
- package/dist/{local-d1-2CMnpuW_.mjs → local-d1-fGxYrVD6.mjs} +2 -2
- package/dist/login-D7meQg_3.mjs +2 -0
- package/dist/{login-BuiMyUrx.mjs → login-DFuo-RWO.mjs} +9 -7
- package/dist/{logs-CZG9d-ic.mjs → logs-DYgnh6dH.mjs} +7 -8
- package/dist/migrate-CEu2X5DB.mjs +2 -0
- package/dist/{migrate-q4_njtaW.mjs → migrate-CV1on-yJ.mjs} +2 -4
- package/dist/{node-BkyRWRx8.mjs → node-C6Q6e1Es.mjs} +1 -1
- package/dist/{operator-args-B3BTmSoi.mjs → operator-args-DdY54Bgb.mjs} +1 -1
- package/dist/{operator-auth-7erYc6Lt.mjs → operator-auth-2dsGlTT5.mjs} +4 -8
- package/dist/{operator-client-CpHjTd0t.mjs → operator-client-BFqpp6z0.mjs} +3 -3
- package/dist/{operator-cmd-DGqPJUD3.mjs → operator-cmd-CUGHXrQf.mjs} +27 -9
- package/dist/operator-cmd-DRPvhpjM.mjs +2 -0
- package/dist/{output-CbM85T4k.mjs → output-BvdaehtE.mjs} +28 -4
- package/dist/pages/client.d.mts +4 -1
- package/dist/pages/client.mjs +120 -29
- package/dist/pages/index.mjs +1 -1
- package/dist/pages/islands-plugin.mjs +1 -1
- package/dist/pages/protocol.d.mts +2 -2
- package/dist/{plan-NPpwZ_kc.mjs → plan-CJGEeTEI.mjs} +2 -2
- package/dist/plan-COtUvdMA.mjs +2 -0
- package/dist/{platform-args-3k8X9-H_.mjs → platform-args-DSV2p4nY.mjs} +4 -2
- package/dist/platform-args-Dcy_5b_Y.mjs +2 -0
- package/dist/{platform-auth-config-DDrxUy4m.mjs → platform-auth-config-Bosx7U1h.mjs} +20 -19
- package/dist/{platform-auth-protection-BLadnnct.mjs → platform-auth-protection-DcbL_LW_.mjs} +8 -8
- package/dist/{platform-auth-recovery-CmCzX2Fl.mjs → platform-auth-recovery-WfTZ8K6o.mjs} +7 -7
- package/dist/{platform-cmd-DMDEc9uS.mjs → platform-cmd-DbKtQb_4.mjs} +73 -38
- package/dist/{platform-cmd-pMTRhvYs.mjs → platform-cmd-dyFUof0t.mjs} +1 -1
- package/dist/platform-discovery-BC0HCKYt.mjs +41 -0
- package/dist/{platform-domain-Di6EYrQl.mjs → platform-domain-Bsq43AJp.mjs} +5 -4
- package/dist/{platform-lifecycle-BFdSi9Qt.mjs → platform-lifecycle--5gWmDoI.mjs} +1 -1
- package/dist/{platform-lifecycle-BBoNzojY.mjs → platform-lifecycle-Cfi0o6xM.mjs} +4605 -3527
- package/dist/platform-management-Bbwf6-Dq.mjs +2 -0
- package/dist/{platform-management-CWOQOWXm.mjs → platform-management-BrF9STZp.mjs} +211 -31
- package/dist/{platform-plans-config-Vl9BP3H4.mjs → platform-plans-config-DU-8nC2Y.mjs} +3 -3
- package/dist/{platform-recovery-BJnQJEtQ.mjs → platform-recovery-DQAqAQYu.mjs} +3 -3
- package/dist/{platform-registry-DkPPXfp_.mjs → platform-registry-P387v42A.mjs} +18 -11
- package/dist/prepare-BBknoZI1.mjs +2 -0
- package/dist/{prepare-CBLT3CHH.mjs → prepare-BMrRWLwP.mjs} +3 -4
- package/dist/{prepare-DnaKBi--.mjs → prepare-WoUubFKL.mjs} +1 -1
- package/dist/{project-DsblYifa.mjs → project-BiaPQ7ur.mjs} +1 -1
- package/dist/{project-DKG5Ra8p.mjs → project-DQstYTxO.mjs} +1 -1
- package/dist/{project-cmd-DxnXstAq.mjs → project-cmd-BbH2LptN.mjs} +21 -22
- package/dist/{project-team-BmHcaALJ.mjs → project-team-Yiww3-go.mjs} +8 -9
- package/dist/{project-token-GionZlBI.mjs → project-token-BrtT2NkY.mjs} +6 -9
- package/dist/{project-zero-trust-JLCjVQA7.mjs → project-zero-trust-nYJ2V2nc.mjs} +5 -6
- package/dist/{prompts-BNUoTiaf.mjs → prompts-6OSVA7DJ.mjs} +58 -15
- package/dist/{prompts-2TGE6oXx.mjs → prompts-ZAuJlyCj.mjs} +1 -1
- package/dist/{protocol-CjF_iI9X.d.mts → protocol-BX8t2jiw.d.mts} +1 -1
- package/dist/{provision-CVku1JFU.mjs → provision-DMTPG8Rh.mjs} +1 -1
- package/dist/{provision-CaoxO_U7.mjs → provision-VeqAC77A.mjs} +18 -8
- package/dist/{requests-BOjIVAeF.mjs → requests-TIz_jtSu.mjs} +5 -6
- package/dist/{rollback-CwR3pLj3.mjs → rollback-dBqICPzj.mjs} +9 -10
- package/dist/{runner-Ol0TNjk6.mjs → runner--2KF6Kua.mjs} +1 -1
- package/dist/{runner-CXA9Fh8h.mjs → runner-voIltZrY.mjs} +1 -1
- package/dist/runtime/ai.d.mts +10 -11
- package/dist/runtime/ai.mjs +13 -18
- package/dist/runtime/client-react.mjs +1 -1
- package/dist/runtime/client-solid.mjs +1 -1
- package/dist/runtime/client-svelte.mjs +1 -1
- package/dist/runtime/client-vue.mjs +1 -1
- package/dist/runtime/client.mjs +1 -1
- package/dist/runtime/email/testing.mjs +1 -1
- package/dist/runtime/email.mjs +35 -17
- package/dist/runtime/env-public.d.mts +1 -1
- package/dist/runtime/fetch-stream.mjs +1 -1
- package/dist/runtime/handler.d.mts +1 -1
- package/dist/runtime/limits.d.mts +2 -2
- package/dist/runtime/limits.mjs +2 -2
- package/dist/runtime/live-client.d.mts +1 -1
- package/dist/runtime/live.d.mts +1 -1
- package/dist/runtime/migration-handler.mjs +33 -7
- package/dist/runtime/routing.d.mts +1 -1
- package/dist/runtime/routing.mjs +1 -1
- package/dist/runtime/sandbox.d.mts +1 -1
- package/dist/runtime/sandbox.mjs +12 -22
- package/dist/runtime/validator.d.mts +1 -1
- package/dist/runtime/ws-server.d.mts +1 -1
- package/dist/runtime/ws.d.mts +1 -1
- package/dist/{sandbox-XZAqzFlG.d.mts → sandbox-C5LFoJMf.d.mts} +7 -7
- package/dist/{scan-C7okrLyM.mjs → scan-C8dA7iM4.mjs} +10 -6
- package/dist/{secret-ByWJWBUG.mjs → secret-AKnNXNP5.mjs} +15 -16
- package/dist/{skills-C1PlclPt.mjs → skills-BPQUGClu.mjs} +1 -1
- package/dist/{subcommand-prompt-klFCfcor.mjs → subcommand-prompt-B6WS9Aoz.mjs} +2 -2
- package/dist/sveltekit.d.mts +1 -1
- package/dist/sveltekit.mjs +4 -9
- package/dist/validate-pna7R3Pv.mjs +2 -0
- package/dist/{validate-ctOrgiS3.mjs → validate-ymhap6M_.mjs} +1 -1
- package/dist/{wrangler-7K-bW_DL.mjs → wrangler-DhUerFkW.mjs} +10 -15
- package/dist/{ws-CL1w7GXU.d.mts → ws-C79j4aED.d.mts} +1 -1
- package/package.json +21 -21
- package/sandbox.Dockerfile +1 -1
- package/skills/void/SKILL.md +5 -2
- package/skills/void/docs/guide/ai.md +78 -137
- package/skills/void/docs/guide/app-types.md +1 -1
- package/skills/void/docs/guide/auth.md +0 -2
- package/skills/void/docs/guide/database/d1.md +7 -7
- package/skills/void/docs/guide/database.md +15 -0
- package/skills/void/docs/guide/deployment.md +58 -124
- package/skills/void/docs/guide/env-vars.md +1 -5
- package/skills/void/docs/guide/index.md +19 -18
- package/skills/void/docs/guide/kv.md +0 -2
- package/skills/void/docs/guide/live.md +2 -0
- package/skills/void/docs/guide/pages-routing/actions-and-forms.md +49 -47
- package/skills/void/docs/guide/pages-routing/overview.md +2 -2
- package/skills/void/docs/guide/platform/administration/email.md +0 -2
- package/skills/void/docs/guide/platform/administration/operations.md +11 -22
- package/skills/void/docs/guide/platform/administration/plans.md +1 -5
- package/skills/void/docs/guide/platform/administration/zero-trust.md +1 -4
- package/skills/void/docs/guide/platform/development/schema-ci.md +7 -1
- package/skills/void/docs/guide/platform/installation/credentials.md +2 -2
- package/skills/void/docs/guide/platform/installation/first-deployment.md +5 -1
- package/skills/void/docs/guide/platform/installation/maintenance.md +33 -11
- package/skills/void/docs/guide/platform/installation/prerequisites.md +79 -7
- package/skills/void/docs/guide/platform/installation/setup.md +1 -1
- package/skills/void/docs/guide/platform/installation/uninstall.md +44 -11
- package/skills/void/docs/guide/quickstart.md +37 -80
- package/skills/void/docs/guide/sandboxes.md +75 -66
- package/skills/void/docs/guide/self-hosted-platform.md +20 -0
- package/skills/void/docs/guide/websockets.md +0 -2
- package/skills/void/docs/integrations/frameworks/overview.md +2 -2
- package/skills/void/docs/integrations/frameworks/sveltekit.md +40 -25
- package/skills/void/docs/integrations/nodejs-bun-deno.md +7 -2
- package/skills/void/docs/reference/api/resources.md +38 -14
- package/skills/void/docs/reference/api.md +35 -34
- package/skills/void/docs/reference/cli/auth.md +3 -1
- package/skills/void/docs/reference/cli/deploy.md +1 -1
- package/skills/void/docs/reference/cli/platform-config.md +2 -2
- package/skills/void/docs/reference/cli/platform-installation.md +14 -12
- package/skills/void/docs/reference/cli/platform-operations.md +4 -8
- package/skills/void/docs/reference/cli/platform.md +9 -2
- package/skills/void/docs/reference/cli.md +1 -1
- package/skills/void/docs/reference/resource-inference.md +12 -8
- package/dist/cf-build-output-_0HNWysu.mjs +0 -2
- package/dist/client-B9UBI03V.mjs +0 -2
- package/dist/deploy-irP5q0-x.mjs +0 -2
- package/dist/gen-DvQTWzDU.mjs +0 -2
- package/dist/help-mabuIV98.mjs +0 -2
- package/dist/login-DIy9Sb-U.mjs +0 -2
- package/dist/migrate-BCiJ8w0f.mjs +0 -2
- package/dist/plan-D1Q5rf-r.mjs +0 -2
- package/dist/platform-args-DdnM6WIf.mjs +0 -2
- package/dist/platform-management-DG47jys8.mjs +0 -2
- package/dist/prepare-CnjcTV2s.mjs +0 -2
- package/dist/validate-Dq_L3s0S.mjs +0 -2
- package/skills/void/docs/guide/env-migration.md +0 -109
- package/dist/{cf-build-output-BPqOT964.mjs → cf-build-output-U8o1Gl6X.mjs} +1 -1
- package/dist/{env-validation-C_8tPdhs.mjs → env-validation-vBSQ8gw5.mjs} +1 -1
|
@@ -6,12 +6,6 @@ outline: deep
|
|
|
6
6
|
|
|
7
7
|
[Cloudflare D1](https://developers.cloudflare.com/d1/) is Void's default SQLite database. Start with a [schema](../database.md#schema-definition); Void manages the database locally and when you deploy.
|
|
8
8
|
|
|
9
|
-
## Read replication
|
|
10
|
-
|
|
11
|
-
Void enables [D1 read replication](https://developers.cloudflare.com/d1/best-practices/read-replication/) when it provisions a database. To enable it on an existing database, run `void deploy --platform cloudflare --provision`. Queries through `db` from `void/db` use a D1 session for each Void request, so reads can run near the request and later queries in that request see at least the same data. Framework handlers without Void's request scope start each database operation on the primary. `createDb` starts a replica-capable session for the binding you pass it.
|
|
12
|
-
|
|
13
|
-
Replicas can lag between requests. Authentication session checks start on the primary so a revoked session is not accepted because of replica lag. If another read must start with the latest primary data, use `env.DB.withSession('first-primary')` from `cloudflare:workers`. Other query libraries and raw D1 calls need their own `withSession()` to use replicas; a bare D1 binding reads from the primary.
|
|
14
|
-
|
|
15
9
|
## Local Database
|
|
16
10
|
|
|
17
11
|
`void dev` and local `void db` commands share the same database. If `cloudflare.d1_databases` in `void.config.ts` declares the D1 binding, Void uses its ID. A `preview_database_id` takes precedence during local development.
|
|
@@ -44,6 +38,12 @@ await db.batch([
|
|
|
44
38
|
]);
|
|
45
39
|
```
|
|
46
40
|
|
|
41
|
+
## Read replication
|
|
42
|
+
|
|
43
|
+
Void enables [D1 read replication](https://developers.cloudflare.com/d1/best-practices/read-replication/) when it provisions a database. To enable it on an existing database, run `void deploy --platform cloudflare --provision`. Queries through `db` from `void/db` use a D1 session for each Void request, so reads can run near the request and later queries in that request see at least the same data. Framework handlers without Void's request scope start each database operation on the primary. `createDb` starts a replica-capable session for the binding you pass it.
|
|
44
|
+
|
|
45
|
+
Replicas can lag between requests. Authentication session checks start on the primary so a revoked session is not accepted because of replica lag. If another read must start with the latest primary data, use `env.DB.withSession('first-primary')` from `cloudflare:workers`. Other query libraries and raw D1 calls need their own `withSession()` to use replicas; a bare D1 binding reads from the primary.
|
|
46
|
+
|
|
47
47
|
## Alternative Query Layers
|
|
48
48
|
|
|
49
49
|
Use `env.DB` from `cloudflare:workers` with another query library or the raw D1 API:
|
|
@@ -69,5 +69,5 @@ const { results } = await env.DB.prepare('SELECT * FROM users WHERE id = ?').bin
|
|
|
69
69
|
Void still handles binding inference and deployment regardless of which query layer you use.
|
|
70
70
|
|
|
71
71
|
::: warning ⚠️ Meta framework limitation
|
|
72
|
-
Nuxt and SvelteKit do not support `cloudflare:workers` imports during local development. Use `void/db` or your framework's binding access API.
|
|
72
|
+
Nuxt and SvelteKit 2 do not support `cloudflare:workers` imports during local development. Use `void/db` or your framework's binding access API. SvelteKit 3 supports these imports.
|
|
73
73
|
:::
|
|
@@ -361,6 +361,21 @@ npm install arktype
|
|
|
361
361
|
|
|
362
362
|
See the [CLI reference](../reference/cli/database.md#database) for connection setup, SQL execution, Studio, exports, and other commands.
|
|
363
363
|
|
|
364
|
+
## Hand-written migrations {#hand-written-migrations}
|
|
365
|
+
|
|
366
|
+
Deploy compares your Drizzle schema with the snapshots in `db/migrations/meta/`. If you have SQL migrations without this metadata, running `void db generate` would create another migration for the same tables.
|
|
367
|
+
|
|
368
|
+
To keep an existing migration history:
|
|
369
|
+
|
|
370
|
+
1. Make your Drizzle schema match the tables your SQL migrations create.
|
|
371
|
+
2. In a scratch copy of the project, remove `db/migrations/` and run `void db generate`.
|
|
372
|
+
3. Copy the generated `meta/` folder into your original migration directory. In `_journal.json`, replace `entries` with an entry for each existing SQL file in order. Use consecutive `idx` values starting at `0`, the file name without `.sql` as `tag`, increasing timestamps as `when`, and the generated entry's `version`. Set `breakpoints` to whether the file uses `--> statement-breakpoint` lines.
|
|
373
|
+
4. Rename the generated snapshot to `<prefix>_snapshot.json`, where `<prefix>` is the part of the last migration tag before its first `_`. For `001_create_users.sql`, use `001_snapshot.json`.
|
|
374
|
+
|
|
375
|
+
Review and commit the metadata, then run `void deploy` again. If no database has applied the SQL yet, you can instead replace it with migrations from `void db generate`.
|
|
376
|
+
|
|
377
|
+
For D1 migrations containing triggers, add a `--> statement-breakpoint` line after each complete SQL statement, including the trigger's closing `END;`. Keep the trigger body together.
|
|
378
|
+
|
|
364
379
|
## Scaffolding
|
|
365
380
|
|
|
366
381
|
The `void gen model` command generates dialect-appropriate `sqliteTable`, `pgTable`, or `mysqlTable` definitions.
|
|
@@ -4,180 +4,114 @@ outline: deep
|
|
|
4
4
|
|
|
5
5
|
# Deployment
|
|
6
6
|
|
|
7
|
-
`void deploy` builds your app, provisions
|
|
7
|
+
`void deploy` builds your app, provisions resources, applies migrations, and deploys it. Choose your own Cloudflare account or a Void platform run by your team.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
After a successful deployment, Void prints your deployment URL in a summary box with the details reported by your deployment target.
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Deploy to Cloudflare
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Choose Cloudflare during `void init`, or connect later:
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
| Routing rules, WebSockets, queues, cron, and ISR | Supported | Supported |
|
|
19
|
-
| D1, KV, R2, and external SQL through Hyperdrive | Supported | Supported |
|
|
20
|
-
| Workers AI and provider requests | Your account and gateway | Installation gateway and proxy |
|
|
21
|
-
| Runtime logs | Live Cloudflare tail | Retained platform logs |
|
|
22
|
-
| Application rollback | Worker versions | Retained platform deployments |
|
|
23
|
-
| Typed Durable State | Supported | Unavailable |
|
|
24
|
-
| Sandboxes | Requires Workers Paid and Docker | Requires Workers Paid on the platform account |
|
|
25
|
-
| Custom application domains | Supported | Unavailable in the core installation |
|
|
26
|
-
| Generated GitHub deployment workflow | Supported | Use your CI with a scoped developer token |
|
|
27
|
-
| User dashboard and managed GitHub builds | Not required | Not included in a standard installation |
|
|
28
|
-
|
|
29
|
-
Native apps can run on Workers Free within its quotas. A team platform requires Workers for Platforms and the [documented infrastructure](./platform/installation/domains.md#cloudflare-footprint). Rollback does not reverse database migrations.
|
|
30
|
-
|
|
31
|
-
Native Void apps and static sites use Void routing rules. Framework deployments use their framework's routing and asset policies; direct deploy rejects unsupported Void rules.
|
|
32
|
-
|
|
33
|
-
Use matching CLI and framework adapter versions. For a team platform, the available features depend on its installed version and configuration. Ask your administrator if a feature is unavailable or an upgrade is required.
|
|
34
|
-
|
|
35
|
-
## CLI
|
|
36
|
-
|
|
37
|
-
### First deploy
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
void init # choose Cloudflare (default), Void, or Skip deployment setup
|
|
41
|
-
void deploy # builds and deploys to the saved platform
|
|
15
|
+
```sh
|
|
16
|
+
void connect --platform cloudflare
|
|
17
|
+
void deploy --platform cloudflare
|
|
42
18
|
```
|
|
43
19
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
- **Cloudflare:** sign in through your browser and choose an account. Void saves the account in `void.config.ts` or `void.lock.json`.
|
|
47
|
-
- **Void:** connect to a platform, sign in, and link or create a project.
|
|
48
|
-
- **Skip:** set up deployment later with `void connect`.
|
|
49
|
-
|
|
50
|
-
Your choice is saved in `.void/project.json`, so the next deploy is just `void deploy`.
|
|
51
|
-
|
|
52
|
-
Already have a Cloudflare Worker and a root `wrangler.jsonc` or `wrangler.json`? Run `void deploy`. If no destination is selected, Void offers to link and deploy using the existing Worker and resources. Accept once to keep deploying to that site. See [Deploy an existing Worker](../integrations/cloudflare.md#deploy-an-existing-worker) for the first-deployment checks.
|
|
20
|
+
Void opens your browser to sign in and asks which account to use. Later deploys use the saved target, so you can run `void deploy`.
|
|
53
21
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
Owners can [share a platform project](./project-collaboration.md) with readers, collaborators, and project administrators. This does not apply to direct Cloudflare deployments.
|
|
57
|
-
|
|
58
|
-
### Deploy to another Void platform
|
|
59
|
-
|
|
60
|
-
Connect to the additional platform once, then select it for the deployment:
|
|
61
|
-
|
|
62
|
-
```sh
|
|
63
|
-
void connect https://second.example.com
|
|
64
|
-
VOID_API_URL=https://second.example.com void deploy --platform void --project my-app
|
|
65
|
-
```
|
|
22
|
+
Native apps work on Workers Free within its quotas. [Sandboxes](./sandboxes.md#requirements) require Workers Paid and Containers access. See the [Cloudflare guide](../integrations/cloudflare.md) for configuration, token permissions, and features with additional requirements.
|
|
66
23
|
|
|
67
|
-
|
|
68
|
-
destination stays unchanged, including when a new project is created or deployment
|
|
69
|
-
fails. The next plain `void deploy` still uses your original destination.
|
|
24
|
+
If you already have a Worker and a root `wrangler.jsonc` or `wrangler.json`, `void deploy` can link it and preserve its resources. See [Deploy an existing Worker](../integrations/cloudflare.md#deploy-an-existing-worker).
|
|
70
25
|
|
|
71
|
-
|
|
72
|
-
belong to their original platform. Each platform has its own projects, secrets, and
|
|
73
|
-
data. For an app without a saved destination, its first deployment still saves a link.
|
|
26
|
+
## Prepare your app
|
|
74
27
|
|
|
75
28
|
### Migrations
|
|
76
29
|
|
|
77
|
-
Deploy applies pending SQL migrations from `db/migrations/`. If your schema has changes without a migration, deploy stops
|
|
30
|
+
Deploy applies pending SQL migrations from `db/migrations/`. If your schema has changes without a migration, deploy stops:
|
|
78
31
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
```bash
|
|
82
|
-
void deploy [--platform <cloudflare|void>] [--project <name>] [--dir <path>] [--spa]
|
|
32
|
+
```sh
|
|
33
|
+
void db generate
|
|
83
34
|
```
|
|
84
35
|
|
|
85
|
-
|
|
86
|
-
| ------------------------------- | ------------------------------------------------- |
|
|
87
|
-
| `--platform <cloudflare\|void>` | Override the saved deployment platform |
|
|
88
|
-
| `--project <name>` | Target a specific Void project by slug |
|
|
89
|
-
| `--dir <path>` | Deploy a pre-built static directory (skips build) |
|
|
90
|
-
| `--spa` | Use SPA mode instead of SSG for static deploys |
|
|
91
|
-
|
|
92
|
-
### Project resolution
|
|
36
|
+
Review and commit the SQL, then deploy again. Rollback does not reverse database migrations. See [Database](./database.md) for the local workflow.
|
|
93
37
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
1. `--project <name>` flag
|
|
97
|
-
2. `VOID_PROJECT` environment variable
|
|
98
|
-
3. Linked project in `.void/project.json`
|
|
38
|
+
### Environment variables
|
|
99
39
|
|
|
100
|
-
|
|
40
|
+
Declare values in `env.ts` and set production server secrets with `void secret put`. Deploy never uploads your local `.env`. Supply public `VITE_*` values through the build environment. See [Environment Variables](./env-vars.md).
|
|
101
41
|
|
|
102
|
-
|
|
42
|
+
Keep the CLI and framework adapters on matching versions, and commit `void.config.ts` and `void.lock.json` when generated.
|
|
103
43
|
|
|
104
|
-
|
|
105
|
-
CI environment before deployment. Set `VOID_API_URL` to the platform you selected;
|
|
106
|
-
there is no default hosted platform. The generated GitHub Actions workflow
|
|
107
|
-
includes this connection step.
|
|
44
|
+
## Deploy from GitHub {#github}
|
|
108
45
|
|
|
109
|
-
|
|
46
|
+
Generate a workflow for your saved target and package manager:
|
|
110
47
|
|
|
111
|
-
|
|
48
|
+
```sh
|
|
49
|
+
void init --github
|
|
50
|
+
```
|
|
112
51
|
|
|
113
|
-
|
|
114
|
-
| -------------- | -------------------------------- |
|
|
115
|
-
| `VOID_TOKEN` | Auth token (for CI, skips OAuth) |
|
|
116
|
-
| `VOID_PROJECT` | Project slug override |
|
|
52
|
+
For Cloudflare, add `CLOUDFLARE_API_TOKEN` to your repository secrets. The token needs access to the account and products your app uses. PostgreSQL and MySQL apps also need `DATABASE_URL`.
|
|
117
53
|
|
|
118
|
-
|
|
54
|
+
Follow the [Cloudflare CI setup](../integrations/cloudflare.md#deploying-from-ci) for Worker preview URLs and Cloudflare Access credentials.
|
|
119
55
|
|
|
120
|
-
|
|
56
|
+
### Team platform CI
|
|
121
57
|
|
|
122
|
-
For
|
|
58
|
+
For a core self-hosted platform, use your own workflow with a [project deploy token](./platform/installation/first-deployment.md). Set `VOID_TOKEN`, `VOID_API_URL`, and the project slug, then connect in each fresh CI environment:
|
|
123
59
|
|
|
124
|
-
|
|
60
|
+
```sh
|
|
61
|
+
void connect "$VOID_API_URL" --no-login
|
|
62
|
+
void deploy --platform void --project "$VOID_PROJECT"
|
|
63
|
+
```
|
|
125
64
|
|
|
126
|
-
|
|
65
|
+
Platforms with the optional GitHub Actions integration use short-lived OIDC credentials. Authorize the repository with `void github connect <project> --repo <owner/repo> --executor github_actions`, set the repository's `VOID_API_URL`, and keep `permissions: id-token: write` in the generated workflow.
|
|
127
66
|
|
|
128
|
-
|
|
67
|
+
If your platform supports managed GitHub builds, the GitHub App can deploy on push without a workflow file. See [GitHub commands](../reference/cli/github.md#github) to install the App and connect your repository.
|
|
129
68
|
|
|
130
|
-
If
|
|
69
|
+
If CI runs typechecking before deploy, run `void prepare` after installing dependencies to generate the `.void/` types.
|
|
131
70
|
|
|
132
|
-
|
|
71
|
+
## Deploy to a team platform
|
|
133
72
|
|
|
134
|
-
|
|
73
|
+
Use the API URL from your administrator. In a new or unlinked app:
|
|
135
74
|
|
|
136
75
|
```sh
|
|
137
|
-
void
|
|
138
|
-
void
|
|
139
|
-
void github status
|
|
76
|
+
void connect https://platform.example.com
|
|
77
|
+
void deploy --platform void --project my-app
|
|
140
78
|
```
|
|
141
79
|
|
|
142
|
-
|
|
80
|
+
Sign in and confirm project creation when asked. To use an existing project, run `void project link`. Later deploys use the saved destination.
|
|
143
81
|
|
|
144
|
-
|
|
82
|
+
Project owners can [share access](./project-collaboration.md). To install a platform for your team, start with [Install a Void Platform](./self-hosted-platform.md), which also compares the deployment features of both targets.
|
|
145
83
|
|
|
146
|
-
###
|
|
84
|
+
### Deploy to another Void platform
|
|
147
85
|
|
|
148
|
-
|
|
86
|
+
For a single deployment to a different platform, connect and name its project:
|
|
149
87
|
|
|
150
88
|
```sh
|
|
151
|
-
void
|
|
89
|
+
void connect https://second.example.com
|
|
90
|
+
VOID_API_URL=https://second.example.com void deploy --platform void --project my-app
|
|
152
91
|
```
|
|
153
92
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
Core self-hosted installations do not support this integration. Use your own CI workflow with a [project deploy token](./platform/installation/first-deployment.md).
|
|
157
|
-
|
|
158
|
-
## Other Targets
|
|
93
|
+
This keeps your saved destination. Each platform has its own projects, secrets, and data. See the [CLI reference](../reference/cli/deploy.md) for target selection and other flags.
|
|
159
94
|
|
|
160
|
-
|
|
95
|
+
## Logs and rollback
|
|
161
96
|
|
|
162
|
-
|
|
97
|
+
Inspect your deployment, read runtime logs, or select a previous deployment:
|
|
163
98
|
|
|
164
|
-
|
|
99
|
+
```sh
|
|
100
|
+
void project status
|
|
101
|
+
void project logs
|
|
102
|
+
void project rollback
|
|
103
|
+
```
|
|
165
104
|
|
|
166
|
-
|
|
105
|
+
Cloudflare logs use a live tail; team platforms retain log history. Before rolling back, check that the earlier code works with your current database schema. See [Project commands](../reference/cli/project.md).
|
|
167
106
|
|
|
168
|
-
|
|
107
|
+
## Other runtimes
|
|
169
108
|
|
|
170
|
-
|
|
109
|
+
Build a standalone server for [Node.js, Bun, or Deno](../integrations/nodejs-bun-deno.md) using the `target` setting. Deploy `dist/ssr` and `dist/client` together using your own hosting. Cloudflare bindings such as D1, KV, R2, and Workers AI are unavailable on these targets.
|
|
171
110
|
|
|
172
111
|
## Usage and execution limit pages
|
|
173
112
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
To customize browser error pages, add either optional file to your app's public assets:
|
|
177
|
-
|
|
178
|
-
- `public/usage-limit.html` for exhausted request allowances.
|
|
179
|
-
- `public/execution-limit.html` for execution limits.
|
|
113
|
+
Team platforms return a structured HTTP 429 to API and Pages action requests when an app exceeds its request or CPU allowance. Browser requests get an error page.
|
|
180
114
|
|
|
181
|
-
Use standalone HTML with inline CSS and data-URL images.
|
|
115
|
+
To customize it, add `public/usage-limit.html` for request limits or `public/execution-limit.html` for execution limits. Use standalone HTML with inline CSS and data-URL images. Scripts, external assets, and form submissions are disabled. Missing custom pages use the built-in page.
|
|
182
116
|
|
|
183
|
-
Responses are not cached.
|
|
117
|
+
Responses are not cached. A streaming response that has already started cannot be replaced with an error page; handle stream failures in your UI.
|
|
@@ -39,7 +39,7 @@ STRIPE_KEY=sk_test_example
|
|
|
39
39
|
VITE_API_ORIGIN=http://localhost:5173
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
Keep `.env` out of Git. Other dotenv files, including `.env.local`, `.env.production`, `.env.example`, and Wrangler’s `.dev.vars*`, are not supported.
|
|
42
|
+
Keep `.env` out of Git. Other dotenv files, including `.env.local`, `.env.production`, `.env.example`, and Wrangler’s `.dev.vars*`, are not supported.
|
|
43
43
|
|
|
44
44
|
Run the local check at any time:
|
|
45
45
|
|
|
@@ -105,7 +105,3 @@ Invalid-value diagnostics redact the supplied value by default. Set `VOID_ENV_UN
|
|
|
105
105
|
## Imports inside `env.ts`
|
|
106
106
|
|
|
107
107
|
Use relative imports or package names inside `env.ts`. TypeScript path aliases and imports that need Vite transforms are not supported.
|
|
108
|
-
|
|
109
|
-
## Migrating from the multi-file model
|
|
110
|
-
|
|
111
|
-
See [Environment migration](/guide/env-migration) for the breaking-change checklist.
|
|
@@ -4,34 +4,35 @@ outline: deep
|
|
|
4
4
|
|
|
5
5
|
# What is Void?
|
|
6
6
|
|
|
7
|
-
Void
|
|
7
|
+
Void is a full-stack framework for Cloudflare Workers, powered by Vite. Build your UI with React, Vue, Svelte, or Solid, and write server code in the same project. Void connects routing, data access, and deployment while keeping types shared across your app.
|
|
8
8
|
|
|
9
|
-
Start with the [Quickstart](./quickstart) to create an app
|
|
9
|
+
Start with the [Quickstart](./quickstart.md) to create and deploy an app. If you already use a meta framework, follow its [integration guide](../integrations/frameworks/overview.md).
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## Server routes and pages
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Files define routes. A handler in `routes/api/users.ts` serves `/api/users`; a component in `pages/users/index.tsx` renders `/users`.
|
|
14
|
+
|
|
15
|
+
Each page can have a companion `.server.ts` file. Its **loader** reads data and returns typed props to the component. Its **actions** handle forms and other mutations, then update the page. Server code stays on the server; components render there initially and run in the browser for navigation and interaction.
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
Use [Pages routing](./pages-routing/overview.md) for a full-stack UI, or keep your own client-side router and call [server routes](./server-routing.md) with [typed fetch](./typed-fetch.md). You can also build an API without a frontend.
|
|
18
|
+
|
|
19
|
+
## Resources from your code
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
Import `db` from `void/db` to query your database. Void provides a local database during development and provisions one when you deploy. Imports also enable resources such as [KV](./kv.md), [object storage](./storage.md), and [queues](./queues.md). Use configuration when you need to connect existing resources.
|
|
18
22
|
|
|
19
|
-
|
|
23
|
+
Your Drizzle schema defines database types. Handlers infer response types, and typed fetch checks their callers. Page loaders and actions carry the same types into components and forms. Changing a field shows you which parts of the app need to change.
|
|
20
24
|
|
|
21
|
-
|
|
22
|
-
- [Database](./database.md), [KV](./kv.md), and [storage](./storage.md) that work locally and in production
|
|
23
|
-
- [Standard Schema](https://standardschema.dev/) validation for runtime values and TypeScript types
|
|
24
|
-
- `void deploy` to build, apply migrations, provision resources, and deploy
|
|
25
|
+
## From local development to production
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
Vite runs your app locally with Cloudflare's runtime. `void deploy` builds it, provisions resources, applies database migrations, and publishes it. [Environment variables](./env-vars.md) use a schema, local values, and production secrets.
|
|
27
28
|
|
|
28
|
-
Deploy to [your own Cloudflare account](
|
|
29
|
+
Deploy to [your own Cloudflare account](./deployment.md#deploy-to-cloudflare), or connect to a [Void platform](./self-hosted-platform.md) run by your team. Both use the same application APIs. A platform adds shared access, deployment history, and administration.
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
Void also deploys [existing frameworks and static sites](./app-types.md). Your framework keeps its routing and rendering; Void handles resources and deployment.
|
|
31
32
|
|
|
32
33
|
## Next steps
|
|
33
34
|
|
|
34
|
-
- [Quickstart](./quickstart):
|
|
35
|
-
- [
|
|
36
|
-
- [
|
|
37
|
-
- [
|
|
35
|
+
- [Quickstart](./quickstart.md): create your first app
|
|
36
|
+
- [Pages Routing](./pages-routing/overview.md): loaders, layouts, and forms
|
|
37
|
+
- [Database](./database.md): schemas, queries, and migrations
|
|
38
|
+
- [Deployment](./deployment.md): Cloudflare, team platforms, and CI
|
|
@@ -27,8 +27,6 @@ await kv.put('user:123', { name: 'Alice', role: 'admin' });
|
|
|
27
27
|
|
|
28
28
|
Values, including strings, are JSON-serialized. Reads preserve their types, so a string such as `"123"` or `"null"` comes back as a string.
|
|
29
29
|
|
|
30
|
-
If an older Void version stored a JSON-looking string as raw text, rewrite that key with `kv.put(key, originalString)`. Existing stored values keep their previous read behavior; Void cannot distinguish an old raw string such as `"123"` from a stored number. Use the original string or read its raw text through `c.env.KV.get(key)` when rewriting it.
|
|
31
|
-
|
|
32
30
|
Add a TTL (in seconds) or absolute expiration (Unix timestamp):
|
|
33
31
|
|
|
34
32
|
```ts
|
|
@@ -22,6 +22,8 @@ export const live = defineLiveStream({
|
|
|
22
22
|
});
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
Void enables live streams when a [scanned file](../reference/resource-inference.md#scanned-directories) imports `void/live`, so keep this module in `src/` or another scanned directory. To keep it in an unscanned directory such as `lib/`, add that directory to [`inference.scanDirs`](../reference/resource-inference.md#custom-scan-directories) and list the default directories you still use, because `scanDirs` replaces them.
|
|
26
|
+
|
|
25
27
|
Expose it from a normal route:
|
|
26
28
|
|
|
27
29
|
```ts
|
|
@@ -29,57 +29,12 @@ export const action = defineHandler.withValidator({
|
|
|
29
29
|
| Nothing (void) | Re-runs the loader, page re-renders with fresh props. |
|
|
30
30
|
| `c.redirect('/path')` | Navigates to another page. |
|
|
31
31
|
|
|
32
|
-
## Named Actions
|
|
33
|
-
|
|
34
|
-
When a page needs multiple mutations, such as updating and deleting a user on the same page, export `actions` (plural) instead of `action`:
|
|
35
|
-
|
|
36
|
-
```ts
|
|
37
|
-
// pages/users/[id].server.ts
|
|
38
|
-
import { defineHandler } from 'void';
|
|
39
|
-
import { db, eq } from 'void/db';
|
|
40
|
-
import { users, updateUserSchema } from '@schema';
|
|
41
|
-
|
|
42
|
-
export const actions = {
|
|
43
|
-
update: defineHandler.withValidator({
|
|
44
|
-
body: updateUserSchema,
|
|
45
|
-
})(async (c, { body }) => {
|
|
46
|
-
await db
|
|
47
|
-
.update(users)
|
|
48
|
-
.set(body)
|
|
49
|
-
.where(eq(users.id, Number(c.req.param('id'))));
|
|
50
|
-
}),
|
|
51
|
-
|
|
52
|
-
delete: defineHandler(async (c) => {
|
|
53
|
-
await db.delete(users).where(eq(users.id, Number(c.req.param('id'))));
|
|
54
|
-
}),
|
|
55
|
-
};
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
Named actions are dispatched via a `?actionName` suffix on the URL (e.g. `/users/42?update`). The client primitives `useForm` and `action()` handle this automatically.
|
|
59
|
-
|
|
60
|
-
Use `action` or `actions` in a file, not both.
|
|
61
|
-
|
|
62
|
-
You can also define an `actions.default` key for the action that runs when no name is specified (i.e. a bare POST to the page URL):
|
|
63
|
-
|
|
64
|
-
```ts
|
|
65
|
-
export const actions = {
|
|
66
|
-
default: defineHandler(async (c) => {
|
|
67
|
-
// runs on POST /users/edit (no ?suffix)
|
|
68
|
-
}),
|
|
69
|
-
delete: defineHandler(async (c) => {
|
|
70
|
-
// runs on POST /users/edit?delete
|
|
71
|
-
}),
|
|
72
|
-
};
|
|
73
|
-
```
|
|
74
|
-
|
|
75
32
|
## Form
|
|
76
33
|
|
|
77
|
-
Pair `Form` with `useForm`
|
|
34
|
+
Pair `Form` with `useForm` to submit values and display validation and action errors. Inputs stay editable when a submission fails.
|
|
78
35
|
|
|
79
36
|
Import `Form` from your adapter. Pass `form` and, optionally, `method="put"`, `"patch"`, or `"delete"`; the default is `"post"`. Use `renderError` for a custom action-error renderer (a snippet in Svelte).
|
|
80
37
|
|
|
81
|
-
On the server, use `limit.response({ message: 'AI is temporarily unavailable. Your draft is still editable.' })` in an AI or Sandbox operation's required `limited` handler. It supplies the status and structured metadata consumed by `Form`.
|
|
82
|
-
|
|
83
38
|
## `useForm`
|
|
84
39
|
|
|
85
40
|
`useForm` handles submissions, loading state, and validation errors. URLs, form values, and error fields are typed from your action.
|
|
@@ -216,6 +171,49 @@ const form = useForm('/users/:id', { name: '' }, { params: { id: '42' } });
|
|
|
216
171
|
<Form form={form} method="put">{/* submits to /users/42 */}</Form>
|
|
217
172
|
```
|
|
218
173
|
|
|
174
|
+
## Named Actions
|
|
175
|
+
|
|
176
|
+
When a page needs multiple mutations, such as updating and deleting a user on the same page, export `actions` (plural) instead of `action`:
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
// pages/users/[id].server.ts
|
|
180
|
+
import { defineHandler } from 'void';
|
|
181
|
+
import { db, eq } from 'void/db';
|
|
182
|
+
import { users, updateUserSchema } from '@schema';
|
|
183
|
+
|
|
184
|
+
export const actions = {
|
|
185
|
+
update: defineHandler.withValidator({
|
|
186
|
+
body: updateUserSchema,
|
|
187
|
+
})(async (c, { body }) => {
|
|
188
|
+
await db
|
|
189
|
+
.update(users)
|
|
190
|
+
.set(body)
|
|
191
|
+
.where(eq(users.id, Number(c.req.param('id'))));
|
|
192
|
+
}),
|
|
193
|
+
|
|
194
|
+
delete: defineHandler(async (c) => {
|
|
195
|
+
await db.delete(users).where(eq(users.id, Number(c.req.param('id'))));
|
|
196
|
+
}),
|
|
197
|
+
};
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Named actions are dispatched via a `?actionName` suffix on the URL (e.g. `/users/42?update`). The client primitives `useForm` and `action()` handle this automatically.
|
|
201
|
+
|
|
202
|
+
Use `action` or `actions` in a file, not both.
|
|
203
|
+
|
|
204
|
+
You can also define an `actions.default` key for the action that runs when no name is specified (i.e. a bare POST to the page URL):
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
export const actions = {
|
|
208
|
+
default: defineHandler(async (c) => {
|
|
209
|
+
// runs on POST /users/edit (no ?suffix)
|
|
210
|
+
}),
|
|
211
|
+
delete: defineHandler(async (c) => {
|
|
212
|
+
// runs on POST /users/edit?delete
|
|
213
|
+
}),
|
|
214
|
+
};
|
|
215
|
+
```
|
|
216
|
+
|
|
219
217
|
### Named Actions with `useForm`
|
|
220
218
|
|
|
221
219
|
When a page exports named actions, append `?actionName` to the URL:
|
|
@@ -258,7 +256,7 @@ Authentication errors (`401`, `403`), server errors (`500`, `502`), and unexpect
|
|
|
258
256
|
Actions can throw `ValidationError` for custom validation logic:
|
|
259
257
|
|
|
260
258
|
```ts
|
|
261
|
-
import { defineHandler, ValidationError } from 'void';
|
|
259
|
+
import { defineHandler, ValidationError } from 'void/handler';
|
|
262
260
|
|
|
263
261
|
export const action = defineHandler(async (c) => {
|
|
264
262
|
const body = await c.req.json();
|
|
@@ -269,6 +267,10 @@ export const action = defineHandler(async (c) => {
|
|
|
269
267
|
});
|
|
270
268
|
```
|
|
271
269
|
|
|
270
|
+
### Usage limits
|
|
271
|
+
|
|
272
|
+
For [AI](../ai.md#usage-limits) and [Sandbox](../sandboxes.md#usage-limits) actions, an uncaught `UsageLimit` automatically produces a structured HTTP 429. To customize the message, catch the error with `instanceof UsageLimit` and return `error.response({ message: 'Try again shortly. Your draft is still editable.' })`. `Form` displays the message and waits until a known retry deadline before allowing resubmission. It keeps the fields editable and never retries automatically.
|
|
273
|
+
|
|
272
274
|
## Authentication and origin checks
|
|
273
275
|
|
|
274
276
|
Browser submissions must come from the same origin as the page, including its scheme, hostname, and port. Void rejects cross-origin page actions with `403 Forbidden`. Server clients can call actions without browser origin headers; actions still need authentication and authorization for protected data.
|
|
@@ -225,9 +225,9 @@ export default function PostPage() {
|
|
|
225
225
|
|
|
226
226
|
## Scroll Restoration
|
|
227
227
|
|
|
228
|
-
|
|
228
|
+
Void manages scroll position for Pages automatically:
|
|
229
229
|
|
|
230
|
-
- **Back/forward navigation**
|
|
230
|
+
- **Back/forward navigation and reloads** restore the saved scroll position.
|
|
231
231
|
- **New navigation** scrolls to the top of the page.
|
|
232
232
|
- **Hash links** (`/docs#api`) scroll to the target element. Same-page hash links (`#section`) skip the server fetch entirely.
|
|
233
233
|
|
|
@@ -144,5 +144,3 @@ Run recovery with the same platform version that created the persisted intent.
|
|
|
144
144
|
`applied` continues without replaying the write; `not-applied` permits that exact
|
|
145
145
|
step to retry. Secret rotation keeps its staged generation, and removal resumes
|
|
146
146
|
from the unresolved cleanup step. Age alone never authorizes a retry.
|
|
147
|
-
|
|
148
|
-
Register administrator domains only after a platform upgrade has completed, and remove them before rolling the platform back to a version that predates this feature: an earlier runtime cannot use the platform credential for them and does not distinguish administrator-registered domains from owner-registered ones.
|
|
@@ -51,28 +51,6 @@ Following waits for the final logs before stopping, including diagnostics writte
|
|
|
51
51
|
|
|
52
52
|
## Checking the Platform
|
|
53
53
|
|
|
54
|
-
### Migrating older deployment assets
|
|
55
|
-
|
|
56
|
-
After upgrading the platform, inspect every page of its asset inventory:
|
|
57
|
-
|
|
58
|
-
```sh
|
|
59
|
-
void platform system asset-migrations --page 1 --limit 100
|
|
60
|
-
void platform deployment migrate-assets <deployment-id> --plan
|
|
61
|
-
void platform deployment migrate-assets <deployment-id> --yes
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
Migrate every deployment with a nonzero `needsMigration` count, including retained
|
|
65
|
-
rollback targets and stored Worker bundles. Investigate entries marked `invalid`
|
|
66
|
-
before continuing. The command verifies each copied asset, preserves originals,
|
|
67
|
-
and applies successive batches. If interrupted, inspect the result and resume
|
|
68
|
-
with the last successful `nextCursor` using `--cursor`; restarting without a
|
|
69
|
-
cursor also verifies and reuses completed copies.
|
|
70
|
-
|
|
71
|
-
Run the inventory again across all pages when finished. Existing applications
|
|
72
|
-
continue serving during this migration, and the provider asset mirror remains.
|
|
73
|
-
Legacy reads remain available while older platform runtimes and cached manifests
|
|
74
|
-
can still reference original assets.
|
|
75
|
-
|
|
76
54
|
### Health checks
|
|
77
55
|
|
|
78
56
|
Use the overview to see recent activity, or run a health check to test the platform's services and database:
|
|
@@ -88,6 +66,17 @@ The dashboard’s **System Status** page refreshes health checks every 30 second
|
|
|
88
66
|
|
|
89
67
|
Use `void platform upgrade`, `repair`, `disable`, and `enable` to maintain your platform. See [platform maintenance](/guide/platform/installation/maintenance#resume-repair-recover-and-upgrade).
|
|
90
68
|
|
|
69
|
+
Upgrades and rollbacks run through the CLI; watching their progress is optional.
|
|
70
|
+
During maintenance, navigating the admin UI automatically redirects to
|
|
71
|
+
`/admin/status`. You can also open that page directly on the API origin. It
|
|
72
|
+
refreshes automatically and shows saved progress and the API's traffic state
|
|
73
|
+
while the API and authentication database remain reachable. If a status refresh
|
|
74
|
+
fails, the last confirmed snapshot is marked as stale. Normal administrator
|
|
75
|
+
changes stay paused during maintenance.
|
|
76
|
+
If the CLI reports an error or a waiting state, follow its recovery instructions
|
|
77
|
+
to resume the operation. See
|
|
78
|
+
[Follow upgrade and rollback progress](/guide/platform/installation/maintenance#follow-upgrade-and-rollback-progress).
|
|
79
|
+
|
|
91
80
|
For disaster recovery, keep a matching PostgreSQL backup, provider data backups, installation identity and complete project-encryption keyring, and immutable runtime artifacts. Keep traffic disabled while restoring data, run `discover` to reconstruct verified local metadata, and review `repair --plan` before recreating missing installer-owned infrastructure. Neither command restores backed-up data. See [Prepare for disaster recovery](/guide/platform/installation/maintenance#prepare-for-disaster-recovery) for the full sequence.
|
|
92
81
|
|
|
93
82
|
## Using Scripts
|