void 0.23.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/AGENTS_TEMPLATE.md +1 -1
- package/README.md +19 -106
- package/dist/{account-cmd-C84Ee8cO.mjs → account-cmd-DcR1ywt8.mjs} +5 -5
- package/dist/{auth-CSkdO2Bb.mjs → auth-7wuZ5ob8.mjs} +22 -49
- package/dist/auth-CdgZ9uag.mjs +2 -0
- package/dist/{auth-link-CioEg6uY.mjs → auth-link-Z6E5DYvM.mjs} +5 -6
- package/dist/{auth-router-BsR981d4.mjs → auth-router-BdM4avI8.mjs} +7 -7
- package/dist/{build-cmd-LzvNJORH.mjs → build-cmd-CEE7D-hM.mjs} +7 -8
- package/dist/{cache-C4MvnrMH.mjs → cache-TcZnBLtH.mjs} +6 -7
- package/dist/{cancel-deploy-abUxpP2n.mjs → cancel-deploy-CYoZmcmR.mjs} +4 -6
- package/dist/{cf-access-P0iZnu0q.mjs → cf-access-AHKBzmuu.mjs} +4 -48
- package/dist/{cf-access-DRsQRe6k.mjs → cf-access-TWNzXltp.mjs} +3 -11
- package/dist/cf-build-output-ChY6-XWP.mjs +2 -0
- package/dist/cli/cli.mjs +49 -46
- package/dist/cli/cloudflare-operation-process.mjs +16 -7
- package/dist/cli/env-schema-probe.mjs +3 -3
- package/dist/client-B4Me-9HE.mjs +2 -0
- package/dist/{client-RV8NVeB8.mjs → client-RsPo8wsP.mjs} +129 -33
- package/dist/{cloudflare-cmd-BcrVyTmJ.mjs → cloudflare-cmd-bhwCxAN6.mjs} +2 -2
- package/dist/{cloudflare-connect-B8uPZ4nx.mjs → cloudflare-connect-CuhRgk3k.mjs} +2 -2
- package/dist/{cloudflare-operations-AiWashgg.mjs → cloudflare-operations-BhbK6yTq.mjs} +1 -1
- package/dist/{cloudflare-operations-fxHb-byx.mjs → cloudflare-operations-CjaV4lZi.mjs} +2 -2
- package/dist/{connect-Bd4kJd9U.mjs → connect-DCvUmPXY.mjs} +13 -10
- package/dist/{create-project-Boczwj5r.mjs → create-project-C734I-Mu.mjs} +1 -1
- package/dist/{create-project-bMf6ffLZ.mjs → create-project-eAPgYq35.mjs} +13 -13
- package/dist/{db-8uG64XLl.mjs → db-C07GEdKF.mjs} +27 -30
- package/dist/{delete-NvbiyeJf.mjs → delete-pKMVsrpJ.mjs} +5 -6
- package/dist/deploy-BDu1vhSH.mjs +2 -0
- package/dist/{deploy-DzAIwqNU.mjs → deploy-DfsAe-T0.mjs} +9567 -9215
- package/dist/{dev-inbox-P0u4tM8Y.mjs → dev-inbox-D64ZKUod.mjs} +5 -6
- package/dist/{domain-y5Tvydvo.mjs → domain-D3uA9ize.mjs} +8 -8
- package/dist/{email-B3umsW75.mjs → email-z3o2cwjH.mjs} +8 -8
- package/dist/{env-BS6qYHDb.mjs → env-3Q8-_2IH.mjs} +7 -9
- package/dist/{env-types-C2_bIk_b.mjs → env-types-D5kds_OZ.mjs} +1 -1
- package/dist/{env-validation-DbTg7-ar.mjs → env-validation-cZBvGWaP.mjs} +1 -1
- package/dist/{env-validation-BPn7vk-V.mjs → env-validation-vBSQ8gw5.mjs} +3 -3
- package/dist/gen-ById9r2j.mjs +2 -0
- package/dist/{gen-B580--vC.mjs → gen-NjwoG9FK.mjs} +2 -4
- package/dist/{github-cmd-v45BdfKX.mjs → github-cmd-DquUq-b1.mjs} +15 -24
- package/dist/{headers-DWi2IXWx.mjs → headers-2rKda9Y6.mjs} +1 -1
- package/dist/help-DPGBwomV.mjs +2 -0
- package/dist/{help-daGKjXGk.mjs → help-DRZXC4fj.mjs} +8 -4
- package/dist/{inbound-aVHEUhKo.mjs → inbound-fRkqcXaC.mjs} +1 -1
- package/dist/index.d.mts +18 -14
- package/dist/index.mjs +2176 -2110
- package/dist/{info-B97bTX9N.mjs → info-BmA3_IFZ.mjs} +1 -3
- package/dist/{init-Bvy7zrBo.mjs → init-DT7yuuyl.mjs} +28 -27
- package/dist/{link-CDqqCjFl.mjs → link-CXOlqh2F.mjs} +6 -7
- package/dist/{list-CZj0dzKY.mjs → list-eEWVJEPn.mjs} +8 -9
- package/dist/{local-d1-2CMnpuW_.mjs → local-d1-Df4XpwhW.mjs} +1 -1
- package/dist/log-vqY3pqwI.mjs +29 -0
- package/dist/login-C98-sw79.mjs +2 -0
- package/dist/{login-UZKFM_u7.mjs → login-pWQHYVu2.mjs} +12 -10
- package/dist/{logs-CUZ6t9t3.mjs → logs-DnxVX7TR.mjs} +11 -13
- package/dist/migrate-CEu2X5DB.mjs +2 -0
- package/dist/{migrate-DHul7PRV.mjs → migrate-CV1on-yJ.mjs} +2 -4
- package/dist/{operator-args-CLgKGlwU.mjs → operator-args-CAVcmwUt.mjs} +12 -5
- package/dist/{operator-auth-8KnOVXVd.mjs → operator-auth-CkmTE3rt.mjs} +2 -2
- package/dist/{operator-client-DUwumHpQ.mjs → operator-client-LmwjxT6q.mjs} +3 -3
- package/dist/{operator-cmd-DBA6dl0m.mjs → operator-cmd-d-IEKgNk.mjs} +6 -6
- package/dist/{output-Dm_A4Tbv.mjs → output-BBsUwdyT.mjs} +22 -14
- package/dist/pages/client.d.mts +3 -0
- package/dist/pages/client.mjs +120 -29
- package/dist/pages/index.mjs +1 -1
- package/dist/{platform-args-BJdRtlLq.mjs → platform-args-Bzf8JPc2.mjs} +11 -3
- package/dist/platform-args-Cq6EjQro.mjs +2 -0
- package/dist/{platform-auth-config-B56E9YP1.mjs → platform-auth-config-0V0lA3pF.mjs} +7 -7
- package/dist/{platform-auth-protection-BDWO_aER.mjs → platform-auth-protection-DFeJ-JkK.mjs} +9 -9
- package/dist/{platform-auth-recovery-1gg4CSRe.mjs → platform-auth-recovery-ICy4muq6.mjs} +7 -7
- package/dist/{platform-cmd-Bt-1w6pY.mjs → platform-cmd-BPySFOew.mjs} +1 -1
- package/dist/{platform-cmd-DMcQStSc.mjs → platform-cmd-D7vSWMvV.mjs} +38 -28
- package/dist/platform-discovery-DDDUvnqp.mjs +27 -0
- package/dist/{platform-domain-BNkcz0OB.mjs → platform-domain-CUdY064e.mjs} +5 -5
- package/dist/{platform-lifecycle-BE6C_jxh.mjs → platform-lifecycle-BaUdTRPU.mjs} +1 -1
- package/dist/{platform-lifecycle-9OyBALhH.mjs → platform-lifecycle-Dm09JNkn.mjs} +4404 -3297
- package/dist/{platform-management-CjwLVQwN.mjs → platform-management-BSEc_ZeG.mjs} +48 -11
- package/dist/platform-management-Bp6aoH2C.mjs +2 -0
- package/dist/{platform-plans-config-BNGKGr4P.mjs → platform-plans-config-B0pOVQyW.mjs} +3 -3
- package/dist/{platform-recovery-D6KSpuFm.mjs → platform-recovery-WOZ95Uze.mjs} +4 -4
- package/dist/{platform-registry-QBa4DK32.mjs → platform-registry-KfNEF84O.mjs} +3 -3
- package/dist/{prepare-B5Mkic5u.mjs → prepare-39EvOhI6.mjs} +2 -4
- package/dist/prepare-CnjcTV2s.mjs +2 -0
- package/dist/{prepare-DOsL0CC9.mjs → prepare-DnaKBi--.mjs} +1 -1
- package/dist/{project-C0Fqu05O.mjs → project-BkbfDs0V.mjs} +15 -82
- package/dist/project-IOjBU8R6.mjs +2 -0
- package/dist/{project-cmd-CNzrqvBv.mjs → project-cmd-Bs5A392E.mjs} +21 -22
- package/dist/{project-team-DQOWPfQT.mjs → project-team-ohAWWaew.mjs} +8 -9
- package/dist/{project-token-CTDYU0Cc.mjs → project-token-CP01Jna6.mjs} +6 -9
- package/dist/{project-zero-trust-BNAkW-_0.mjs → project-zero-trust-BzkVgx35.mjs} +5 -6
- package/dist/prompts-6OSVA7DJ.mjs +2087 -0
- package/dist/prompts-ZAuJlyCj.mjs +2 -0
- package/dist/{provision-C4ORE7G7.mjs → provision-BEv0k-qz.mjs} +1 -1
- package/dist/{provision-CJFgTZY8.mjs → provision-Btj1jppf.mjs} +5 -7
- package/dist/{requests-MhxYnau8.mjs → requests-B3PBuGlX.mjs} +5 -6
- package/dist/{rollback-CJ6iSDoU.mjs → rollback-DDub9GsO.mjs} +9 -10
- package/dist/runtime/ai.mjs +3 -5
- package/dist/runtime/email/testing.mjs +2 -2
- package/dist/runtime/email.mjs +36 -18
- package/dist/runtime/remote/index.mjs +2 -2
- package/dist/runtime/routing.mjs +1 -1
- package/dist/{secret-Dli5fP0B.mjs → secret-3c72lY1U.mjs} +15 -16
- package/dist/{skills-D1II1Juz.mjs → skills-BPQUGClu.mjs} +1 -1
- package/dist/{subcommand-prompt-CY1C4fvl.mjs → subcommand-prompt-Dhom39bd.mjs} +40 -32
- 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 +22 -23
- package/sandbox.Dockerfile +1 -1
- package/skills/void/SKILL.md +6 -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 -102
- package/skills/void/docs/guide/edge/headers.md +1 -1
- package/skills/void/docs/guide/email/domains.md +5 -1
- package/skills/void/docs/guide/email/sending.md +1 -1
- 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 +24 -9
- package/skills/void/docs/guide/platform/development/schema-ci.md +7 -1
- package/skills/void/docs/guide/platform/installation/ci.md +1 -1
- package/skills/void/docs/guide/platform/installation/credentials.md +10 -3
- package/skills/void/docs/guide/platform/installation/domains.md +8 -3
- package/skills/void/docs/guide/platform/installation/first-deployment.md +2 -2
- package/skills/void/docs/guide/platform/installation/maintenance.md +37 -5
- package/skills/void/docs/guide/platform/installation/prerequisites.md +87 -14
- package/skills/void/docs/guide/platform/installation/setup.md +80 -10
- package/skills/void/docs/guide/quickstart.md +37 -80
- package/skills/void/docs/guide/remote-dev.md +1 -1
- 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/auth.md +4 -3
- package/skills/void/docs/reference/cli/database.md +1 -1
- package/skills/void/docs/reference/cli/deploy.md +21 -1
- package/skills/void/docs/reference/cli/platform-installation.md +42 -27
- package/skills/void/docs/reference/cli/platform-operations.md +4 -8
- package/skills/void/docs/reference/cli/platform-zero-trust.md +14 -0
- package/skills/void/docs/reference/cli/platform.md +5 -0
- package/skills/void/docs/reference/config.md +1 -1
- package/skills/void/docs/reference/resource-inference.md +11 -8
- package/dist/auth-CCjt0hcq.mjs +0 -2
- package/dist/cf-build-output-_0HNWysu.mjs +0 -2
- package/dist/client-Cu7jWiF1.mjs +0 -2
- package/dist/deploy-bjXdFCtn.mjs +0 -2
- package/dist/dist-BuDuKZJv.mjs +0 -2
- package/dist/dist-CTBk70IR.mjs +0 -1310
- package/dist/gen-BVaUUumi.mjs +0 -2
- package/dist/help-DofyZuY7.mjs +0 -2
- package/dist/log-ChfPKsVd.mjs +0 -26
- package/dist/login-DYt_An22.mjs +0 -2
- package/dist/migrate-8_2u55MD.mjs +0 -2
- package/dist/platform-args-D3RXyR6h.mjs +0 -2
- package/dist/platform-management-CnyTdcWX.mjs +0 -2
- package/dist/prepare-cgvDMtSb.mjs +0 -2
- package/dist/project-BuUwfj6f.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
|
@@ -4,7 +4,7 @@ import { m as readConfig } from "./config-Br_JZD6u.mjs";
|
|
|
4
4
|
import { a as hasSandboxSqliteMigration, c as resolveSandboxConfig, i as assertSandboxNamespaceConfig, l as sandboxContainerConfig, r as SANDBOX_MIGRATION_TAG } from "./config-C_XRIPx2.mjs";
|
|
5
5
|
import { i as persistCloudflareConfig, r as materializeCloudflareConfig } from "./cloudflare-config-Bktvwtpf.mjs";
|
|
6
6
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
7
|
-
import { appendSqliteClassMigration } from "@void/deploy-core";
|
|
7
|
+
import { appendSqliteClassMigration, isRecord } from "@void/deploy-core";
|
|
8
8
|
import { createHash } from "node:crypto";
|
|
9
9
|
import { SyntaxKind, applyEdits, createScanner, findNodeAtLocation, modify, parse, parseTree } from "jsonc-parser";
|
|
10
10
|
//#region src/cli/wrangler.ts
|
|
@@ -686,7 +686,10 @@ function writeProvisionedWranglerConfig(root, patch, options) {
|
|
|
686
686
|
const matches = [];
|
|
687
687
|
for (let i = 0; i < currentList.length; i++) {
|
|
688
688
|
const entry = currentList[i];
|
|
689
|
-
if (isRecord(entry) && entry[identityKey] === binding) matches.push(
|
|
689
|
+
if (isRecord(entry) && entry[identityKey] === binding) matches.push({
|
|
690
|
+
index: i,
|
|
691
|
+
entry
|
|
692
|
+
});
|
|
690
693
|
}
|
|
691
694
|
if (matches.length > 1) throw new Error(`deploy: cannot update "${configPath}" — binding ${JSON.stringify(binding)} is declared ${matches.length} times in "${field}". Void cannot choose which entry to update, and wrangler rejects duplicate binding names. Remove the duplicate and retry.`);
|
|
692
695
|
const owners = collectWorkerBindingNames(configWithoutField(currentConfig, field));
|
|
@@ -694,8 +697,7 @@ function writeProvisionedWranglerConfig(root, patch, options) {
|
|
|
694
697
|
const owner = owners.get(binding);
|
|
695
698
|
if (owner !== void 0) throw new Error(`deploy: cannot update "${configPath}" — cannot adopt ${JSON.stringify(binding)} into "${field}" because that binding name is already used by a ${owner} binding. Wrangler requires every binding name to be unique across the whole worker, so this would make the config undeployable. Rename the conflicting binding and retry.`);
|
|
696
699
|
if (matches.length === 1) {
|
|
697
|
-
const index = matches[0];
|
|
698
|
-
const existing = isRecord(currentList[index]) ? currentList[index] : {};
|
|
700
|
+
const { index, entry: existing } = matches[0];
|
|
699
701
|
for (const [key, value] of Object.entries(properties)) if (!jsonEqual(existing[key], value)) set([
|
|
700
702
|
field,
|
|
701
703
|
index,
|
|
@@ -752,20 +754,16 @@ function writeProvisionedWranglerConfig(root, patch, options) {
|
|
|
752
754
|
const upsertQueueEntries = (section, entries) => {
|
|
753
755
|
if (!entries || entries.length === 0) return;
|
|
754
756
|
const currentQueues = assertObjectContainer(parseJsonc(text).queues, "queues");
|
|
755
|
-
|
|
756
|
-
const currentList = Array.isArray(currentQueues?.[section]) ? [...currentQueues[section]] : [];
|
|
757
|
+
const currentList = section === "producers" ? assertValidQueueProducers(currentQueues?.producers) : Array.isArray(currentQueues?.consumers) ? [...currentQueues.consumers] : [];
|
|
757
758
|
for (const entry of entries) {
|
|
758
759
|
let index;
|
|
759
760
|
if (section === "producers") {
|
|
760
761
|
const matches = [];
|
|
761
|
-
for (let i = 0; i < currentList.length; i++)
|
|
762
|
-
const existing = currentList[i];
|
|
763
|
-
if (isRecord(existing) && existing.binding === entry.binding) matches.push(i);
|
|
764
|
-
}
|
|
762
|
+
for (let i = 0; i < currentList.length; i++) if (currentList[i].binding === entry.binding) matches.push(i);
|
|
765
763
|
if (matches.length > 1) throw new Error(`deploy: cannot update "${configPath}" — queue producer binding ${JSON.stringify(entry.binding)} is declared ${matches.length} times across producers. A producer binding must map to exactly one queue, so wrangler rejects this config. Remove the duplicate producers and retry.`);
|
|
766
764
|
if (matches.length === 1) {
|
|
767
765
|
const existing = currentList[matches[0]];
|
|
768
|
-
if (
|
|
766
|
+
if (existing.queue !== entry.queue) throw new Error(`deploy: cannot update "${configPath}" — queue producer binding ${JSON.stringify(entry.binding)} is already bound to queue ${JSON.stringify(existing.queue)}, but queue ${JSON.stringify(entry.queue)} also requests it. A producer binding must map to exactly one queue. Rename or remove the conflicting producer and retry.`);
|
|
769
767
|
}
|
|
770
768
|
index = matches.length === 1 ? matches[0] : -1;
|
|
771
769
|
workerBindingOwners ??= collectWorkerBindingNames(parseJsonc(text));
|
|
@@ -774,7 +772,7 @@ function writeProvisionedWranglerConfig(root, patch, options) {
|
|
|
774
772
|
if (owner !== void 0) throw new Error(`deploy: cannot update "${configPath}" — queue producer binding ${JSON.stringify(bindingName)} is already used by a ${owner} binding. Wrangler requires every binding name to be unique across the whole worker, so this producer would make the config undeployable. Rename the conflicting binding (or the queue) and retry.`);
|
|
775
773
|
} else index = currentList.findIndex((existing) => isRecord(existing) && existing.queue === entry.queue);
|
|
776
774
|
if (index >= 0) {
|
|
777
|
-
const existing =
|
|
775
|
+
const existing = currentList[index];
|
|
778
776
|
for (const [key, value] of Object.entries(entry)) {
|
|
779
777
|
if (value === void 0) continue;
|
|
780
778
|
if (!jsonEqual(existing[key], value)) set([
|
|
@@ -1243,9 +1241,6 @@ function offsetToLineColumn(text, offset) {
|
|
|
1243
1241
|
column
|
|
1244
1242
|
};
|
|
1245
1243
|
}
|
|
1246
|
-
function isRecord(value) {
|
|
1247
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1248
|
-
}
|
|
1249
1244
|
function validateDurableObjectMigrations(value, configPath) {
|
|
1250
1245
|
if (value === void 0) return [];
|
|
1251
1246
|
if (!Array.isArray(value)) throw new Error(`deploy: cannot update "${configPath}" — "migrations" must be an array of Durable Object migration steps.`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "void",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/voidzero-dev/void.git",
|
|
@@ -331,24 +331,24 @@
|
|
|
331
331
|
}
|
|
332
332
|
},
|
|
333
333
|
"dependencies": {
|
|
334
|
-
"@cloudflare/build-output-utils": "0.8.
|
|
335
|
-
"@cloudflare/codemods": "0.
|
|
336
|
-
"@cloudflare/config": "0.
|
|
334
|
+
"@cloudflare/build-output-utils": "0.8.5",
|
|
335
|
+
"@cloudflare/codemods": "0.4.0",
|
|
336
|
+
"@cloudflare/config": "0.23.0",
|
|
337
337
|
"@cloudflare/sandbox": "1.0.0",
|
|
338
|
-
"@cloudflare/vite-plugin": "1.62.
|
|
339
|
-
"@cloudflare/workers-auth": "0.
|
|
338
|
+
"@cloudflare/vite-plugin": "1.62.5",
|
|
339
|
+
"@cloudflare/workers-auth": "0.12.0",
|
|
340
340
|
"@cloudflare/workers-types": "^4.20260702.1",
|
|
341
341
|
"@napi-rs/keyring": "2.1.0",
|
|
342
|
-
"@void/deploy-cloudflare": "0.
|
|
343
|
-
"@void/deploy-core": "0.
|
|
344
|
-
"@void/edge": "0.
|
|
345
|
-
"@void/isr": "0.
|
|
346
|
-
"@void/platform": "0.
|
|
342
|
+
"@void/deploy-cloudflare": "0.25.0",
|
|
343
|
+
"@void/deploy-core": "0.25.0",
|
|
344
|
+
"@void/edge": "0.25.0",
|
|
345
|
+
"@void/isr": "0.25.0",
|
|
346
|
+
"@void/platform": "0.25.0",
|
|
347
347
|
"acorn": "^8.18.0",
|
|
348
|
-
"better-auth": "^1.7.
|
|
348
|
+
"better-auth": "^1.7.7",
|
|
349
349
|
"better-sqlite3": "^13.0.3",
|
|
350
350
|
"blake3-jit": "^1.1.0",
|
|
351
|
-
"cf": "1.0.0-beta.
|
|
351
|
+
"cf": "1.0.0-beta.12",
|
|
352
352
|
"drizzle-arktype": "^0.1.3",
|
|
353
353
|
"drizzle-kit": "^0.31.11",
|
|
354
354
|
"drizzle-orm": "^0.45.3",
|
|
@@ -356,28 +356,27 @@
|
|
|
356
356
|
"drizzle-zod": "^0.8.3",
|
|
357
357
|
"email-validator": "^2.0.4",
|
|
358
358
|
"es-module-lexer": "^3.0.2",
|
|
359
|
-
"hono": "^4.13.
|
|
360
|
-
"ignore": "^7.0.
|
|
359
|
+
"hono": "^4.13.13",
|
|
360
|
+
"ignore": "^7.0.12",
|
|
361
361
|
"jiti": "^2.7.0",
|
|
362
362
|
"jsonc-parser": "3.3.1",
|
|
363
363
|
"mime": "4.1.0",
|
|
364
|
-
"miniflare": "5.
|
|
364
|
+
"miniflare": "5.20261001.0-alpha",
|
|
365
365
|
"minimatch": "^10.2.6",
|
|
366
366
|
"mysql2": "3.24.5",
|
|
367
|
-
"pg": "8.23.
|
|
368
|
-
"postal-mime": "^4.0.
|
|
367
|
+
"pg": "8.23.1",
|
|
368
|
+
"postal-mime": "^4.0.4",
|
|
369
369
|
"proper-lockfile": "^4.1.2",
|
|
370
370
|
"undici": "8.11.2"
|
|
371
371
|
},
|
|
372
372
|
"devDependencies": {
|
|
373
|
-
"@clack/core": "^1.5.1",
|
|
374
|
-
"@clack/prompts": "^1.8.1",
|
|
375
373
|
"@electric-sql/pglite": "0.5.8",
|
|
376
374
|
"@types/better-sqlite3": "^9.6.0",
|
|
377
|
-
"@types/node": "^26.6.
|
|
375
|
+
"@types/node": "^26.6.4",
|
|
378
376
|
"@types/pg": "^8.23.1",
|
|
379
377
|
"@types/proper-lockfile": "^4.1.4",
|
|
380
|
-
"
|
|
378
|
+
"@voidzero-dev/vite-plus-prompts": "0.0.0",
|
|
379
|
+
"arktype": "^2.2.7",
|
|
381
380
|
"ci-info": "^4.4.0",
|
|
382
381
|
"estree-walker": "^3.0.3",
|
|
383
382
|
"fast-wrap-ansi": "^0.2.2",
|
|
@@ -394,7 +393,7 @@
|
|
|
394
393
|
"zod": "^4.6.5"
|
|
395
394
|
},
|
|
396
395
|
"peerDependencies": {
|
|
397
|
-
"@void/md": "0.
|
|
396
|
+
"@void/md": "0.25.0",
|
|
398
397
|
"arktype": ">=2.0.0",
|
|
399
398
|
"valibot": ">=1.0.0-beta.7",
|
|
400
399
|
"vite": "^8.0.0",
|
package/sandbox.Dockerfile
CHANGED
package/skills/void/SKILL.md
CHANGED
|
@@ -16,7 +16,12 @@ workflows. Mention Wrangler only when the user needs to recognize a literal
|
|
|
16
16
|
configuration file or environment variable.
|
|
17
17
|
|
|
18
18
|
Use `void` and `@void/*` in imports, examples, and package manifests. Follow the
|
|
19
|
-
project's existing framework and deployment destination.
|
|
19
|
+
project's existing framework and deployment destination. Deploying to a Void
|
|
20
|
+
platform requires an explicit `void connect <url>` first; never infer a platform
|
|
21
|
+
from old examples, tokens, or project IDs.
|
|
22
|
+
For a one-time deployment elsewhere, connect to that platform, then set
|
|
23
|
+
`VOID_API_URL` for the deploy command and pass `--project <slug>`. This preserves
|
|
24
|
+
the app's existing saved destination, including when the target project is new.
|
|
20
25
|
|
|
21
26
|
## Task Routing
|
|
22
27
|
|
|
@@ -4,19 +4,24 @@ outline: deep
|
|
|
4
4
|
|
|
5
5
|
# AI
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Run Workers AI models and provider APIs from server code with `ai` from `void/ai`. Provider requests use Cloudflare's [AI Gateway](https://developers.cloudflare.com/ai-gateway/).
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
import { ai } from 'void/ai';
|
|
11
|
-
```
|
|
9
|
+
## Local Development
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
For a direct Cloudflare project, connect your account and start development:
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
```sh
|
|
14
|
+
void connect --platform cloudflare
|
|
15
|
+
npm run dev
|
|
16
|
+
```
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
When the app imports `void/ai`, Void enables a remote Workers AI binding during
|
|
19
|
+
development and preview. Requests use your Cloudflare account and its allowance;
|
|
20
|
+
Workers AI has no local simulator. Use your Cloudflare login or
|
|
21
|
+
`CLOUDFLARE_API_TOKEN` in an automated environment.
|
|
18
22
|
|
|
19
|
-
|
|
23
|
+
For a team platform, use `void connect <platform-url>` and link your project.
|
|
24
|
+
Development requests use that platform's account and usage limits.
|
|
20
25
|
|
|
21
26
|
## Basic Usage
|
|
22
27
|
|
|
@@ -29,16 +34,16 @@ import { ai } from 'void/ai';
|
|
|
29
34
|
export const POST = defineHandler(async (c) => {
|
|
30
35
|
const { prompt } = await c.req.json();
|
|
31
36
|
|
|
32
|
-
|
|
37
|
+
return ai
|
|
33
38
|
.run('@cf/meta/llama-3.3-70b-instruct-fp8-fast', {
|
|
34
39
|
messages: [{ role: 'user', content: prompt }],
|
|
35
40
|
})
|
|
36
|
-
.match({ ok: (result) => result, limited: (limit) => limit.response() });
|
|
37
|
-
|
|
38
|
-
return c.json(result);
|
|
41
|
+
.match({ ok: (result) => c.json(result), limited: (limit) => limit.response() });
|
|
39
42
|
});
|
|
40
43
|
```
|
|
41
44
|
|
|
45
|
+
Every operation runs through `.match({ ok, limited })`. Both handlers are required. Return a fallback from `limited`, or use `limit.response()` to send a structured HTTP 429. Limits include `resource`, `reason`, and an optional `retryAt`; other failures throw. Await `.match()`, rather than the operation itself.
|
|
46
|
+
|
|
42
47
|
You can use any model available through Cloudflare's AI binding, including Workers AI models such as `@cf/meta/llama-3.3-70b-instruct-fp8-fast` and Cloudflare Gateway models such as `google/gemini-2.5-flash` or `openai/gpt-4.1-mini`. The input object must match the selected Cloudflare model's schema. Models that return binary data, such as generated images, are returned as a `Blob` from `ai.run()`.
|
|
43
48
|
|
|
44
49
|
## Streaming
|
|
@@ -60,6 +65,8 @@ export const POST = defineHandler(async (c) => {
|
|
|
60
65
|
});
|
|
61
66
|
```
|
|
62
67
|
|
|
68
|
+
Streaming responses end with a `void:error` SSE event if generation is interrupted after the response starts. A recognized quota interruption calls your `limited` handler and emits `void:limit`, preserving the message from `limit.response()`. `fetchStream()` throws on either terminal event so your UI can exit its generating state. This also applies to streaming provider responses and `ai.run()` with `stream: true`.
|
|
69
|
+
|
|
63
70
|
## Listing Models
|
|
64
71
|
|
|
65
72
|
Use `ai.models()` to list available models:
|
|
@@ -85,23 +92,6 @@ const result = await ai
|
|
|
85
92
|
.match({ ok: (result) => result, limited: (limit) => limit.response() });
|
|
86
93
|
```
|
|
87
94
|
|
|
88
|
-
## Local Development
|
|
89
|
-
|
|
90
|
-
For a direct Cloudflare project, connect your account and start development:
|
|
91
|
-
|
|
92
|
-
```sh
|
|
93
|
-
void connect --platform cloudflare
|
|
94
|
-
npm run dev
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
When the app imports `void/ai`, Void enables a remote Workers AI binding during
|
|
98
|
-
development and preview. Requests use your Cloudflare account and its allowance;
|
|
99
|
-
Workers AI has no local simulator. Use your Cloudflare login or
|
|
100
|
-
`CLOUDFLARE_API_TOKEN` in an automated environment.
|
|
101
|
-
|
|
102
|
-
For a team platform, use `void connect <platform-url>` and link your project.
|
|
103
|
-
Development requests use that platform's account and usage limits.
|
|
104
|
-
|
|
105
95
|
## Usage Limits
|
|
106
96
|
|
|
107
97
|
Workers AI usage is measured in [neurons](https://developers.cloudflare.com/workers-ai/platform/pricing/).
|
|
@@ -127,33 +117,7 @@ const result = await ai
|
|
|
127
117
|
.match({ ok: (result) => result, limited: (limit) => limit.response() });
|
|
128
118
|
```
|
|
129
119
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
```ts
|
|
133
|
-
const result = await ai
|
|
134
|
-
.run('openai/gpt-4.1-mini', {
|
|
135
|
-
messages: [{ role: 'user', content: 'Summarize this deploy.' }],
|
|
136
|
-
})
|
|
137
|
-
.match({ ok: (result) => result, limited: (limit) => limit.response() });
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
Pass Cloudflare AI Gateway options as the third argument:
|
|
141
|
-
|
|
142
|
-
```ts
|
|
143
|
-
const result = await ai
|
|
144
|
-
.run(
|
|
145
|
-
'openai/gpt-4.1-mini',
|
|
146
|
-
{
|
|
147
|
-
messages: [{ role: 'user', content: 'Summarize this deploy.' }],
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
gateway: {
|
|
151
|
-
skipCache: true,
|
|
152
|
-
},
|
|
153
|
-
},
|
|
154
|
-
)
|
|
155
|
-
.match({ ok: (result) => result, limited: (limit) => limit.response() });
|
|
156
|
-
```
|
|
120
|
+
Pass AI Gateway options as the third argument: `ai.run(model, inputs, { gateway: { skipCache: true } })`.
|
|
157
121
|
|
|
158
122
|
For provider-native requests on a direct deployment, configure [`ai.gateway`](../integrations/cloudflare.md#ai-self-host).
|
|
159
123
|
|
|
@@ -173,7 +137,7 @@ import { ai } from 'void/ai';
|
|
|
173
137
|
export const POST = defineHandler(async (c) => {
|
|
174
138
|
const { prompt } = await c.req.json();
|
|
175
139
|
|
|
176
|
-
|
|
140
|
+
return ai
|
|
177
141
|
.provider('openai')
|
|
178
142
|
.fetch('/chat/completions', {
|
|
179
143
|
body: {
|
|
@@ -183,9 +147,6 @@ export const POST = defineHandler(async (c) => {
|
|
|
183
147
|
},
|
|
184
148
|
})
|
|
185
149
|
.match({ ok: (result) => result, limited: (limit) => limit.response() });
|
|
186
|
-
|
|
187
|
-
const result = await response.json();
|
|
188
|
-
return c.json(result);
|
|
189
150
|
});
|
|
190
151
|
```
|
|
191
152
|
|
|
@@ -205,8 +166,6 @@ const response = await ai
|
|
|
205
166
|
},
|
|
206
167
|
})
|
|
207
168
|
.match({ ok: (result) => result, limited: (limit) => limit.response() });
|
|
208
|
-
|
|
209
|
-
const result = await response.json();
|
|
210
169
|
```
|
|
211
170
|
|
|
212
171
|
### Custom Providers
|
|
@@ -277,30 +236,9 @@ export const POST = defineHandler(async (c) => {
|
|
|
277
236
|
|
|
278
237
|
### Provider Key Convention
|
|
279
238
|
|
|
280
|
-
Provider-native requests
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
| ------------------ | --------------------- |
|
|
284
|
-
| `openai` | `OPENAI_API_KEY` |
|
|
285
|
-
| `anthropic` | `ANTHROPIC_API_KEY` |
|
|
286
|
-
| `google-ai-studio` | `GOOGLE_API_KEY` |
|
|
287
|
-
| `deepseek` | `DEEPSEEK_API_KEY` |
|
|
288
|
-
| `groq` | `GROQ_API_KEY` |
|
|
289
|
-
| `mistral` | `MISTRAL_API_KEY` |
|
|
290
|
-
| `grok` | `GROK_API_KEY` |
|
|
291
|
-
| `openrouter` | `OPENROUTER_API_KEY` |
|
|
292
|
-
| `perplexity` | `PERPLEXITY_API_KEY` |
|
|
293
|
-
| `cohere` | `COHERE_API_KEY` |
|
|
294
|
-
| `cerebras` | `CEREBRAS_API_KEY` |
|
|
295
|
-
| `huggingface` | `HUGGINGFACE_API_KEY` |
|
|
296
|
-
| `replicate` | `REPLICATE_API_KEY` |
|
|
297
|
-
| `baseten` | `BASETEN_API_KEY` |
|
|
298
|
-
| `cartesia` | `CARTESIA_API_KEY` |
|
|
299
|
-
| `deepgram` | `DEEPGRAM_API_KEY` |
|
|
300
|
-
| `elevenlabs` | `ELEVENLABS_API_KEY` |
|
|
301
|
-
| `fal` | `FAL_API_KEY` |
|
|
302
|
-
| `ideogram` | `IDEOGRAM_API_KEY` |
|
|
303
|
-
| `parallel` | `PARALLEL_API_KEY` |
|
|
239
|
+
Provider-native requests use a project secret, such as `OPENAI_API_KEY` for OpenAI or `GOOGLE_API_KEY` for Google AI Studio.
|
|
240
|
+
|
|
241
|
+
See the [provider key reference](../reference/api/resources.md#provider-keys) for supported providers and their secret names.
|
|
304
242
|
|
|
305
243
|
OpenAI-style providers use `Authorization: Bearer <key>`. Google AI Studio uses `x-goog-api-key`. Use `apiKeyHeader` and `apiKeyPrefix` for custom providers.
|
|
306
244
|
|
|
@@ -155,5 +155,3 @@ void db generate
|
|
|
155
155
|
```
|
|
156
156
|
|
|
157
157
|
Review and commit the SQL before deploying. Void includes your auth configuration and plugin tables; you don't need to duplicate them in `db/schema.ts` or run the Better Auth CLI.
|
|
158
|
-
|
|
159
|
-
MySQL stores OAuth access, refresh, and ID tokens as unbounded text. Existing direct-deploy MySQL apps should run `void db generate` once after upgrading to widen earlier `varchar(255)` token columns. Void platform deployments apply the same safe widening automatically.
|
|
@@ -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
|
:::
|