void 0.24.0 → 0.25.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-DcR1ywt8.mjs} +5 -5
- package/dist/{auth-CQkSDS50.mjs → auth-7wuZ5ob8.mjs} +3 -3
- package/dist/{auth-DX3JURcX.mjs → auth-CdgZ9uag.mjs} +1 -1
- package/dist/{auth-link-D75t9wO2.mjs → auth-link-Z6E5DYvM.mjs} +5 -6
- package/dist/{auth-router-ClfhL1J7.mjs → auth-router-BdM4avI8.mjs} +7 -7
- package/dist/{build-cmd-zMi1iFnS.mjs → build-cmd-CEE7D-hM.mjs} +6 -7
- package/dist/{cache-ZtQmyxVV.mjs → cache-TcZnBLtH.mjs} +6 -7
- package/dist/{cancel-deploy-Box0kkEV.mjs → cancel-deploy-CYoZmcmR.mjs} +4 -6
- package/dist/{cf-access-BGe5sWXF.mjs → cf-access-AHKBzmuu.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 +2 -2
- package/dist/cli/env-schema-probe.mjs +2 -2
- package/dist/client-B4Me-9HE.mjs +2 -0
- package/dist/{client-DKAsFA4X.mjs → client-RsPo8wsP.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-BCdXSsmo.mjs → cloudflare-operations-BhbK6yTq.mjs} +1 -1
- package/dist/{cloudflare-operations-DzH-A966.mjs → cloudflare-operations-CjaV4lZi.mjs} +2 -2
- package/dist/{connect-B-usTnlF.mjs → connect-DCvUmPXY.mjs} +12 -9
- package/dist/{create-project-FWbf5Olo.mjs → create-project-C734I-Mu.mjs} +1 -1
- package/dist/{create-project-CYOOAYcn.mjs → create-project-eAPgYq35.mjs} +6 -6
- package/dist/{db-Ck2eZ2iB.mjs → db-C07GEdKF.mjs} +25 -28
- package/dist/{delete-sK56qtzZ.mjs → delete-pKMVsrpJ.mjs} +5 -6
- package/dist/deploy-BDu1vhSH.mjs +2 -0
- package/dist/{deploy-gCVaiJbS.mjs → deploy-DfsAe-T0.mjs} +9212 -8902
- package/dist/{dev-inbox-P0u4tM8Y.mjs → dev-inbox-D64ZKUod.mjs} +5 -6
- package/dist/{domain-DFfQE8jg.mjs → domain-D3uA9ize.mjs} +8 -8
- package/dist/{email-CdnhUHvJ.mjs → email-z3o2cwjH.mjs} +7 -7
- package/dist/{env-DmGdHi5i.mjs → env-3Q8-_2IH.mjs} +6 -8
- package/dist/{env-validation-zZOCcQVZ.mjs → env-validation-cZBvGWaP.mjs} +1 -1
- package/dist/gen-ById9r2j.mjs +2 -0
- package/dist/{gen-CshAkukR.mjs → gen-NjwoG9FK.mjs} +2 -4
- package/dist/{github-cmd-DftuEvIt.mjs → github-cmd-DquUq-b1.mjs} +7 -16
- package/dist/help-DPGBwomV.mjs +2 -0
- package/dist/{help-Dotbf6iz.mjs → help-DRZXC4fj.mjs} +3 -3
- package/dist/index.d.mts +18 -14
- package/dist/index.mjs +2166 -2096
- package/dist/{info-B97bTX9N.mjs → info-BmA3_IFZ.mjs} +1 -3
- package/dist/{init-BTQEZZGJ.mjs → init-DT7yuuyl.mjs} +16 -18
- package/dist/{link-B46sYH0K.mjs → link-CXOlqh2F.mjs} +6 -7
- package/dist/{list-BnPrIsU_.mjs → list-eEWVJEPn.mjs} +8 -9
- package/dist/{local-d1-2CMnpuW_.mjs → local-d1-Df4XpwhW.mjs} +1 -1
- package/dist/login-C98-sw79.mjs +2 -0
- package/dist/{login-BuiMyUrx.mjs → login-pWQHYVu2.mjs} +9 -7
- package/dist/{logs-CZG9d-ic.mjs → logs-DnxVX7TR.mjs} +7 -8
- package/dist/migrate-CEu2X5DB.mjs +2 -0
- package/dist/{migrate-q4_njtaW.mjs → migrate-CV1on-yJ.mjs} +2 -4
- package/dist/{operator-args-B3BTmSoi.mjs → operator-args-CAVcmwUt.mjs} +1 -1
- package/dist/{operator-auth-7erYc6Lt.mjs → operator-auth-CkmTE3rt.mjs} +2 -2
- package/dist/{operator-client-CpHjTd0t.mjs → operator-client-LmwjxT6q.mjs} +2 -2
- package/dist/{operator-cmd-DGqPJUD3.mjs → operator-cmd-d-IEKgNk.mjs} +6 -6
- package/dist/{output-CbM85T4k.mjs → output-BBsUwdyT.mjs} +5 -5
- package/dist/pages/client.d.mts +3 -0
- package/dist/pages/client.mjs +120 -29
- package/dist/{platform-args-3k8X9-H_.mjs → platform-args-Bzf8JPc2.mjs} +1 -1
- package/dist/platform-args-Cq6EjQro.mjs +2 -0
- package/dist/{platform-auth-config-DDrxUy4m.mjs → platform-auth-config-0V0lA3pF.mjs} +7 -7
- package/dist/{platform-auth-protection-BLadnnct.mjs → platform-auth-protection-DFeJ-JkK.mjs} +8 -8
- package/dist/{platform-auth-recovery-CmCzX2Fl.mjs → platform-auth-recovery-ICy4muq6.mjs} +7 -7
- package/dist/{platform-cmd-pMTRhvYs.mjs → platform-cmd-BPySFOew.mjs} +1 -1
- package/dist/{platform-cmd-DMDEc9uS.mjs → platform-cmd-D7vSWMvV.mjs} +37 -27
- package/dist/platform-discovery-DDDUvnqp.mjs +27 -0
- package/dist/{platform-domain-Di6EYrQl.mjs → platform-domain-CUdY064e.mjs} +4 -4
- package/dist/{platform-lifecycle-BFdSi9Qt.mjs → platform-lifecycle-BaUdTRPU.mjs} +1 -1
- package/dist/{platform-lifecycle-BBoNzojY.mjs → platform-lifecycle-Dm09JNkn.mjs} +3901 -3651
- package/dist/{platform-management-CWOQOWXm.mjs → platform-management-BSEc_ZeG.mjs} +47 -10
- package/dist/platform-management-Bp6aoH2C.mjs +2 -0
- package/dist/{platform-plans-config-Vl9BP3H4.mjs → platform-plans-config-B0pOVQyW.mjs} +3 -3
- package/dist/{platform-recovery-BJnQJEtQ.mjs → platform-recovery-WOZ95Uze.mjs} +3 -3
- package/dist/{prepare-CBLT3CHH.mjs → prepare-39EvOhI6.mjs} +1 -3
- package/dist/{project-DKG5Ra8p.mjs → project-BkbfDs0V.mjs} +1 -1
- package/dist/{project-DsblYifa.mjs → project-IOjBU8R6.mjs} +1 -1
- package/dist/{project-cmd-DxnXstAq.mjs → project-cmd-Bs5A392E.mjs} +21 -22
- package/dist/{project-team-BmHcaALJ.mjs → project-team-ohAWWaew.mjs} +8 -9
- package/dist/{project-token-GionZlBI.mjs → project-token-CP01Jna6.mjs} +6 -9
- package/dist/{project-zero-trust-JLCjVQA7.mjs → project-zero-trust-BzkVgx35.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/{provision-CVku1JFU.mjs → provision-BEv0k-qz.mjs} +1 -1
- package/dist/{provision-CaoxO_U7.mjs → provision-Btj1jppf.mjs} +5 -7
- package/dist/{requests-BOjIVAeF.mjs → requests-B3PBuGlX.mjs} +5 -6
- package/dist/{rollback-CwR3pLj3.mjs → rollback-DDub9GsO.mjs} +9 -10
- package/dist/runtime/email/testing.mjs +1 -1
- package/dist/runtime/email.mjs +35 -17
- package/dist/runtime/routing.mjs +1 -1
- package/dist/{secret-ByWJWBUG.mjs → secret-3c72lY1U.mjs} +15 -16
- package/dist/{skills-C1PlclPt.mjs → skills-BPQUGClu.mjs} +1 -1
- package/dist/{subcommand-prompt-klFCfcor.mjs → subcommand-prompt-Dhom39bd.mjs} +2 -2
- package/dist/sveltekit.d.mts +1 -1
- package/dist/sveltekit.mjs +4 -9
- package/dist/{wrangler-7K-bW_DL.mjs → wrangler-DhUerFkW.mjs} +10 -15
- package/package.json +21 -21
- package/sandbox.Dockerfile +1 -1
- package/skills/void/docs/guide/ai.md +24 -86
- package/skills/void/docs/guide/auth.md +0 -2
- package/skills/void/docs/guide/database/d1.md +7 -7
- 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/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/maintenance.md +30 -10
- package/skills/void/docs/guide/platform/installation/prerequisites.md +79 -7
- package/skills/void/docs/guide/quickstart.md +37 -80
- package/skills/void/docs/guide/sandboxes.md +36 -46
- 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 +27 -0
- package/skills/void/docs/reference/api.md +1 -1
- package/skills/void/docs/reference/cli/deploy.md +1 -1
- package/skills/void/docs/reference/cli/platform-operations.md +4 -8
- package/skills/void/docs/reference/cli/platform.md +5 -0
- package/skills/void/docs/reference/resource-inference.md +11 -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/platform-args-DdnM6WIf.mjs +0 -2
- package/dist/platform-management-DG47jys8.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
- package/dist/{platform-registry-DkPPXfp_.mjs → platform-registry-KfNEF84O.mjs} +1 -1
|
@@ -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) and [Sandbox](../sandboxes.md) actions, return `limit.response({ message: 'Try again shortly. Your draft is still editable.' })` from the operation's `limited` handler. `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
|
|
@@ -11,9 +11,7 @@ void platform auth login
|
|
|
11
11
|
void platform config plans
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
Choose a plan to inspect or edit it, copy one into a new plan, or choose the default for new accounts.
|
|
15
|
-
|
|
16
|
-
Inspection and previews are available immediately after a platform upgrade. Allow 15 minutes before applying changes.
|
|
14
|
+
Choose a plan to inspect or edit it, copy one into a new plan, or choose the default for new accounts. Changes require no app or platform redeploy.
|
|
17
15
|
|
|
18
16
|
## Use the Dashboard
|
|
19
17
|
|
|
@@ -90,8 +88,6 @@ Storage figures shown for D1, R2, and KV are informational and cannot be edited
|
|
|
90
88
|
|
|
91
89
|
The preview shows the affected account count and checks a sample for accounts already above a proposed quota. Lowering a quota can restrict existing apps, including accounts outside that sample. Usage history and billing periods are preserved, so a plan change does not reset usage. Manual administrator suspensions remain in effect.
|
|
92
90
|
|
|
93
|
-
After the initial platform upgrade, request quota accounting includes unlimited plans too. For an account that was unlimited before that upgrade, its quota counter may not include earlier requests in the current billing period. Historical analytics remain available. When introducing its first cap, allow for the remaining period or wait until its next billing period.
|
|
94
|
-
|
|
95
91
|
## Archive or Remove a Plan
|
|
96
92
|
|
|
97
93
|
Archive a plan to stop assigning it to new accounts while preserving its current accounts:
|
|
@@ -8,10 +8,7 @@ Project Zero Trust puts Cloudflare Access in front of the hostnames of projects
|
|
|
8
8
|
|
|
9
9
|
This is separate from the Access login and protection for the platform API. Projects deployed directly to Cloudflare are not affected.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
reuses the platform policy or helps you select separate company rules, and finishes
|
|
13
|
-
setup before opening traffic. Existing installations keep their settings when
|
|
14
|
-
upgraded; use this page to configure app access if it has not been set up yet.
|
|
11
|
+
Choose app access during `void platform install`, or configure it later using this page. The installer reuses the platform policy or helps you select separate company rules, and finishes setup before opening traffic.
|
|
15
12
|
|
|
16
13
|
If you choose public apps in an account with Default-Deny, Void manages scoped
|
|
17
14
|
public rules instead. New projects and custom domains remain public automatically.
|
|
@@ -14,7 +14,13 @@ vp run --filter @voidcloud/api db:generate
|
|
|
14
14
|
|
|
15
15
|
Review the generated SQL and migration journal before committing them. Released migrations are append-only. An upgrade applies new migrations while the previous Workers may still serve requests, so schema changes must remain compatible with that code.
|
|
16
16
|
|
|
17
|
-
`platform/packages/api/drizzle/compatibility.json` records which earlier runtimes have been verified against the new schema. Add an edge only after testing that compatibility. The runtime build checks that the migration files and recorded schema history agree.
|
|
17
|
+
`platform/packages/api/drizzle/compatibility.json` records which earlier runtimes have been verified against the new schema. Add an edge only after testing that compatibility. The runtime build checks that the migration files and recorded schema history agree.
|
|
18
|
+
|
|
19
|
+
## Runtime artifact contract
|
|
20
|
+
|
|
21
|
+
`@void/platform` contains installation manifests, resource naming, discovery contracts, Worker configuration, and deployable bundles under the `./installer` export. Platform source lives in `platform/packages/`.
|
|
22
|
+
|
|
23
|
+
Runtime artifacts include migration SQL, its journal, and a rollback compatibility manifest. Drizzle authoring snapshots remain in the source tree. Migrations are forward-only; compatibility edges in `platform/packages/api/drizzle/compatibility.json` must be tested against the earlier runtime before publication. The build verifies schema lineage and hashes the journal and SQL files.
|
|
18
24
|
|
|
19
25
|
## CI in a Fork
|
|
20
26
|
|
|
@@ -42,11 +42,6 @@ secret manager to an object keyed by each exact API/proxy origin, with
|
|
|
42
42
|
and stops if the gate still rejects its checks. Account-wide Default-Deny and
|
|
43
43
|
deployed-application policies remain your responsibility.
|
|
44
44
|
|
|
45
|
-
If **System Status** reports `proxy HTTP 302 (redirect)` on an older Access-protected
|
|
46
|
-
installation, upgrade with `void platform upgrade <id>`. Current installations use
|
|
47
|
-
a private connection for the dashboard's proxy health check. Keep the proxy's
|
|
48
|
-
Access protection enabled.
|
|
49
|
-
|
|
50
45
|
### Expired administrator setup code
|
|
51
46
|
|
|
52
47
|
Resume an unfinished installation with `void platform install --resume --name <id>`.
|
|
@@ -68,7 +63,7 @@ Repair recreates missing infrastructure that the installer owns. It does not res
|
|
|
68
63
|
|
|
69
64
|
### Upgrade the platform
|
|
70
65
|
|
|
71
|
-
Keep the platform runtime current when updating the Void CLI.
|
|
66
|
+
Keep the platform runtime current when updating the Void CLI.
|
|
72
67
|
|
|
73
68
|
Use the installed CLI's packaged runtime to upgrade:
|
|
74
69
|
|
|
@@ -92,10 +87,6 @@ manager so they can also restore a missing Worker during repair.
|
|
|
92
87
|
|
|
93
88
|
Database migrations only move forward. Void checks compatibility before upgrading and tells you if an intermediate release is needed. If deployment fails, it attempts to restore the previous Workers against the compatible database schema. Retrying does not repeat completed migrations.
|
|
94
89
|
|
|
95
|
-
Upgrades automatically enable managed Sandboxes. The platform runtime token needs Account / Containers: Edit and Account / Cloudchamber: Edit, and the Cloudflare account must use Workers Paid before its first Sandbox application deploy. The upgrade itself does not probe Containers access, so platforms that do not deploy Sandbox applications need no additional plan or permissions.
|
|
96
|
-
|
|
97
|
-
When upgrading from a release that used tenant-owned Sandbox containers, the upgrade may first ask you to finish the legacy cleanup. Follow the [`sandbox-drain` instructions](../../../reference/cli/platform-operations.md#operator-system), then rerun the upgrade. Administrator login remains available during that maintenance step.
|
|
98
|
-
|
|
99
90
|
After a successful upgrade, you can restore a declared-compatible earlier runtime without reversing migrations:
|
|
100
91
|
|
|
101
92
|
```sh
|
|
@@ -107,6 +98,35 @@ Keep the earlier runtime files if you need rollback. If the installed version is
|
|
|
107
98
|
|
|
108
99
|
:::
|
|
109
100
|
|
|
101
|
+
### Follow upgrade and rollback progress
|
|
102
|
+
|
|
103
|
+
Watching progress is optional: a running upgrade or rollback proceeds through
|
|
104
|
+
the CLI without action on the status page. During maintenance, navigating the
|
|
105
|
+
admin UI automatically redirects to `/admin/status`. You can also open it
|
|
106
|
+
directly on your platform API origin and sign in as an administrator.
|
|
107
|
+
|
|
108
|
+
The read-only page shows the saved operation, source and target versions, and
|
|
109
|
+
the traffic state reported by the API. It refreshes automatically every five
|
|
110
|
+
seconds while visible. If updates fail, it keeps the last confirmed snapshot
|
|
111
|
+
and marks it as out of date. Normal administrator changes remain paused.
|
|
112
|
+
|
|
113
|
+
Sign-in and status remain available while the API and authentication database
|
|
114
|
+
are reachable. An operation completing
|
|
115
|
+
does not confirm every project's health. A disabled installation keeps traffic
|
|
116
|
+
paused after an upgrade or rollback.
|
|
117
|
+
|
|
118
|
+
If an operation fails or waits for DNS or Sandbox drain work, the CLI prints
|
|
119
|
+
the recovery instructions and command needed to resume. Resolve the reported
|
|
120
|
+
problem, then resume with the same runtime files. For a custom rollback, retain
|
|
121
|
+
the source runtime files too. `void platform status <id>` also prints locally saved progress
|
|
122
|
+
before checking the live API; this local checkpoint can be out of date if another
|
|
123
|
+
administrator changed the installation.
|
|
124
|
+
|
|
125
|
+
When application traffic is paused, visitors receive a temporary-unavailability
|
|
126
|
+
page with a **Try again** link. API requests and form submissions still receive
|
|
127
|
+
HTTP 503 responses. Void does not automatically replay requests; visitors who
|
|
128
|
+
submitted a form should check its result before submitting it again.
|
|
129
|
+
|
|
110
130
|
### Manage an installation from another machine
|
|
111
131
|
|
|
112
132
|
Use `discover` to restore the administrator's local installation records:
|
|
@@ -73,16 +73,88 @@ Use any PostgreSQL provider that accepts connections from your computer and Clou
|
|
|
73
73
|
2. Open the provider's connection details and select the primary database. Use a direct connection or a session-mode pooler, not transaction pooling. The connection must work from both your computer and Cloudflare.
|
|
74
74
|
3. Copy the PostgreSQL connection URL, including the password and SSL settings, into your password manager. Paste only the URL—not a surrounding `psql` command—into Void's `PostgreSQL DATABASE_URL` prompt, as the provider gives it, including SSL settings such as `sslmode=verify-full`. A Hyperdrive that Void creates trusts only public certificate authorities, so if your database uses a private certificate authority, use a separately managed Hyperdrive, as described below.
|
|
75
75
|
|
|
76
|
-
| Provider
|
|
77
|
-
|
|
|
78
|
-
| [PlanetScale Postgres](https://planetscale.com/docs/postgres/connecting)
|
|
79
|
-
| [Neon](https://neon.com/docs/get-started-with-neon/connect-neon)
|
|
80
|
-
| [Supabase](https://supabase.com/docs/guides/database/connecting-to-postgres) | Open **Connect** and use the direct connection where IPv6 is available, or the **Session pooler** on port `5432` for IPv4 connectivity. Do not select the transaction pooler on `6543`. Replace the password placeholder with your database password. |
|
|
81
|
-
|
|
82
|
-
For a dedicated Supabase project, [disable the Data API](https://supabase.com/docs/guides/api/securing-your-api#disable-the-data-api) so the platform's tables are not exposed through Supabase's auto-generated endpoints. Void uses the PostgreSQL connection, not Supabase API keys.
|
|
76
|
+
| Provider | Connection setup |
|
|
77
|
+
| ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
78
|
+
| [PlanetScale Postgres](https://planetscale.com/docs/postgres/connecting) | Choose **Postgres**, not Vitess/MySQL. Open **Connect**, create role credentials, and use the direct primary connection on port `5432`, not PgBouncer on `6432`. |
|
|
79
|
+
| [Neon](https://neon.com/docs/get-started-with-neon/connect-neon) | Open **Connect**, select the database and owner role, and turn **connection pooling off**. |
|
|
83
80
|
|
|
84
81
|
Once installation claims the database, continue using that same database for resume and maintenance commands. Uninstall never deletes external PostgreSQL.
|
|
85
82
|
|
|
83
|
+
### Use a provider CLI
|
|
84
|
+
|
|
85
|
+
You can create the database and retrieve its connection URL from either provider's CLI instead of its dashboard.
|
|
86
|
+
|
|
87
|
+
::: details PlanetScale Postgres
|
|
88
|
+
|
|
89
|
+
Install the latest [PlanetScale CLI](https://planetscale.com/docs/cli/planetscale-environment-setup). On macOS, use `brew install pscale`; the installation guide also covers Linux and Windows.
|
|
90
|
+
|
|
91
|
+
Sign in and list your organizations and regions:
|
|
92
|
+
|
|
93
|
+
```sh
|
|
94
|
+
pscale auth login
|
|
95
|
+
pscale org list
|
|
96
|
+
pscale region list --org <organization>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Replace `<organization>` with your organization slug and choose a region. List the available Postgres cluster sizes and their prices for that region:
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
pscale size cluster list --org <organization> --engine postgresql --region <region>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Create a dedicated Postgres database with your chosen cluster size, then create a role with permission to create and migrate Void's tables:
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
pscale database create void-platform \
|
|
109
|
+
--org <organization> \
|
|
110
|
+
--engine postgresql \
|
|
111
|
+
--region <region> \
|
|
112
|
+
--cluster-size <cluster-size> \
|
|
113
|
+
--wait
|
|
114
|
+
|
|
115
|
+
pscale role create void-platform main void_owner \
|
|
116
|
+
--org <organization> \
|
|
117
|
+
--inherited-roles postgres
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Save the **DATABASE URL** printed by the role-creation command in your password manager and paste it into Void's `PostgreSQL DATABASE_URL` prompt. Use the direct primary connection on port `5432` with `sslmode=verify-full`. The role's password is shown when it is created, so save it before closing the terminal.
|
|
121
|
+
|
|
122
|
+
See PlanetScale's [database commands](https://planetscale.com/docs/cli/database) and [role commands](https://planetscale.com/docs/cli/role) for more options.
|
|
123
|
+
|
|
124
|
+
:::
|
|
125
|
+
|
|
126
|
+
::: details Neon
|
|
127
|
+
|
|
128
|
+
Install the latest [Neon CLI](https://neon.com/docs/cli/install) and sign in:
|
|
129
|
+
|
|
130
|
+
```sh
|
|
131
|
+
pnpm add --global neon@latest
|
|
132
|
+
neon login
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Create a dedicated project, database, and owner role. Replace `<region-id>` with one of Neon's [supported regions](https://neon.com/docs/cli/projects#create), such as `aws-us-east-2`:
|
|
136
|
+
|
|
137
|
+
```sh
|
|
138
|
+
neon projects create --name void-platform \
|
|
139
|
+
--database void_platform \
|
|
140
|
+
--role void_owner \
|
|
141
|
+
--region-id <region-id>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Use the project ID from the output to retrieve a direct primary connection URL with TLS certificate verification:
|
|
145
|
+
|
|
146
|
+
```sh
|
|
147
|
+
neon connection-string --project-id <project-id> \
|
|
148
|
+
--database-name void_platform \
|
|
149
|
+
--role-name void_owner \
|
|
150
|
+
--endpoint-type read_write \
|
|
151
|
+
--ssl verify-full
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Save the printed URL in your password manager and paste it into Void's `PostgreSQL DATABASE_URL` prompt. Keep this connection unpooled. See Neon's [connection-string command](https://neon.com/docs/cli/connection-string) for more options.
|
|
155
|
+
|
|
156
|
+
:::
|
|
157
|
+
|
|
86
158
|
### Use an existing Hyperdrive
|
|
87
159
|
|
|
88
160
|
The installer can create Hyperdrive for you or use one you manage separately. For an existing configuration:
|
|
@@ -4,65 +4,51 @@ outline: deep
|
|
|
4
4
|
|
|
5
5
|
# Quickstart
|
|
6
6
|
|
|
7
|
-
Create a Void app, run it locally, and deploy it. You can also [add Void to an existing Vite app](#adding-to-an-existing-vite-app).
|
|
7
|
+
Create a Void app, run it locally, and deploy it. You can also [add Void to an existing Vite app](#adding-to-an-existing-vite-app).
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Create an app
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
In an empty directory, install Void and run setup:
|
|
12
12
|
|
|
13
13
|
::: code-group
|
|
14
14
|
|
|
15
15
|
```sh [npm]
|
|
16
16
|
npm install -D void
|
|
17
|
+
npx void init
|
|
17
18
|
```
|
|
18
19
|
|
|
19
20
|
```sh [pnpm]
|
|
20
21
|
pnpm add -D void
|
|
22
|
+
pnpm void init
|
|
21
23
|
```
|
|
22
24
|
|
|
23
25
|
```sh [yarn]
|
|
24
26
|
yarn add -D void
|
|
27
|
+
yarn void init
|
|
25
28
|
```
|
|
26
29
|
|
|
27
30
|
```sh [bun]
|
|
28
31
|
bun add -D void
|
|
32
|
+
bunx void init
|
|
29
33
|
```
|
|
30
34
|
|
|
31
35
|
:::
|
|
32
36
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
::: code-group
|
|
36
|
-
|
|
37
|
-
```sh [npm]
|
|
38
|
-
npx void init
|
|
39
|
-
```
|
|
37
|
+
Choose your UI framework, a starter, and a deployment target. Vite+ is the default build tool. D1 is a good first database: it runs locally without a separate database server. Choose Cloudflare to deploy to your own account, or skip deployment setup for now.
|
|
40
38
|
|
|
41
|
-
|
|
42
|
-
pnpm void init
|
|
43
|
-
```
|
|
39
|
+
With pnpm, `pnpm create void my-app` also creates the project directory and configures native build permissions for you.
|
|
44
40
|
|
|
45
|
-
|
|
46
|
-
yarn void init
|
|
47
|
-
```
|
|
41
|
+
## Run locally
|
|
48
42
|
|
|
49
|
-
```sh
|
|
50
|
-
|
|
43
|
+
```sh
|
|
44
|
+
npm run dev
|
|
51
45
|
```
|
|
52
46
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
Void asks you to choose Vite+ or Vite, a UI framework, a starter, and a deployment target. Vite+ is the default. D1 needs no local database server; choose PostgreSQL or MySQL if you use an external database. You can skip deployment setup and decide later.
|
|
56
|
-
|
|
57
|
-
With pnpm, you can start with `pnpm create void my-app`. It configures native build permissions before installing Void.
|
|
58
|
-
|
|
59
|
-
The examples below use `void` for brevity. Outside package scripts, run the local binary with `npx void`, `pnpm void`, `yarn void`, or `bunx void`. Keep Void installed in the project so the CLI and app use the same version.
|
|
47
|
+
Open `http://localhost:5173`. In a Pages starter, `pages/` contains your UI and companion `.server.ts` files contain its server loaders and actions. Loaders return data to page components as typed props.
|
|
60
48
|
|
|
61
|
-
##
|
|
49
|
+
## Call a server route
|
|
62
50
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
Database-backed starters include `routes/api/hello.ts`. You can edit its `GET` handler, or create this file if you started with Static Pages:
|
|
51
|
+
Edit `routes/api/hello.ts`, or create it if your starter doesn't include it:
|
|
66
52
|
|
|
67
53
|
```ts
|
|
68
54
|
import { defineHandler } from 'void';
|
|
@@ -72,75 +58,46 @@ export const GET = defineHandler(() => {
|
|
|
72
58
|
});
|
|
73
59
|
```
|
|
74
60
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
```sh
|
|
78
|
-
npm run dev
|
|
79
|
-
```
|
|
61
|
+
Visit `http://localhost:5173/api/hello` to see the response. From your client code, call it with Void's typed fetch:
|
|
80
62
|
|
|
81
|
-
|
|
63
|
+
```ts
|
|
64
|
+
import { fetch } from 'void/client';
|
|
82
65
|
|
|
83
|
-
|
|
84
|
-
|
|
66
|
+
const { message } = await fetch('/api/hello');
|
|
67
|
+
```
|
|
85
68
|
|
|
86
|
-
|
|
69
|
+
The file path defines the URL, and the handler defines the response type. Change `message` in the handler and TypeScript checks the client against the new shape.
|
|
87
70
|
|
|
88
|
-
|
|
71
|
+
Database starters also include `db/schema.ts`. Its Drizzle schema defines your tables and query types; Void runs a local database and provisions one when you deploy.
|
|
89
72
|
|
|
90
|
-
|
|
91
|
-
void deploy
|
|
92
|
-
```
|
|
73
|
+
## Deploy
|
|
93
74
|
|
|
94
|
-
If you
|
|
75
|
+
If you chose a target during setup:
|
|
95
76
|
|
|
96
77
|
```sh
|
|
97
|
-
void deploy
|
|
78
|
+
npx void deploy
|
|
98
79
|
```
|
|
99
80
|
|
|
100
|
-
|
|
81
|
+
If you skipped setup, select your Cloudflare account:
|
|
101
82
|
|
|
102
83
|
```sh
|
|
103
|
-
void
|
|
104
|
-
void project link
|
|
105
|
-
void deploy
|
|
84
|
+
npx void deploy --platform cloudflare
|
|
106
85
|
```
|
|
107
86
|
|
|
108
|
-
Void builds the app, provisions
|
|
109
|
-
|
|
110
|
-
See [Deployment](./deployment.md) for CI setup and rollback.
|
|
111
|
-
|
|
112
|
-
## Using with Coding Agents
|
|
113
|
-
|
|
114
|
-
`void init` detects your coding agent and installs its instructions and skills. If no agent is detected, use the bundled docs linked in `AGENTS.md`. In agents that support it, load the `/void` skill and describe the app you want to build. See [Coding Agents](../integrations/agents) for setup details.
|
|
87
|
+
Void opens your browser to sign in when needed, builds the app, provisions resources, applies migrations, and prints the deployed URL. Later deploys use the saved target. See [Deployment](./deployment.md) for team platforms, CI, and rollback.
|
|
115
88
|
|
|
116
|
-
##
|
|
89
|
+
## Adding to an existing Vite app
|
|
117
90
|
|
|
118
|
-
|
|
91
|
+
Install Void and run `void init` with your package manager as shown [above](#create-an-app). Setup adds `voidPlugin()` to your Vite config and creates the remaining project files. If the config needs a manual edit, the CLI shows the change to make.
|
|
119
92
|
|
|
120
|
-
|
|
93
|
+
For a meta framework such as TanStack Start, React Router, or SvelteKit, follow its [integration guide](../integrations/frameworks/overview.md).
|
|
121
94
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
Enable the plugin in `vite.config.ts`:
|
|
125
|
-
|
|
126
|
-
```ts
|
|
127
|
-
import { defineConfig } from 'vite';
|
|
128
|
-
import { voidPlugin } from 'void';
|
|
129
|
-
|
|
130
|
-
export default defineConfig({
|
|
131
|
-
plugins: [voidPlugin()],
|
|
132
|
-
});
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
Then run `void init` with your package manager to configure the remaining project files.
|
|
95
|
+
## Next steps
|
|
136
96
|
|
|
137
|
-
|
|
97
|
+
- [Pages Routing](./pages-routing/overview.md): loaders, layouts, and forms
|
|
98
|
+
- [Server Routing](./server-routing.md): params, middleware, and validation
|
|
99
|
+
- [Database](./database.md): queries and migrations
|
|
100
|
+
- [Environment Variables](./env-vars.md): local values and production secrets
|
|
101
|
+
- [Coding Agents](../integrations/agents.md): use Void's bundled docs and skills
|
|
138
102
|
|
|
139
103
|
If a manual pnpm install reports blocked build scripts, run `pnpm approve-builds` for `esbuild`, `sharp`, and `workerd`. Set `better-sqlite3: false` in `pnpm-workspace.yaml`'s `allowBuilds`; Void uses its bundled binaries.
|
|
140
|
-
|
|
141
|
-
## Next steps
|
|
142
|
-
|
|
143
|
-
- To understand what kind of apps are supported: [Supported App Types](./app-types)
|
|
144
|
-
- [Server Routing](./server-routing): dynamic params, middleware, and validation
|
|
145
|
-
- [Database](./database): queries, migrations, and generated types
|
|
146
|
-
- [Type Safety](./type-safety): end-to-end typed fetch client
|