void 0.10.12 → 0.20.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 +6 -0
- package/{skills/void/docs/node_modules/void/node_modules/pglite-server/LICENSE.md → LICENSE} +1 -1
- package/README.md +34 -8
- package/dist/{auth-qgMlYp7Z.d.mts → auth-DkcFflXV.d.mts} +10 -11
- package/dist/auth-W9WII-mN.mjs +630 -0
- package/dist/{auth-cmd-BqsdZJp5.mjs → auth-cmd-CYVhSNFy.mjs} +4 -3
- package/dist/{auth-migrations-BTZ-ATvQ.mjs → auth-migrations-9vif1uj8.mjs} +53 -12
- package/dist/{better-auth-shared-BQooDxbw.mjs → better-auth-shared-CYw1T3k4.mjs} +7 -10
- package/dist/{better-auth-shared-DealXecJ.d.mts → better-auth-shared-DSCeohOK.d.mts} +10 -5
- package/dist/{build-cmd-Bujrv5q-.mjs → build-cmd-CkVD1uOh.mjs} +6 -4
- package/dist/{cache-C11V8Fxq.mjs → cache-QcUfR-ff.mjs} +9 -5
- package/dist/{cancel-deploy-fwFYF04b.mjs → cancel-deploy-DsvWKFTe.mjs} +3 -2
- package/dist/cf-access-AJ1ehiFR.mjs +42 -0
- package/dist/cf-access-DsSsZUPr.mjs +67 -0
- package/dist/cli/cli.d.mts +1 -1
- package/dist/cli/cli.mjs +1592 -153
- package/dist/cli/env-schema-probe.d.mts +48 -61
- package/dist/cli/env-schema-probe.mjs +10 -58
- package/dist/{client-Gb71-XkG.mjs → client-CyCHWSO_.mjs} +61 -463
- package/dist/cloudflare-auth-DRkGe7-s.mjs +170 -0
- package/dist/cloudflare-cmd-D3ME2GAe.mjs +62 -0
- package/dist/cloudflare-connect-BivMefMA.mjs +56 -0
- package/dist/cloudflare-operations-CPTpRW6d.mjs +566 -0
- package/dist/{config-BkTvs43g.mjs → config-BQFq7QvD.mjs} +85 -41
- package/dist/{config-CutEMNGJ.mjs → config-NOG_U1aK.mjs} +10 -15
- package/dist/connect-D9Yr-T5f.mjs +79 -0
- package/dist/{create-project-DsYvl3TB.mjs → create-project-DMV-csEm.mjs} +26 -16
- package/dist/database-provider.d.mts +21 -0
- package/dist/database-provider.mjs +6 -0
- package/dist/{db-DOiJMRt2.mjs → db-BxoUWL0F.mjs} +600 -115
- package/dist/{delete-mh6p-zkQ.mjs → delete-iJOqxBz1.mjs} +9 -6
- package/dist/{deploy-u7Rv9q_q.mjs → deploy-CcDoeBIf.mjs} +3451 -1986
- package/dist/dev-inbox-DkgRWLkW.mjs +307 -0
- package/dist/{discover-CJHyvYfR.mjs → discover-xvfrgJeo.mjs} +3 -3
- package/dist/{magic-string.es-ZQjdJFFn.mjs → dist-BR1quN_w.mjs} +570 -216
- package/dist/{dist-DaKKDf8D.mjs → dist-BrsS7cai.mjs} +17 -2
- package/dist/{dist-BuiRJkTd.mjs → dist-m40_XgNh.mjs} +48 -33
- package/dist/{domain-DiaNQbrl.mjs → domain-gu_iaHmn.mjs} +41 -4
- package/dist/dotenv-VQxupEUv.mjs +181 -0
- package/dist/edge.d.mts +2 -0
- package/dist/edge.mjs +2 -0
- package/dist/email-Ce6SQq-i.mjs +182 -0
- package/dist/email-r6DHJyAB.mjs +262 -0
- package/dist/{entry-D7yy4xVH.mjs → entry-DU3oDoQ3.mjs} +2 -2
- package/dist/env-D4Emu-M_.mjs +95 -0
- package/dist/env-DmU2To0C.mjs +73 -0
- package/dist/env-helpers-CyKtOBpj.d.mts +22 -0
- package/dist/env-public-D_6u46fX.d.mts +135 -0
- package/dist/{env-types-QBj-ndax.mjs → env-types-BNPhro-M.mjs} +2 -2
- package/dist/{env-validation-Dea3v3ej.mjs → env-validation-ENpMy6Ez.mjs} +68 -122
- package/dist/{gen-o_w-8yI8.mjs → gen-BKw6qHIg.mjs} +70 -15
- package/dist/{github-cmd-DKcGUNsj.mjs → github-cmd-DJS5Ab-H.mjs} +39 -31
- package/dist/{handler-Cjh8uM3Y.d.mts → handler-D1hLsObx.d.mts} +124 -122
- package/dist/{head-nmvOgFjd.d.mts → head-Do8P4puT.d.mts} +9 -8
- package/dist/{headers-nsHIFixA.mjs → headers-D8QfRX9Y.mjs} +12 -10
- package/dist/inbound-BJ70in1n.d.mts +354 -0
- package/dist/inbound-CNKxb3FY.mjs +694 -0
- package/dist/index.d.mts +61 -34
- package/dist/index.mjs +1048 -321
- package/dist/{init-3rgHKBVi.mjs → init-Dx5cgKqK.mjs} +329 -271
- package/dist/link-D_rm5sRH.mjs +52 -0
- package/dist/{list-CPwFDZ_c.mjs → list-M8XShti7.mjs} +37 -5
- package/dist/{runner-kapo9aPs.mjs → local-d1-BE8KBbMy.mjs} +116 -6
- package/dist/{login-BT3H8PN3.mjs → login-C8-UuLnp.mjs} +17 -15
- package/dist/{logs-Bt313ax7.mjs → logs-DwFU7dMW.mjs} +16 -2
- package/dist/mime-BJD7d_qL.mjs +1216 -0
- package/dist/neon-DHwd2zvC.mjs +54 -0
- package/dist/{node-Da0UcsGA.mjs → node-BkaXcpAc.mjs} +29 -8
- package/dist/operator-cmd-DYWRbWUA.mjs +348 -0
- package/dist/{agents-CtgBYqld.mjs → output-tFQLLj26.mjs} +676 -211
- package/dist/{package-json-Cx1osYo6.mjs → package-json-CPoWX79C.mjs} +1 -1
- package/dist/pages/client.d.mts +43 -41
- package/dist/pages/client.mjs +40 -33
- package/dist/pages/head-client.d.mts +10 -12
- package/dist/pages/head.d.mts +1 -1
- package/dist/pages/index.d.mts +37 -14
- package/dist/pages/index.mjs +5 -5
- package/dist/pages/islands-plugin.d.mts +25 -27
- package/dist/pages/islands-plugin.mjs +6 -4
- package/dist/pages/prefetch.d.mts +6 -7
- package/dist/pages/protocol.d.mts +2 -2
- package/dist/pages/protocol.mjs +2 -1
- package/dist/pages/serialize.d.mts +7 -8
- package/dist/platform-cmd-BEOVv1PN.mjs +123 -0
- package/dist/platform-domain-BszUfiS8.mjs +228 -0
- package/dist/platform-lifecycle-CjSr6xf0.mjs +4450 -0
- package/dist/platform-management-W30iCaTL.mjs +698 -0
- package/dist/platform-recovery-pHHv4ZSg.mjs +99 -0
- package/dist/{plugin-inference-DMeavIJ6.mjs → plugin-inference-BDRfZngg.mjs} +35 -19
- package/dist/prepare-BfJvFUtJ.mjs +14 -0
- package/dist/{prepare-BoKHgMNx.mjs → prepare-CBetXvsN.mjs} +15 -24
- package/dist/{preset-BjyR3lzz.mjs → preset-lAy0B0BQ.mjs} +25 -212
- package/dist/{project-cmd-D_w-4w5B.mjs → project-cmd-DCpk1cDt.mjs} +25 -12
- package/dist/{project-paths-BQd7OmIo.mjs → project-paths-SK8nMHPp.mjs} +3 -1
- package/dist/{project-tsconfig-B-QtXjLQ.mjs → project-tsconfig-Ql2XsSQp.mjs} +2 -2
- package/dist/{protocol-Bnb0LFp3.d.mts → protocol-C-pqYJjE.d.mts} +3 -4
- package/dist/{provision-rShh6MKY.mjs → provision-Blnstcm2.mjs} +78 -45
- package/dist/r2-conditions-D1Wk8i7b.mjs +30 -0
- package/dist/{requests-B8sZxaFM.mjs → requests-Dn8Vheh1.mjs} +5 -3
- package/dist/{resolve-project-BBMtLLV9.mjs → resolve-project--Vxawf7z.mjs} +2 -2
- package/dist/rollback-CtlPXEBi.mjs +166 -0
- package/dist/{rolldown-runtime-DJK8HYOj.mjs → rolldown-runtime-rQ84J-ij.mjs} +1 -1
- package/dist/{route-types-COI2DsZv.mjs → route-types-Da-DpyUp.mjs} +85 -26
- package/dist/routes-stub.d.mts +22 -23
- package/dist/runner-mysql-CgRFl3s6.mjs +61 -0
- package/dist/{runner-pg-CHM76xuC.mjs → runner-pg-DCkWPsWS.mjs} +18 -6
- package/dist/runtime/ai.d.mts +21 -14
- package/dist/runtime/ai.mjs +5 -4
- package/dist/runtime/auth-client-react.d.mts +3 -5
- package/dist/runtime/auth-client-solid.d.mts +3 -5
- package/dist/runtime/auth-client-svelte.d.mts +3 -5
- package/dist/runtime/auth-client-vue.d.mts +3 -5
- package/dist/runtime/auth-client.d.mts +3 -5
- package/dist/runtime/auth.d.mts +1 -1
- package/dist/runtime/better-auth-mysql.d.mts +10 -0
- package/dist/runtime/better-auth-mysql.mjs +49 -0
- package/dist/runtime/better-auth-pg.d.mts +8 -9
- package/dist/runtime/better-auth-pg.mjs +2 -2
- package/dist/runtime/better-auth.d.mts +8 -9
- package/dist/runtime/better-auth.mjs +2 -2
- package/dist/runtime/client-react.d.mts +1 -1
- package/dist/runtime/client-solid.d.mts +1 -1
- package/dist/runtime/client-svelte.d.mts +1 -1
- package/dist/runtime/client-vue.d.mts +1 -1
- package/dist/runtime/client.d.mts +1 -1
- package/dist/runtime/db-mysql.d.mts +2 -0
- package/dist/runtime/db-mysql.mjs +1 -0
- package/dist/runtime/db.d.mts +10 -11
- package/dist/runtime/durable.d.mts +47 -0
- package/dist/runtime/durable.mjs +146 -0
- package/dist/runtime/email/testing.d.mts +112 -0
- package/dist/runtime/email/testing.mjs +283 -0
- package/dist/runtime/email.d.mts +30 -0
- package/dist/runtime/email.mjs +573 -0
- package/dist/runtime/env-helpers.d.mts +2 -2
- package/dist/runtime/env-helpers.mjs +5 -42
- package/dist/runtime/env-public-client.d.mts +10 -11
- package/dist/runtime/env-public-client.mjs +1 -1
- package/dist/runtime/env-public.d.mts +2 -2
- package/dist/runtime/env-public.mjs +104 -49
- package/dist/runtime/env.d.mts +19 -18
- package/dist/runtime/env.mjs +15 -2
- package/dist/runtime/fetch-stream.d.mts +20 -21
- package/dist/runtime/fetch.d.mts +15 -16
- package/dist/runtime/handler.d.mts +1 -1
- package/dist/runtime/isr.d.mts +21 -22
- package/dist/runtime/isr.mjs +26 -8
- package/dist/runtime/kv.d.mts +9 -10
- package/dist/runtime/live-client.d.mts +5 -7
- package/dist/runtime/live-client.mjs +9 -7
- package/dist/runtime/live-server.d.mts +4 -5
- package/dist/runtime/live.d.mts +22 -24
- package/dist/runtime/live.mjs +1 -1
- package/dist/runtime/log.d.mts +16 -17
- package/dist/runtime/migration-handler-mysql.d.mts +4 -0
- package/dist/runtime/migration-handler-mysql.mjs +81 -0
- package/dist/runtime/migration-handler-pg.d.mts +2 -4
- package/dist/runtime/migration-handler.d.mts +5 -6
- package/dist/runtime/migration-handler.mjs +4 -3
- package/dist/runtime/queues.d.mts +3 -4
- package/dist/runtime/queues.mjs +2 -1
- package/dist/runtime/remote/binding-handler.d.mts +10 -12
- package/dist/runtime/remote/binding-handler.mjs +24 -3
- package/dist/runtime/remote/index.d.mts +5 -6
- package/dist/runtime/remote/index.mjs +21 -18
- package/dist/runtime/response.d.mts +10 -11
- package/dist/runtime/sandbox.d.mts +56 -55
- package/dist/runtime/sandbox.mjs +57 -49
- package/dist/runtime/schema-mysql.d.mts +1 -0
- package/dist/runtime/schema-mysql.mjs +2 -0
- package/dist/runtime/seed.d.mts +14 -9
- package/dist/runtime/sse-client.d.mts +6 -7
- package/dist/runtime/sse.d.mts +11 -12
- package/dist/runtime/storage.d.mts +3 -4
- package/dist/runtime/validator.d.mts +1 -1
- package/dist/runtime/ws-server.d.mts +12 -12
- package/dist/runtime/ws-server.mjs +32 -4
- package/dist/runtime/ws.d.mts +19 -21
- package/dist/{scan-DYXkrasO.mjs → scan-BMH4rzlv.mjs} +53 -31
- package/dist/{scan-DEwlM_Xy.mjs → scan-CpK-57ug.mjs} +9 -5
- package/dist/{secret-Dt32J6RI.mjs → secret-BqTxGqki.mjs} +62 -5
- package/dist/{skills-CLjN0uUO.mjs → skills-Q46GZMO-.mjs} +6 -4
- package/dist/{standard-schema-DJ0HW7QP.d.mts → standard-schema-Fo_vCAZh.d.mts} +6 -6
- package/dist/{subcommand-prompt-BzV8iQZo.mjs → subcommand-prompt-WfySCQ7S.mjs} +67 -48
- package/dist/sveltekit.d.mts +12 -11
- package/dist/sveltekit.mjs +1 -1
- package/dist/types-BAp5AEBU.d.mts +79 -0
- package/dist/types-CKWnYgfy.d.mts +1 -0
- package/dist/{validate-Cw_RLeTj.mjs → validate-Bihr8WBi.mjs} +3 -3
- package/dist/wrangler--imS8n0d.mjs +1796 -0
- package/dist/{yarn-pnp-DJn3SAHF.mjs → yarn-pnp-DxSInkzL.mjs} +1 -1
- package/package.json +79 -65
- package/schema.json +35 -3
- package/skills/migrate-vite-cloudflare-to-void/SKILL.md +1 -1
- package/skills/void/SKILL.md +59 -2
- package/skills/void/docs/guide/ai.md +32 -14
- package/skills/void/docs/guide/app-types.md +6 -6
- package/skills/void/docs/guide/auth.md +14 -16
- package/skills/void/docs/guide/database/d1.md +6 -0
- package/skills/void/docs/guide/database/mysql.md +60 -0
- package/skills/void/docs/guide/database/postgresql.md +14 -9
- package/skills/void/docs/guide/database.md +39 -26
- package/skills/void/docs/guide/deployment.md +163 -22
- package/skills/void/docs/guide/durable-state.md +140 -0
- package/skills/void/docs/guide/edge/headers.md +5 -5
- package/skills/void/docs/guide/edge/prerendering.md +2 -0
- package/skills/void/docs/guide/edge/revalidation.md +21 -6
- package/skills/void/docs/guide/edge/rewrites.md +18 -14
- package/skills/void/docs/guide/edge/static-assets.md +23 -8
- package/skills/void/docs/guide/email.md +609 -0
- package/skills/void/docs/guide/env-migration.md +109 -0
- package/skills/void/docs/guide/env-vars.md +70 -248
- package/skills/void/docs/guide/index.md +15 -17
- package/skills/void/docs/guide/jobs.md +8 -5
- package/skills/void/docs/guide/live.md +7 -15
- package/skills/void/docs/guide/pages-routing/actions-and-forms.md +8 -4
- package/skills/void/docs/guide/pages-routing/islands.md +3 -3
- package/skills/void/docs/guide/pages-routing/loaders.md +6 -4
- package/skills/void/docs/guide/pages-routing/overview.md +7 -7
- package/skills/void/docs/guide/platform-administration.md +212 -0
- package/skills/void/docs/guide/platform-development.md +235 -0
- package/skills/void/docs/guide/queues.md +10 -10
- package/skills/void/docs/guide/quickstart.md +46 -67
- package/skills/void/docs/guide/remote-dev.md +8 -6
- package/skills/void/docs/guide/sandboxes.md +33 -16
- package/skills/void/docs/guide/self-hosted-platform.md +553 -0
- package/skills/void/docs/guide/server-routing.md +25 -5
- package/skills/void/docs/guide/sse.md +4 -4
- package/skills/void/docs/guide/ssg.md +5 -3
- package/skills/void/docs/guide/storage.md +2 -2
- package/skills/void/docs/guide/websockets.md +18 -7
- package/skills/void/docs/index.md +3 -3
- package/skills/void/docs/integrations/agents.md +6 -64
- package/skills/void/docs/integrations/cloudflare.md +165 -146
- package/skills/void/docs/integrations/frameworks/analog.md +4 -4
- package/skills/void/docs/integrations/frameworks/astro.md +5 -5
- package/skills/void/docs/integrations/frameworks/nuxt.md +5 -5
- package/skills/void/docs/integrations/frameworks/overview.md +3 -3
- package/skills/void/docs/integrations/frameworks/react-router.md +3 -3
- package/skills/void/docs/integrations/frameworks/sveltekit.md +3 -3
- package/skills/void/docs/integrations/frameworks/tanstack-start.md +2 -2
- package/skills/void/docs/integrations/nodejs-bun-deno.md +11 -4
- package/skills/void/docs/reference/api.md +42 -6
- package/skills/void/docs/reference/cli.md +637 -159
- package/skills/void/docs/reference/config.md +80 -25
- package/skills/void/docs/reference/resource-inference.md +13 -9
- package/skills/void/docs/reference/structure.md +10 -11
- package/AGENT_PROMPT.md +0 -19
- package/dist/cf-access-Bqw81xAf.mjs +0 -22
- package/dist/env-CZy5MorI.mjs +0 -299
- package/dist/env-helpers-z4stu8uc.d.mts +0 -52
- package/dist/env-mask-Dd47NbR6.mjs +0 -90
- package/dist/env-public-BfiLcMBk.d.mts +0 -140
- package/dist/link-CdGHSIy-.mjs +0 -45
- package/dist/mcp-DoM3_nhd.mjs +0 -377
- package/dist/project-paths-GpziKeQQ.d.mts +0 -25
- package/dist/providers-BNKRacMr.d.mts +0 -7
- package/dist/proxy-D-3_D-Gl.mjs +0 -5
- package/dist/rollback-CkvTFXx5.mjs +0 -90
- package/dist/runtime/isr-cache.d.mts +0 -207
- package/dist/runtime/isr-cache.mjs +0 -523
- package/dist/types-lLjNE9Qp.d.mts +0 -51
- package/getting-started-prompt.txt +0 -28
- package/skills/void/command/void.md +0 -7
- package/skills/void/docs/integrations/auth-providers.md +0 -0
- package/skills/void/docs/integrations/payment-processors.md +0 -0
- package/skills/void/docs/node_modules/@iconify/vue/README.md +0 -408
- package/skills/void/docs/node_modules/@iconify/vue/offline/readme.md +0 -5
- package/skills/void/docs/node_modules/@voidzero-dev/vitepress-theme/README.md +0 -103
- package/skills/void/docs/node_modules/oxc-minify/README.md +0 -78
- package/skills/void/docs/node_modules/reka-ui/README.md +0 -80
- package/skills/void/docs/node_modules/vitepress/README.md +0 -28
- package/skills/void/docs/node_modules/vitepress/template/api-examples.md +0 -49
- package/skills/void/docs/node_modules/vitepress/template/index.md +0 -28
- package/skills/void/docs/node_modules/vitepress/template/markdown-examples.md +0 -85
- package/skills/void/docs/node_modules/vitepress-plugin-group-icons/README.md +0 -101
- package/skills/void/docs/node_modules/void/AGENT_PROMPT.md +0 -19
- package/skills/void/docs/node_modules/void/CLAUDE.md +0 -219
- package/skills/void/docs/node_modules/void/README.md +0 -90
- package/skills/void/docs/node_modules/void/node_modules/@clack/prompts/CHANGELOG.md +0 -685
- package/skills/void/docs/node_modules/void/node_modules/@clack/prompts/README.md +0 -396
- package/skills/void/docs/node_modules/void/node_modules/@cloudflare/sandbox/README.md +0 -219
- package/skills/void/docs/node_modules/void/node_modules/@cloudflare/vite-plugin/README.md +0 -37
- package/skills/void/docs/node_modules/void/node_modules/@cloudflare/workers-types/README.md +0 -135
- package/skills/void/docs/node_modules/void/node_modules/@electric-sql/pglite/README.md +0 -189
- package/skills/void/docs/node_modules/void/node_modules/@hono/oauth-providers/CHANGELOG.md +0 -143
- package/skills/void/docs/node_modules/void/node_modules/@hono/oauth-providers/README.md +0 -1272
- package/skills/void/docs/node_modules/void/node_modules/@napi-rs/keyring/README.md +0 -19
- package/skills/void/docs/node_modules/void/node_modules/@types/better-sqlite3/README.md +0 -15
- package/skills/void/docs/node_modules/void/node_modules/@types/node/README.md +0 -15
- package/skills/void/docs/node_modules/void/node_modules/@types/pg/README.md +0 -15
- package/skills/void/docs/node_modules/void/node_modules/@types/proper-lockfile/README.md +0 -51
- package/skills/void/docs/node_modules/void/node_modules/@typescript/native-preview/README.md +0 -22
- package/skills/void/docs/node_modules/void/node_modules/@typescript/native-preview/vendor/vscode-jsonrpc/README.md +0 -69
- package/skills/void/docs/node_modules/void/node_modules/@void/md/README.md +0 -153
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/@shikijs/engine-javascript/README.md +0 -9
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/@shikijs/transformers/README.md +0 -9
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/@types/node/README.md +0 -15
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/gray-matter/CHANGELOG.md +0 -24
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/gray-matter/README.md +0 -565
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/markdown-exit/README.md +0 -127
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/markdown-it-anchor/README.md +0 -600
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/markdown-it-attrs/README.md +0 -386
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/markdown-it-container/README.md +0 -95
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/markdown-it-emoji/README.md +0 -101
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/markdown-it-footnote/README.md +0 -135
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/pathslash/README.md +0 -64
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/shiki/README.md +0 -15
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/tinyglobby/README.md +0 -25
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/AGENTS.md +0 -16
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/README.md +0 -220
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/config/build.md +0 -21
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/config/check.md +0 -35
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/config/create.md +0 -70
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/config/fmt.md +0 -20
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/config/index.md +0 -35
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/config/lint.md +0 -26
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/config/pack.md +0 -17
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/config/run.md +0 -364
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/config/staged.md +0 -15
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/config/test.md +0 -18
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/automatic-data-tracking.md +0 -145
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/build.md +0 -40
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/cache.md +0 -107
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/check.md +0 -60
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/ci.md +0 -62
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/commit-hooks.md +0 -60
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/create.md +0 -341
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/dev.md +0 -24
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/docker.md +0 -175
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/env.md +0 -167
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/fmt.md +0 -41
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/github-actions-cache.md +0 -165
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/ide-integration.md +0 -101
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/implode.md +0 -23
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/index.md +0 -134
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/install.md +0 -199
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/lint.md +0 -50
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/migrate-rules.md +0 -347
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/migrate.md +0 -197
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/monorepo.md +0 -176
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/pack.md +0 -69
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/run.md +0 -356
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/test.md +0 -35
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/troubleshooting.md +0 -108
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/upgrade.md +0 -101
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/vpx.md +0 -66
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/guide/why.md +0 -39
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/index.md +0 -12
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/docs/team.md +0 -35
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/templates/generator/README.md +0 -35
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite-plus/templates/monorepo/README.md +0 -29
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vue/README.md +0 -58
- package/skills/void/docs/node_modules/void/node_modules/arktype/README.md +0 -165
- package/skills/void/docs/node_modules/void/node_modules/better-auth/LICENSE.md +0 -20
- package/skills/void/docs/node_modules/void/node_modules/better-auth/README.md +0 -32
- package/skills/void/docs/node_modules/void/node_modules/better-sqlite3/README.md +0 -99
- package/skills/void/docs/node_modules/void/node_modules/blake3-jit/README.md +0 -108
- package/skills/void/docs/node_modules/void/node_modules/drizzle-arktype/README.md +0 -51
- package/skills/void/docs/node_modules/void/node_modules/drizzle-kit/README.md +0 -79
- package/skills/void/docs/node_modules/void/node_modules/drizzle-orm/README.md +0 -44
- package/skills/void/docs/node_modules/void/node_modules/drizzle-valibot/README.md +0 -51
- package/skills/void/docs/node_modules/void/node_modules/drizzle-zod/README.md +0 -65
- package/skills/void/docs/node_modules/void/node_modules/es-module-lexer/README.md +0 -403
- package/skills/void/docs/node_modules/void/node_modules/estree-walker/README.md +0 -48
- package/skills/void/docs/node_modules/void/node_modules/hono/README.md +0 -85
- package/skills/void/docs/node_modules/void/node_modules/ignore/README.md +0 -452
- package/skills/void/docs/node_modules/void/node_modules/jsonc-parser/CHANGELOG.md +0 -76
- package/skills/void/docs/node_modules/void/node_modules/jsonc-parser/LICENSE.md +0 -21
- package/skills/void/docs/node_modules/void/node_modules/jsonc-parser/README.md +0 -364
- package/skills/void/docs/node_modules/void/node_modules/jsonc-parser/SECURITY.md +0 -41
- package/skills/void/docs/node_modules/void/node_modules/magic-string/README.md +0 -325
- package/skills/void/docs/node_modules/void/node_modules/ofetch/README.md +0 -398
- package/skills/void/docs/node_modules/void/node_modules/pathslash/README.md +0 -64
- package/skills/void/docs/node_modules/void/node_modules/pg/README.md +0 -96
- package/skills/void/docs/node_modules/void/node_modules/pglite-server/README.md +0 -135
- package/skills/void/docs/node_modules/void/node_modules/picocolors/README.md +0 -21
- package/skills/void/docs/node_modules/void/node_modules/proper-lockfile/CHANGELOG.md +0 -108
- package/skills/void/docs/node_modules/void/node_modules/proper-lockfile/README.md +0 -183
- package/skills/void/docs/node_modules/void/node_modules/tinyglobby/README.md +0 -25
- package/skills/void/docs/node_modules/void/node_modules/valibot/LICENSE.md +0 -9
- package/skills/void/docs/node_modules/void/node_modules/valibot/README.md +0 -94
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/AGENTS.md +0 -16
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/README.md +0 -220
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/config/build.md +0 -21
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/config/check.md +0 -35
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/config/create.md +0 -70
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/config/fmt.md +0 -20
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/config/index.md +0 -35
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/config/lint.md +0 -26
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/config/pack.md +0 -17
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/config/run.md +0 -364
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/config/staged.md +0 -15
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/config/test.md +0 -18
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/automatic-data-tracking.md +0 -145
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/build.md +0 -40
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/cache.md +0 -107
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/check.md +0 -60
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/ci.md +0 -62
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/commit-hooks.md +0 -60
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/create.md +0 -341
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/dev.md +0 -24
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/docker.md +0 -175
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/env.md +0 -167
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/fmt.md +0 -41
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/github-actions-cache.md +0 -165
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/ide-integration.md +0 -101
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/implode.md +0 -23
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/index.md +0 -134
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/install.md +0 -199
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/lint.md +0 -50
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/migrate-rules.md +0 -347
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/migrate.md +0 -197
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/monorepo.md +0 -176
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/pack.md +0 -69
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/run.md +0 -356
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/test.md +0 -35
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/troubleshooting.md +0 -108
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/upgrade.md +0 -101
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/vpx.md +0 -66
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/guide/why.md +0 -39
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/index.md +0 -12
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/docs/team.md +0 -35
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/templates/generator/README.md +0 -35
- package/skills/void/docs/node_modules/void/node_modules/vite-plus/templates/monorepo/README.md +0 -29
- package/skills/void/docs/node_modules/void/node_modules/wrangler/README.md +0 -63
- package/skills/void/docs/node_modules/void/node_modules/zod/README.md +0 -191
- package/skills/void/docs/node_modules/void/skills/migrate-vite-cloudflare-to-void/SKILL.md +0 -175
- package/skills/void/docs/node_modules/void/skills/void/SKILL.md +0 -76
- package/skills/void/docs/node_modules/void/skills/void/command/void.md +0 -7
- package/skills/void/docs/node_modules/void/test/e2e/README.md +0 -85
package/dist/index.mjs
CHANGED
|
@@ -1,32 +1,38 @@
|
|
|
1
|
-
import { r as __toESM } from "./rolldown-runtime-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { i as resolveProjectPaths, n as readProjectPaths, t as assertNoRootSourceConventionConflicts } from "./project-paths-
|
|
6
|
-
import { a as scanQueuesSync, c as loadVoidAuthConfig, i as scanWebSocketRoutesSync, n as scanRoutePatternsSync, o as scanJobsSync, r as scanRoutes, s as findVoidAuthConfig, t as scanMiddlewareSync } from "./scan-
|
|
7
|
-
import { b as
|
|
8
|
-
import {
|
|
9
|
-
import { c as getDatabaseDialect, f as readConfig, l as isNodeTarget, p as resolveBindingNames } from "./config-
|
|
10
|
-
import { a as inferBindingsFromSource, i as inferProjectBindings, n as FRAMEWORK_SCAN_DIRS, o as walk, r as detectFramework, t as DEFAULT_SCAN_DIRS } from "./plugin-inference-DMeavIJ6.mjs";
|
|
11
|
-
import { a as validateSsrEntries, c as isIdentifier, l as isLiteral, n as SSR_SERVER_ENTRY_RELATIVE_PATHS, o as validateSsrEntry, t as SSR_CLIENT_ENTRY_RELATIVE_PATHS, u as isMemberExpression } from "./entry-D7yy4xVH.mjs";
|
|
1
|
+
import { r as __toESM } from "./rolldown-runtime-rQ84J-ij.mjs";
|
|
2
|
+
import { c as relative, l as resolve, n as dirname, o as join } from "./dist-BrsS7cai.mjs";
|
|
3
|
+
import { st as require_picocolors } from "./output-tFQLLj26.mjs";
|
|
4
|
+
import { D as resolveAssetRoutingPolicy, E as hasDocumentRoutes, T as hasApiRoutes, _ as scanDurableObjectModules, c as resolveDistDir, d as generateQueueResolverSource, f as prerenderPages, g as hasRevalidate, h as collectRevalidate, l as resolveWorkerDirName, m as collectPages, p as prerenderPagesNode, v as SEND_EMAIL_BINDING } from "./deploy-CcDoeBIf.mjs";
|
|
5
|
+
import { i as resolveProjectPaths, n as readProjectPaths, t as assertNoRootSourceConventionConflicts } from "./project-paths-SK8nMHPp.mjs";
|
|
6
|
+
import { a as scanQueuesSync, c as loadVoidAuthConfig, i as scanWebSocketRoutesSync, n as scanRoutePatternsSync, o as scanJobsSync, r as scanRoutes, s as findVoidAuthConfig, t as scanMiddlewareSync } from "./scan-BMH4rzlv.mjs";
|
|
7
|
+
import { a as getApiUrl, b as readDeploymentPlatform, c as getToken, o as getProxyUrl, u as isStagingMode, x as readProjectConfig } from "./auth-W9WII-mN.mjs";
|
|
8
|
+
import { C as readWranglerWebSocketTombstones, D as syncWranglerWebSockets, E as syncWranglerDurableObjects, M as isSandboxEnabled, P as resolveSandboxConfig, T as syncWranglerBindings, a as LIVE_MIGRATION_TAG, d as ensureWranglerNodejsAlsFlag, g as readExistingLiveBindingConfig, h as normalizeWranglerCompatibilityFlags, j as SANDBOX_MIGRATION_TAG, l as ensureWranglerCompat, m as nextDurableObjectMigrationTag, p as hasDurableObjectSqliteMigration, u as ensureWranglerCompatibilityDate, w as resolveLiveBindingConfig, y as readWranglerCompat } from "./wrangler--imS8n0d.mjs";
|
|
9
|
+
import { c as getDatabaseDialect, f as readConfig, l as isNodeTarget, p as resolveBindingNames } from "./config-BQFq7QvD.mjs";
|
|
12
10
|
import { i as voidWarn, n as voidError, r as voidLog, t as setShowTimestamp } from "./log-ChfPKsVd.mjs";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import { t as
|
|
16
|
-
import { t as
|
|
17
|
-
import { n as
|
|
18
|
-
import {
|
|
19
|
-
import { i as
|
|
20
|
-
import {
|
|
21
|
-
import { n as
|
|
11
|
+
import { n as lintDuplicateSources, r as mergeRoutingRules, t as lintDestinationSplats } from "./headers-D8QfRX9Y.mjs";
|
|
12
|
+
import { n as ensureProjectTsconfig, r as writeFileIfChanged } from "./project-tsconfig-Ql2XsSQp.mjs";
|
|
13
|
+
import { a as inferBindingsFromSource, i as inferProjectBindings, n as FRAMEWORK_SCAN_DIRS, o as walk, r as detectFramework, t as DEFAULT_SCAN_DIRS } from "./plugin-inference-BDRfZngg.mjs";
|
|
14
|
+
import { a as validateSsrEntries, c as isIdentifier, l as isLiteral, n as SSR_SERVER_ENTRY_RELATIVE_PATHS, o as validateSsrEntry, t as SSR_CLIENT_ENTRY_RELATIVE_PATHS, u as isMemberExpression } from "./entry-DU3oDoQ3.mjs";
|
|
15
|
+
import { n as writeLocalD1PersistState, t as resolveLocalD1Target } from "./local-d1-BE8KBbMy.mjs";
|
|
16
|
+
import { n as parseDotenvFile } from "./dotenv-VQxupEUv.mjs";
|
|
17
|
+
import { i as generateVoidAuthDrizzleSchema, n as generateQueueTypes, o as DRIZZLE_OPERATORS, r as generateVoidAuthDatabaseModule, s as generateDbDts, t as generateRouteTypes } from "./route-types-Da-DpyUp.mjs";
|
|
18
|
+
import { t as discoverSchema } from "./discover-xvfrgJeo.mjs";
|
|
19
|
+
import { _ as parseCapturedMessage, a as DEV_INBOX_ENV_VAR, c as DEV_INBOX_TOKEN_ENV_VAR, f as clearDevBuffer, g as listDevMessages, l as DEV_INBOX_TOKEN_HEADER, m as findDevMessage, n as DEV_INBOX_ACK_VALUE, o as DEV_INBOX_MAX_CAPTURE_BYTES, s as DEV_INBOX_PREFIX, t as DEV_INBOX_ACK_HEADER, u as DEV_INBOX_TOKEN_QUERY, v as pushToDevBuffer, y as registerEmailSink } from "./dev-inbox-DkgRWLkW.mjs";
|
|
20
|
+
import { t as MagicString } from "./dist-BR1quN_w.mjs";
|
|
21
|
+
import { n as findEnvFileForPaths, r as generateEnvTypes, t as findEnvFile } from "./env-types-BNPhro-M.mjs";
|
|
22
|
+
import { h as loadUserEnvFile } from "./env-validation-ENpMy6Ez.mjs";
|
|
23
|
+
import { a as loadLocalEnv, o as resolveRemoteMode, r as findLegacyEnvFiles, s as stripInternalEnvKeys, t as CLIENT_ENV_PREFIX$2 } from "./env-D4Emu-M_.mjs";
|
|
24
|
+
import { i as resolveLayoutIds, o as isRouteEnabledForEnvironment } from "./scan-CpK-57ug.mjs";
|
|
25
|
+
import { a as scanEmailHandlersSync, r as hasEmailHandlers } from "./email-Ce6SQq-i.mjs";
|
|
22
26
|
import { n as INTERNAL_BINDING_PREFIXES, t as INTERNAL_BINDING_EXACT_NAMES } from "./env-raw-Cx8ElDdj.mjs";
|
|
23
27
|
import { n as defer } from "./defer-YsYDUoii.mjs";
|
|
24
28
|
import { VoidAssetRewriteError, basicAuth, defineHandler, defineHead, defineMiddleware, defineQueue, defineRender, defineScheduled } from "./runtime/handler.mjs";
|
|
25
|
-
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, readdirSync, rmSync, writeFileSync, writeSync } from "node:fs";
|
|
29
|
+
import { chmodSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync, writeSync } from "node:fs";
|
|
26
30
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
27
31
|
import { cloudflare } from "@cloudflare/vite-plugin";
|
|
28
|
-
import {
|
|
32
|
+
import { appendSqliteClassMigration } from "@void/deploy-core";
|
|
33
|
+
import { timingSafeEqual } from "node:crypto";
|
|
29
34
|
import { homedir } from "node:os";
|
|
35
|
+
import { normalizePath, parseSync } from "vite";
|
|
30
36
|
import { init, parse } from "es-module-lexer";
|
|
31
37
|
//#region src/pages/dev-css-assets.ts
|
|
32
38
|
var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
|
|
@@ -272,7 +278,7 @@ function pagesDevCssAssetsPlugin(root, token) {
|
|
|
272
278
|
resolveId(id) {
|
|
273
279
|
if (id !== "virtual:void-pages-dev-assets") return;
|
|
274
280
|
if (this.environment?.name === "client") throw new Error(`${DEV_CSS_ASSET_MODULE_ID} is server-only and cannot be imported by client code.`);
|
|
275
|
-
return "\
|
|
281
|
+
return "\0" + DEV_CSS_ASSET_MODULE_ID;
|
|
276
282
|
},
|
|
277
283
|
load(id) {
|
|
278
284
|
if (id !== "\0virtual:void-pages-dev-assets") return;
|
|
@@ -412,8 +418,8 @@ export async function getVoidPagesDevCss(request, env, payload) {
|
|
|
412
418
|
}
|
|
413
419
|
const edges = [];
|
|
414
420
|
for (const item of imports) {
|
|
415
|
-
if (item.
|
|
416
|
-
const resolved = await this.resolve(item.
|
|
421
|
+
if (item.type !== "static" && item.type !== "reexport-star" || !item.specifier) continue;
|
|
422
|
+
const resolved = await this.resolve(item.specifier, id, { skipSelf: true });
|
|
417
423
|
if (resolved?.id) edges.push(normalizeDevCssUrl(resolved.id, root));
|
|
418
424
|
}
|
|
419
425
|
edgeStore.set(id, edges);
|
|
@@ -505,7 +511,7 @@ function devTriggersHintPlugin(root, options) {
|
|
|
505
511
|
if (queues.length > 0) summary.push(`${queues.length} queue${queues.length === 1 ? "" : "s"}`);
|
|
506
512
|
console.log();
|
|
507
513
|
voidLog(`Detected ${summary.join(" and ")}. Trigger locally:`);
|
|
508
|
-
const configuredProxyToken = parseDotenvFile(join(root, ".
|
|
514
|
+
const configuredProxyToken = parseDotenvFile(join(root, ".env"), { expand: false }).__VOID_PROXY_TOKEN;
|
|
509
515
|
const authHeader = configuredProxyToken ? `x-void-internal: ${configuredProxyToken}` : `x-void-dev-trigger: ${devTriggerToken}`;
|
|
510
516
|
if (jobs.length > 0) {
|
|
511
517
|
const sample = jobs[0].crons[0];
|
|
@@ -525,7 +531,9 @@ const drizzleD1Resolved = fileURLToPath(import.meta.resolve("drizzle-orm/d1"));
|
|
|
525
531
|
const drizzleOrmResolved = fileURLToPath(import.meta.resolve("drizzle-orm"));
|
|
526
532
|
const envModuleResolved = fileURLToPath(import.meta.resolve("#self/_env"));
|
|
527
533
|
const drizzleNodePgResolved = fileURLToPath(import.meta.resolve("drizzle-orm/node-postgres"));
|
|
534
|
+
const drizzleMysql2Resolved = fileURLToPath(import.meta.resolve("drizzle-orm/mysql2"));
|
|
528
535
|
const pgResolved = fileURLToPath(import.meta.resolve("pg"));
|
|
536
|
+
const mysql2Resolved = fileURLToPath(import.meta.resolve("mysql2"));
|
|
529
537
|
const VIRTUAL_DB_ID = "\0virtual:void-db";
|
|
530
538
|
const VIRTUAL_SCHEMA_DB_ID = "\0virtual:void-db-schema";
|
|
531
539
|
/**
|
|
@@ -589,34 +597,72 @@ export function createDb() {
|
|
|
589
597
|
}
|
|
590
598
|
`;
|
|
591
599
|
const schemaImport = schema ? `import * as schema from ${JSON.stringify(schema.path)};` : "";
|
|
592
|
-
const drizzleConfig = schema ? ", { schema }" : "";
|
|
600
|
+
const drizzleConfig = schema ? dialect === "mysql" ? ", { schema, mode: \"default\" }" : ", { schema }" : "";
|
|
601
|
+
if (dialect === "mysql") return `
|
|
602
|
+
import { drizzle } from ${JSON.stringify(drizzleMysql2Resolved)};
|
|
603
|
+
import { createPool } from ${JSON.stringify(mysql2Resolved)};
|
|
604
|
+
import { getRuntimeBinding, getRuntimeRequestResource } from ${JSON.stringify(envModuleResolved)};
|
|
605
|
+
${schemaImport}
|
|
606
|
+
export { ${DRIZZLE_OPERATORS} } from ${JSON.stringify(drizzleOrmResolved)};
|
|
607
|
+
|
|
608
|
+
const _requestResourceKey = {};
|
|
609
|
+
|
|
610
|
+
function getConnectionString() {
|
|
611
|
+
const url = getRuntimeBinding("DATABASE_URL");
|
|
612
|
+
if (url) return url;
|
|
613
|
+
const hd = getRuntimeBinding("HYPERDRIVE");
|
|
614
|
+
if (hd?.connectionString) return hd.connectionString;
|
|
615
|
+
throw new Error("db: MySQL is not configured. Add DATABASE_URL to .env for local dev, or configure Hyperdrive for production.");
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
function getInstance() {
|
|
619
|
+
return getRuntimeRequestResource(_requestResourceKey, () => {
|
|
620
|
+
const pool = createPool({
|
|
621
|
+
uri: getConnectionString(),
|
|
622
|
+
connectionLimit: 1,
|
|
623
|
+
maxIdle: 1,
|
|
624
|
+
idleTimeout: 1000,
|
|
625
|
+
});
|
|
626
|
+
return drizzle(pool${drizzleConfig});
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
export const db = new Proxy({}, {
|
|
631
|
+
get(_, prop) {
|
|
632
|
+
return Reflect.get(getInstance(), prop);
|
|
633
|
+
},
|
|
634
|
+
});
|
|
635
|
+
|
|
636
|
+
export function createDb(connectionString) {
|
|
637
|
+
return drizzle(connectionString${drizzleConfig});
|
|
638
|
+
}
|
|
639
|
+
`;
|
|
593
640
|
if (dialect === "postgresql") return `
|
|
594
641
|
import { drizzle } from ${JSON.stringify(drizzleNodePgResolved)};
|
|
595
642
|
import pg from "pg";
|
|
596
|
-
import { getRuntimeBinding } from ${JSON.stringify(envModuleResolved)};
|
|
643
|
+
import { getRuntimeBinding, getRuntimeRequestResource } from ${JSON.stringify(envModuleResolved)};
|
|
597
644
|
${schemaImport}
|
|
598
645
|
export { ${DRIZZLE_OPERATORS} } from ${JSON.stringify(drizzleOrmResolved)};
|
|
599
646
|
|
|
600
|
-
|
|
647
|
+
const _requestResourceKey = {};
|
|
601
648
|
|
|
602
649
|
function getConnectionString() {
|
|
603
650
|
const url = getRuntimeBinding("DATABASE_URL");
|
|
604
651
|
if (url) return url;
|
|
605
652
|
const hd = getRuntimeBinding("HYPERDRIVE");
|
|
606
653
|
if (hd?.connectionString) return hd.connectionString;
|
|
607
|
-
throw new Error("db: PostgreSQL is not configured. Add DATABASE_URL to .env
|
|
654
|
+
throw new Error("db: PostgreSQL is not configured. Add DATABASE_URL to .env for local dev, or configure Hyperdrive for production.");
|
|
608
655
|
}
|
|
609
656
|
|
|
610
657
|
function getInstance() {
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
return _prodInstance;
|
|
658
|
+
return getRuntimeRequestResource(_requestResourceKey, () => {
|
|
659
|
+
const pool = new pg.Pool({
|
|
660
|
+
connectionString: getConnectionString(),
|
|
661
|
+
max: 1,
|
|
662
|
+
idleTimeoutMillis: 1000,
|
|
663
|
+
});
|
|
664
|
+
return drizzle(pool${drizzleConfig});
|
|
665
|
+
});
|
|
620
666
|
}
|
|
621
667
|
|
|
622
668
|
export const db = new Proxy({}, {
|
|
@@ -655,7 +701,7 @@ export function createDb(d1) {
|
|
|
655
701
|
const migrationsDir = paths.migrationsDir;
|
|
656
702
|
if (!(existsSync(migrationsDir) && readdirSync(migrationsDir).some((f) => f.endsWith(".sql")))) {
|
|
657
703
|
if (dialect === "sqlite") {
|
|
658
|
-
const { getApplicationTables, getMiniflareDatabasePath } = await import("./
|
|
704
|
+
const { getApplicationTables, getMiniflareDatabasePath } = await import("./local-d1-BE8KBbMy.mjs").then((n) => n.i);
|
|
659
705
|
if ((await getApplicationTables(getMiniflareDatabasePath(options.localD1PersistRoot ?? join(root, ".void"), options.localD1DatabaseId ?? "local")).catch(() => [])).length > 0) return;
|
|
660
706
|
}
|
|
661
707
|
voidWarn(`Schema found but no migrations in ${paths.sourceRelative("db/migrations")}/.\n \`void db push\` syncs the schema to your local DB without creating migration files.
|
|
@@ -672,6 +718,264 @@ export function createDb(d1) {
|
|
|
672
718
|
};
|
|
673
719
|
}
|
|
674
720
|
//#endregion
|
|
721
|
+
//#region src/plugin-email-dev-inbox.ts
|
|
722
|
+
const INBOX_PREFIX = DEV_INBOX_PREFIX;
|
|
723
|
+
const SECURITY_HEADERS = {
|
|
724
|
+
"Cache-Control": "no-store",
|
|
725
|
+
"X-Content-Type-Options": "nosniff",
|
|
726
|
+
"X-Frame-Options": "DENY",
|
|
727
|
+
"Referrer-Policy": "no-referrer",
|
|
728
|
+
"Content-Security-Policy": "default-src 'none'; style-src 'unsafe-inline'; frame-src data:; img-src data:; connect-src 'none'"
|
|
729
|
+
};
|
|
730
|
+
function emailDevInboxPlugin(options) {
|
|
731
|
+
const { devTriggerToken } = options;
|
|
732
|
+
let devMode = false;
|
|
733
|
+
let unregister;
|
|
734
|
+
/** `href` for an inbox path that keeps the browser session authorized. */
|
|
735
|
+
const inboxHref = (path) => `${INBOX_PREFIX}${path}?${DEV_INBOX_TOKEN_QUERY}=${encodeURIComponent(devTriggerToken)}`;
|
|
736
|
+
return {
|
|
737
|
+
name: "void:email-dev-inbox",
|
|
738
|
+
apply: "serve",
|
|
739
|
+
config() {
|
|
740
|
+
devMode = true;
|
|
741
|
+
},
|
|
742
|
+
buildStart() {
|
|
743
|
+
if (!devMode || unregister) return;
|
|
744
|
+
unregister = registerEmailSink((m) => pushToDevBuffer(m));
|
|
745
|
+
},
|
|
746
|
+
buildEnd() {
|
|
747
|
+
if (unregister) {
|
|
748
|
+
unregister();
|
|
749
|
+
unregister = void 0;
|
|
750
|
+
}
|
|
751
|
+
},
|
|
752
|
+
configureServer(server) {
|
|
753
|
+
if (server.config.command !== "serve") return;
|
|
754
|
+
const printInboxUrl = () => {
|
|
755
|
+
const address = server.httpServer?.address();
|
|
756
|
+
const port = typeof address === "object" && address ? address.port : null;
|
|
757
|
+
if (port == null) return;
|
|
758
|
+
voidLog(`Email inbox: http://localhost:${port}${inboxHref("")}`);
|
|
759
|
+
};
|
|
760
|
+
if (server.httpServer) server.httpServer.once("listening", () => setTimeout(printInboxUrl, 100));
|
|
761
|
+
server.middlewares.use(INBOX_PREFIX, (req, res) => {
|
|
762
|
+
if (server.config.command !== "serve") {
|
|
763
|
+
res.writeHead(404, SECURITY_HEADERS);
|
|
764
|
+
res.end();
|
|
765
|
+
return;
|
|
766
|
+
}
|
|
767
|
+
const url = new URL(req.url ?? "/", "http://localhost");
|
|
768
|
+
const path = url.pathname;
|
|
769
|
+
if (!isAuthorized(req.headers["x-void-dev-trigger"], url, devTriggerToken)) {
|
|
770
|
+
res.writeHead(401, {
|
|
771
|
+
...SECURITY_HEADERS,
|
|
772
|
+
"Content-Type": "text/plain; charset=utf-8"
|
|
773
|
+
});
|
|
774
|
+
res.end(`Unauthorized: the void dev inbox requires the dev-trigger token — send it as the ${DEV_INBOX_TOKEN_HEADER} header or the ?${DEV_INBOX_TOKEN_QUERY}= query (printed as the inbox URL when void dev starts; stored in .void/dev-trigger-token).`);
|
|
775
|
+
return;
|
|
776
|
+
}
|
|
777
|
+
if (req.method === "POST" && path === "/_capture") {
|
|
778
|
+
handleCapture(req, res);
|
|
779
|
+
return;
|
|
780
|
+
}
|
|
781
|
+
if (req.method === "DELETE" && path === "/") {
|
|
782
|
+
clearDevBuffer();
|
|
783
|
+
res.writeHead(204, SECURITY_HEADERS);
|
|
784
|
+
res.end();
|
|
785
|
+
return;
|
|
786
|
+
}
|
|
787
|
+
if (req.method !== "GET") {
|
|
788
|
+
res.writeHead(405, SECURITY_HEADERS);
|
|
789
|
+
res.end();
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
if (path === "/" || path === "") {
|
|
793
|
+
res.writeHead(200, {
|
|
794
|
+
...SECURITY_HEADERS,
|
|
795
|
+
"Content-Type": "text/html; charset=utf-8"
|
|
796
|
+
});
|
|
797
|
+
res.end(renderListHtml(listDevMessages(), inboxHref));
|
|
798
|
+
return;
|
|
799
|
+
}
|
|
800
|
+
const match = path.match(/^\/([^/]+)(\/raw)?$/);
|
|
801
|
+
if (!match) {
|
|
802
|
+
res.writeHead(404, SECURITY_HEADERS);
|
|
803
|
+
res.end();
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
const id = match[1];
|
|
807
|
+
const wantsRaw = Boolean(match[2]);
|
|
808
|
+
const message = findDevMessage(id);
|
|
809
|
+
if (!message) {
|
|
810
|
+
res.writeHead(404, {
|
|
811
|
+
...SECURITY_HEADERS,
|
|
812
|
+
"Content-Type": "text/plain"
|
|
813
|
+
});
|
|
814
|
+
res.end("Email not found.");
|
|
815
|
+
return;
|
|
816
|
+
}
|
|
817
|
+
if (wantsRaw) {
|
|
818
|
+
const safeId = id.replace(/["\r\n]/g, "");
|
|
819
|
+
res.writeHead(200, {
|
|
820
|
+
...SECURITY_HEADERS,
|
|
821
|
+
"Content-Type": "message/rfc822",
|
|
822
|
+
"Content-Disposition": `attachment; filename="${safeId}.eml"`
|
|
823
|
+
});
|
|
824
|
+
res.end(Buffer.from(message.raw));
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
res.writeHead(200, {
|
|
828
|
+
...SECURITY_HEADERS,
|
|
829
|
+
"Content-Type": "text/html; charset=utf-8"
|
|
830
|
+
});
|
|
831
|
+
res.end(renderDetailHtml(message, inboxHref));
|
|
832
|
+
});
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
}
|
|
836
|
+
/**
|
|
837
|
+
* Constant-time check of the presented token — header first (worker, curl),
|
|
838
|
+
* then the query (browser). Both are compared against the one project token.
|
|
839
|
+
*/
|
|
840
|
+
function isAuthorized(headerValue, url, expected) {
|
|
841
|
+
const presented = typeof headerValue === "string" ? headerValue : url.searchParams.get(DEV_INBOX_TOKEN_QUERY);
|
|
842
|
+
if (typeof presented !== "string") return false;
|
|
843
|
+
const a = Buffer.from(presented);
|
|
844
|
+
const b = Buffer.from(expected);
|
|
845
|
+
return a.byteLength === b.byteLength && timingSafeEqual(a, b);
|
|
846
|
+
}
|
|
847
|
+
/**
|
|
848
|
+
* `POST /__void/inbox/_capture` — the worker's dev-inbox hop.
|
|
849
|
+
*
|
|
850
|
+
* Fails with a status the worker can distinguish, and only a success carries
|
|
851
|
+
* the ack header, so the worker never mistakes an ordinary asset 200 for a
|
|
852
|
+
* capture. Never throws: an exception here would surface as a dev-server 500
|
|
853
|
+
* in the middle of the user's `sendEmail`.
|
|
854
|
+
*/
|
|
855
|
+
async function handleCapture(req, res) {
|
|
856
|
+
try {
|
|
857
|
+
if (!String(req.headers["content-type"] ?? "").includes("application/json")) {
|
|
858
|
+
res.writeHead(415, SECURITY_HEADERS);
|
|
859
|
+
res.end();
|
|
860
|
+
return;
|
|
861
|
+
}
|
|
862
|
+
const chunks = [];
|
|
863
|
+
let size = 0;
|
|
864
|
+
for await (const chunk of req) {
|
|
865
|
+
const buf = typeof chunk === "string" ? Buffer.from(chunk) : Buffer.from(chunk);
|
|
866
|
+
size += buf.byteLength;
|
|
867
|
+
if (size > DEV_INBOX_MAX_CAPTURE_BYTES) {
|
|
868
|
+
res.writeHead(413, SECURITY_HEADERS);
|
|
869
|
+
res.end();
|
|
870
|
+
return;
|
|
871
|
+
}
|
|
872
|
+
chunks.push(buf);
|
|
873
|
+
}
|
|
874
|
+
let parsed;
|
|
875
|
+
try {
|
|
876
|
+
parsed = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
877
|
+
} catch {
|
|
878
|
+
res.writeHead(400, SECURITY_HEADERS);
|
|
879
|
+
res.end();
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
const message = parseCapturedMessage(parsed);
|
|
883
|
+
if (!message) {
|
|
884
|
+
res.writeHead(400, SECURITY_HEADERS);
|
|
885
|
+
res.end();
|
|
886
|
+
return;
|
|
887
|
+
}
|
|
888
|
+
pushToDevBuffer(message);
|
|
889
|
+
res.writeHead(200, {
|
|
890
|
+
...SECURITY_HEADERS,
|
|
891
|
+
[DEV_INBOX_ACK_HEADER]: DEV_INBOX_ACK_VALUE,
|
|
892
|
+
"Content-Type": "application/json"
|
|
893
|
+
});
|
|
894
|
+
res.end(JSON.stringify({
|
|
895
|
+
ok: true,
|
|
896
|
+
id: message.id
|
|
897
|
+
}));
|
|
898
|
+
} catch {
|
|
899
|
+
res.writeHead(500, SECURITY_HEADERS);
|
|
900
|
+
res.end();
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
function escapeHtml(s) {
|
|
904
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
905
|
+
}
|
|
906
|
+
function formatAddress(a) {
|
|
907
|
+
return a.name ? `${a.name} <${a.email}>` : a.email;
|
|
908
|
+
}
|
|
909
|
+
function formatTime(ts) {
|
|
910
|
+
return new Date(ts).toLocaleString();
|
|
911
|
+
}
|
|
912
|
+
const STYLE = `
|
|
913
|
+
:root { color-scheme: light dark; }
|
|
914
|
+
body { font: 14px/1.5 ui-sans-serif, system-ui, sans-serif; margin: 0; padding: 24px; max-width: 1024px; margin: 0 auto; }
|
|
915
|
+
h1 { font-size: 18px; margin: 0 0 16px; }
|
|
916
|
+
h2 { font-size: 14px; margin: 24px 0 8px; text-transform: uppercase; letter-spacing: 0.05em; opacity: 0.7; }
|
|
917
|
+
table { border-collapse: collapse; width: 100%; }
|
|
918
|
+
th, td { text-align: left; padding: 8px 12px; border-bottom: 1px solid color-mix(in srgb, currentColor 15%, transparent); vertical-align: top; }
|
|
919
|
+
th { font-weight: 600; opacity: 0.7; font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em; }
|
|
920
|
+
a { color: #5b8def; text-decoration: none; }
|
|
921
|
+
a:hover { text-decoration: underline; }
|
|
922
|
+
.meta { font-size: 12px; opacity: 0.7; }
|
|
923
|
+
.empty { padding: 48px; text-align: center; opacity: 0.6; }
|
|
924
|
+
.row { display: flex; gap: 12px; align-items: baseline; }
|
|
925
|
+
.row .subject { font-weight: 600; }
|
|
926
|
+
iframe { width: 100%; min-height: 480px; border: 1px solid color-mix(in srgb, currentColor 15%, transparent); border-radius: 8px; background: white; }
|
|
927
|
+
.actions { display: flex; gap: 12px; margin-bottom: 16px; }
|
|
928
|
+
.button { display: inline-block; padding: 6px 12px; border: 1px solid color-mix(in srgb, currentColor 25%, transparent); border-radius: 6px; cursor: pointer; background: transparent; color: inherit; font: inherit; }
|
|
929
|
+
pre { white-space: pre-wrap; word-break: break-word; padding: 12px; background: color-mix(in srgb, currentColor 5%, transparent); border-radius: 6px; }
|
|
930
|
+
.header-table th { width: 160px; }
|
|
931
|
+
`;
|
|
932
|
+
function renderListHtml(messages, href) {
|
|
933
|
+
const rows = messages.map((m) => `
|
|
934
|
+
<tr>
|
|
935
|
+
<td><a href="${escapeHtml(href(`/${m.id}`))}">${escapeHtml(m.subject || "(no subject)")}</a></td>
|
|
936
|
+
<td>${escapeHtml(formatAddress(m.from))}</td>
|
|
937
|
+
<td>${escapeHtml(m.to.map(formatAddress).join(", "))}</td>
|
|
938
|
+
<td class="meta">${escapeHtml(formatTime(m.capturedAt))}</td>
|
|
939
|
+
<td class="meta"><a href="${escapeHtml(href(`/${m.id}/raw`))}">.eml</a></td>
|
|
940
|
+
</tr>`).join("");
|
|
941
|
+
return `<!DOCTYPE html>
|
|
942
|
+
<html><head><meta charset="utf-8"><title>Void — Email inbox</title><style>${STYLE}</style></head>
|
|
943
|
+
<body>
|
|
944
|
+
<h1>Email inbox <span class="meta">(${messages.length} message${messages.length === 1 ? "" : "s"})</span></h1>
|
|
945
|
+
${messages.length === 0 ? `<div class="empty">No messages captured yet. Call <code>sendEmail()</code> from your app to populate.</div>` : `<table>
|
|
946
|
+
<thead><tr><th>Subject</th><th>From</th><th>To</th><th>Captured</th><th></th></tr></thead>
|
|
947
|
+
<tbody>${rows}</tbody>
|
|
948
|
+
</table>`}
|
|
949
|
+
</body></html>`;
|
|
950
|
+
}
|
|
951
|
+
function renderDetailHtml(m, href) {
|
|
952
|
+
const headerRows = Object.entries(m.headers).map(([k, v]) => `<tr><th>${escapeHtml(k)}</th><td>${escapeHtml(v)}</td></tr>`).join("");
|
|
953
|
+
const attachmentRows = m.attachments.map((a) => `<tr><td>${escapeHtml(a.filename)}</td><td>${escapeHtml(a.contentType)}</td><td>${a.size} B</td><td>${a.disposition}</td></tr>`).join("");
|
|
954
|
+
const bodyHtml = m.html ? `<iframe sandbox srcdoc="${escapeHtml(m.html)}"></iframe>` : `<pre>${escapeHtml(m.text ?? "")}</pre>`;
|
|
955
|
+
return `<!DOCTYPE html>
|
|
956
|
+
<html><head><meta charset="utf-8"><title>${escapeHtml(m.subject || "(no subject)")} — Void inbox</title><style>${STYLE}</style></head>
|
|
957
|
+
<body>
|
|
958
|
+
<div class="actions">
|
|
959
|
+
<a class="button" href="${escapeHtml(href(""))}">← Back</a>
|
|
960
|
+
<a class="button" href="${escapeHtml(href(`/${m.id}/raw`))}">Download .eml</a>
|
|
961
|
+
</div>
|
|
962
|
+
<h1>${escapeHtml(m.subject || "(no subject)")}</h1>
|
|
963
|
+
<table class="header-table">
|
|
964
|
+
<tr><th>From</th><td>${escapeHtml(formatAddress(m.from))}</td></tr>
|
|
965
|
+
<tr><th>To</th><td>${escapeHtml(m.to.map(formatAddress).join(", "))}</td></tr>
|
|
966
|
+
${m.cc.length > 0 ? `<tr><th>Cc</th><td>${escapeHtml(m.cc.map(formatAddress).join(", "))}</td></tr>` : ""}
|
|
967
|
+
${m.bcc.length > 0 ? `<tr><th>Bcc</th><td>${escapeHtml(m.bcc.map(formatAddress).join(", "))}</td></tr>` : ""}
|
|
968
|
+
${m.replyTo ? `<tr><th>Reply-To</th><td>${escapeHtml(formatAddress(m.replyTo))}</td></tr>` : ""}
|
|
969
|
+
<tr><th>Captured</th><td class="meta">${escapeHtml(formatTime(m.capturedAt))}</td></tr>
|
|
970
|
+
<tr><th>Message-ID</th><td class="meta">${escapeHtml(m.messageId)}</td></tr>
|
|
971
|
+
</table>
|
|
972
|
+
${headerRows ? `<h2>Custom headers</h2><table class="header-table">${headerRows}</table>` : ""}
|
|
973
|
+
${attachmentRows ? `<h2>Attachments</h2><table><thead><tr><th>Filename</th><th>Type</th><th>Size</th><th>Disposition</th></tr></thead><tbody>${attachmentRows}</tbody></table>` : ""}
|
|
974
|
+
<h2>Body</h2>
|
|
975
|
+
${bodyHtml}
|
|
976
|
+
</body></html>`;
|
|
977
|
+
}
|
|
978
|
+
//#endregion
|
|
675
979
|
//#region src/plugin-env-client-fold.ts
|
|
676
980
|
let cachedModule$1 = null;
|
|
677
981
|
async function loadEnvPublic$1() {
|
|
@@ -743,8 +1047,7 @@ function pushHit(node, hits) {
|
|
|
743
1047
|
return;
|
|
744
1048
|
}
|
|
745
1049
|
}
|
|
746
|
-
|
|
747
|
-
const DEFAULT_ENV_PREFIXES$2 = ["VITE_"];
|
|
1050
|
+
const CLIENT_ENV_PREFIX$1 = "VITE_";
|
|
748
1051
|
/**
|
|
749
1052
|
* Build-time constant folding for client-only `env.FOO` reads.
|
|
750
1053
|
*
|
|
@@ -759,21 +1062,19 @@ const DEFAULT_ENV_PREFIXES$2 = ["VITE_"];
|
|
|
759
1062
|
* • Runs only when `this.environment.name === 'client'`. Server / SSR /
|
|
760
1063
|
* worker builds keep the full runtime Proxy (secrets, runtime-injected
|
|
761
1064
|
* vars, HMR remain live).
|
|
762
|
-
* • Only folds keys that match
|
|
763
|
-
* set Vite is already willing to ship to the browser bundle. A
|
|
1065
|
+
* • Only folds keys that match Void's fixed `VITE_` client prefix. A
|
|
764
1066
|
* server-only key is never folded (and the env-client-guard plugin
|
|
765
1067
|
* would have errored out earlier anyway).
|
|
766
1068
|
* • Only folds static member access: `env.FOO` and `env["FOO"]`.
|
|
767
1069
|
* Dynamic access, destructuring, and reassignment fall through to the
|
|
768
1070
|
* runtime Proxy.
|
|
769
|
-
* • Only folds keys with a known build-time value (
|
|
770
|
-
*
|
|
1071
|
+
* • Only folds keys with a known build-time value (build shell or schema
|
|
1072
|
+
* `.default(...)`). Unknown keys are left as-is
|
|
771
1073
|
* and the Proxy handles them at runtime — no "undefined" shoved in.
|
|
772
|
-
* • Build-only (`apply: 'build'`). Dev runs through the Proxy so
|
|
773
|
-
*
|
|
1074
|
+
* • Build-only (`apply: 'build'`). Dev runs through the Proxy so local
|
|
1075
|
+
* `.env` edits take effect without a full rebuild.
|
|
774
1076
|
*/
|
|
775
1077
|
function envClientFoldPlugin() {
|
|
776
|
-
let envPrefixes = DEFAULT_ENV_PREFIXES$2;
|
|
777
1078
|
let loadedEnv = {};
|
|
778
1079
|
const schemaDefaults = {};
|
|
779
1080
|
/** The merged view the transform consults for each key. */
|
|
@@ -782,18 +1083,14 @@ function envClientFoldPlugin() {
|
|
|
782
1083
|
if (key in schemaDefaults) return schemaDefaults[key];
|
|
783
1084
|
}
|
|
784
1085
|
function isExposedToClient(key) {
|
|
785
|
-
return
|
|
1086
|
+
return key.startsWith(CLIENT_ENV_PREFIX$1);
|
|
786
1087
|
}
|
|
787
1088
|
return {
|
|
788
1089
|
name: "void:env-client-fold",
|
|
789
1090
|
apply: "build",
|
|
790
1091
|
enforce: "post",
|
|
791
1092
|
async configResolved(config) {
|
|
792
|
-
|
|
793
|
-
if (typeof prefix === "string") envPrefixes = [prefix];
|
|
794
|
-
else if (Array.isArray(prefix) && prefix.length > 0) envPrefixes = prefix;
|
|
795
|
-
else envPrefixes = DEFAULT_ENV_PREFIXES$2;
|
|
796
|
-
loadedEnv = { ...config.env ?? {} };
|
|
1093
|
+
loadedEnv = config.env ?? {};
|
|
797
1094
|
try {
|
|
798
1095
|
const mod = await loadEnvPublic$1();
|
|
799
1096
|
if (mod._hasRegisteredSchema()) {
|
|
@@ -947,18 +1244,11 @@ function recordHit(node, hits) {
|
|
|
947
1244
|
* No-op when no `env.ts` is registered. Server / SSR / worker environments
|
|
948
1245
|
* are skipped — only the `client` environment is checked.
|
|
949
1246
|
*/
|
|
950
|
-
|
|
951
|
-
const DEFAULT_ENV_PREFIXES$1 = ["VITE_"];
|
|
1247
|
+
const CLIENT_ENV_PREFIX = "VITE_";
|
|
952
1248
|
function envClientGuardPlugin(root) {
|
|
953
|
-
let envPrefixes = DEFAULT_ENV_PREFIXES$1;
|
|
954
1249
|
return {
|
|
955
1250
|
name: "void:env-client-guard",
|
|
956
1251
|
enforce: "post",
|
|
957
|
-
configResolved(config) {
|
|
958
|
-
const prefix = config.envPrefix;
|
|
959
|
-
if (typeof prefix === "string") envPrefixes = [prefix];
|
|
960
|
-
else if (Array.isArray(prefix) && prefix.length > 0) envPrefixes = prefix;
|
|
961
|
-
},
|
|
962
1252
|
async transform(code, id) {
|
|
963
1253
|
if (this.environment?.name !== "client") return;
|
|
964
1254
|
if (id.includes("/node_modules/")) return;
|
|
@@ -1001,10 +1291,9 @@ function envClientGuardPlugin(root) {
|
|
|
1001
1291
|
}
|
|
1002
1292
|
const key = hit.property;
|
|
1003
1293
|
if (!(key in schema)) continue;
|
|
1004
|
-
if (
|
|
1005
|
-
const prefixHint = envPrefixes.length === 1 ? `${envPrefixes[0]}* prefix` : `one of these prefixes: ${envPrefixes.join(", ")}`;
|
|
1294
|
+
if (key.startsWith(CLIENT_ENV_PREFIX)) continue;
|
|
1006
1295
|
this.error({
|
|
1007
|
-
message: `Server-only env "${key}" referenced from client code at ${relPath}:${line}:${column}.\nIf this should be available in the browser, rename it with the
|
|
1296
|
+
message: `Server-only env "${key}" referenced from client code at ${relPath}:${line}:${column}.\nIf this should be available in the browser, rename it with the VITE_* prefix in env.ts.\nIf it must stay server-only, remove this reference and read the value via a server route or loader.`,
|
|
1008
1297
|
loc: {
|
|
1009
1298
|
line,
|
|
1010
1299
|
column,
|
|
@@ -1028,32 +1317,42 @@ async function loadSchemaModule() {
|
|
|
1028
1317
|
* Vite plugin that auto-discovers `env.ts` at the project root and:
|
|
1029
1318
|
* - imports it (registering the user's schema via `defineEnv`)
|
|
1030
1319
|
* - generates `.void/env.d.ts` so `env.X` and `c.env.X` are typed
|
|
1031
|
-
* - validates the
|
|
1320
|
+
* - validates the local dev env (`.env` + process.env) and warns
|
|
1032
1321
|
* on missing/invalid required keys
|
|
1033
1322
|
* - regenerates types + re-validates when env.ts changes (HMR)
|
|
1034
1323
|
*
|
|
1035
1324
|
* Hard errors are reserved for `void deploy`; dev keeps moving with warnings
|
|
1036
|
-
* so unrelated work isn't blocked by a stale
|
|
1325
|
+
* so unrelated work isn't blocked by a stale local value.
|
|
1037
1326
|
*/
|
|
1038
1327
|
/** Patterns Vite's `define` typically uses for env-shaped constants. */
|
|
1039
1328
|
const DEFINE_ENV_PATTERN = /^(?:globalThis\.)?(?:process\.env|import\.meta\.env)\.([A-Z_][A-Z0-9_]*)$/;
|
|
1040
|
-
const
|
|
1041
|
-
function resolveEnvPrefixes(prefix) {
|
|
1042
|
-
if (typeof prefix === "string") return [prefix];
|
|
1043
|
-
if (Array.isArray(prefix) && prefix.length > 0) return prefix;
|
|
1044
|
-
return DEFAULT_ENV_PREFIXES;
|
|
1045
|
-
}
|
|
1329
|
+
const CLIENT_ENV_PREFIXES = [CLIENT_ENV_PREFIX$2];
|
|
1046
1330
|
function envSchemaPlugin(root, options = {}) {
|
|
1047
1331
|
const outDir = join(root, ".void");
|
|
1048
1332
|
let envFile = null;
|
|
1049
|
-
let
|
|
1050
|
-
let envDir = root;
|
|
1333
|
+
let command = "serve";
|
|
1051
1334
|
const appliedClientDefaults = /* @__PURE__ */ new Map();
|
|
1052
|
-
async function
|
|
1053
|
-
if (!envFile || !options.
|
|
1054
|
-
const { _hasRegisteredSchema,
|
|
1335
|
+
async function emitSchemaFacts(prefixes) {
|
|
1336
|
+
if (!envFile || !options.onSchema) return;
|
|
1337
|
+
const { _hasRegisteredSchema, _getRegisteredSchema } = await loadSchemaModule();
|
|
1055
1338
|
if (!_hasRegisteredSchema()) return;
|
|
1056
|
-
|
|
1339
|
+
const schema = _getRegisteredSchema() ?? {};
|
|
1340
|
+
const keys = Object.keys(schema);
|
|
1341
|
+
const clientKeys = keys.filter((key) => prefixes.some((prefix) => key.startsWith(prefix)));
|
|
1342
|
+
const clientKeySet = new Set(clientKeys);
|
|
1343
|
+
const serverKeys = keys.filter((key) => !clientKeySet.has(key));
|
|
1344
|
+
const requiredServerKeys = [];
|
|
1345
|
+
for (const key of serverKeys) {
|
|
1346
|
+
const result = schema[key]["~standard"].validate(void 0);
|
|
1347
|
+
const resolved = result instanceof Promise ? await result : result;
|
|
1348
|
+
if (resolved && typeof resolved === "object" && "issues" in resolved && resolved.issues) requiredServerKeys.push(key);
|
|
1349
|
+
}
|
|
1350
|
+
options.onSchema({
|
|
1351
|
+
keys,
|
|
1352
|
+
clientKeys,
|
|
1353
|
+
serverKeys,
|
|
1354
|
+
requiredServerKeys
|
|
1355
|
+
});
|
|
1057
1356
|
}
|
|
1058
1357
|
function regenerateTypes() {
|
|
1059
1358
|
if (!envFile) return;
|
|
@@ -1061,11 +1360,12 @@ function envSchemaPlugin(root, options = {}) {
|
|
|
1061
1360
|
const { dts } = generateEnvTypes(envFile, outDir);
|
|
1062
1361
|
writeFileIfChanged(join(outDir, "env.d.ts"), dts);
|
|
1063
1362
|
}
|
|
1064
|
-
async function importUserEnv() {
|
|
1363
|
+
async function importUserEnv(strict = false) {
|
|
1065
1364
|
if (!envFile) return;
|
|
1066
1365
|
try {
|
|
1067
1366
|
await loadUserEnvFile(envFile);
|
|
1068
1367
|
} catch (err) {
|
|
1368
|
+
if (strict) throw err;
|
|
1069
1369
|
voidWarn(err.message);
|
|
1070
1370
|
}
|
|
1071
1371
|
}
|
|
@@ -1093,41 +1393,76 @@ function envSchemaPlugin(root, options = {}) {
|
|
|
1093
1393
|
if (!envFile) return;
|
|
1094
1394
|
const { _hasRegisteredSchema, validateAllEnv } = await loadSchemaModule();
|
|
1095
1395
|
if (!_hasRegisteredSchema()) return;
|
|
1096
|
-
const
|
|
1097
|
-
|
|
1396
|
+
const report = await validateAllEnv({
|
|
1397
|
+
...loadLocalEnv(root, { onWarn: (message) => voidWarn(message) }),
|
|
1398
|
+
...process.env
|
|
1399
|
+
});
|
|
1098
1400
|
if (report.valid) return;
|
|
1099
1401
|
const lines = ["Env validation issues:"];
|
|
1100
|
-
for (const key of report.missing) lines.push(` • ${key} is required but missing — add it to .env
|
|
1402
|
+
for (const key of report.missing) lines.push(` • ${key} is required but missing — add it to .env or set it in your shell`);
|
|
1101
1403
|
for (const { key, messages } of report.invalid) lines.push(` • ${key}: ${messages.join("; ")}`);
|
|
1102
1404
|
voidWarn(lines.join("\n"));
|
|
1103
1405
|
}
|
|
1104
|
-
async function
|
|
1406
|
+
async function applyClientValuesToViteEnv(config) {
|
|
1105
1407
|
if (!envFile) return;
|
|
1106
|
-
|
|
1408
|
+
const configEnv = config.env ?? {};
|
|
1409
|
+
for (const [key, value] of appliedClientDefaults) if (configEnv[key] === value) delete configEnv[key];
|
|
1107
1410
|
appliedClientDefaults.clear();
|
|
1108
|
-
const { _hasRegisteredSchema, _getSchemaDefaults } = await loadSchemaModule();
|
|
1411
|
+
const { _hasRegisteredSchema, _getRegisteredSchema, _getSchemaDefaults } = await loadSchemaModule();
|
|
1109
1412
|
if (!_hasRegisteredSchema()) return;
|
|
1110
|
-
const
|
|
1413
|
+
const schema = _getRegisteredSchema() ?? {};
|
|
1414
|
+
const readable = {
|
|
1415
|
+
...command === "serve" ? loadLocalEnv(root) : {},
|
|
1416
|
+
...process.env
|
|
1417
|
+
};
|
|
1418
|
+
for (const key of Object.keys(schema)) {
|
|
1419
|
+
if (!key.startsWith("VITE_") || configEnv[key] !== void 0) continue;
|
|
1420
|
+
const value = readable[key];
|
|
1421
|
+
if (value !== void 0) configEnv[key] = value;
|
|
1422
|
+
}
|
|
1111
1423
|
for (const [key, value] of Object.entries(_getSchemaDefaults())) {
|
|
1112
|
-
if (!
|
|
1113
|
-
if (
|
|
1114
|
-
|
|
1424
|
+
if (!key.startsWith("VITE_")) continue;
|
|
1425
|
+
if (configEnv[key] !== void 0) continue;
|
|
1426
|
+
configEnv[key] = value;
|
|
1115
1427
|
appliedClientDefaults.set(key, value);
|
|
1116
1428
|
}
|
|
1117
1429
|
}
|
|
1118
1430
|
return {
|
|
1119
1431
|
name: "void:env-schema",
|
|
1120
|
-
|
|
1432
|
+
enforce: "pre",
|
|
1433
|
+
async config(_config, environment) {
|
|
1434
|
+
const legacyFiles = findLegacyEnvFiles(root);
|
|
1435
|
+
if (legacyFiles.length > 0) throw new Error(`void/env supports one local file: .env. Remove ${legacyFiles.join(", ")} and follow the env migration guide.`);
|
|
1121
1436
|
envFile = findEnvFile(root);
|
|
1122
1437
|
if (!envFile) return;
|
|
1123
1438
|
regenerateTypes();
|
|
1124
|
-
await importUserEnv();
|
|
1125
|
-
await
|
|
1439
|
+
await importUserEnv(environment.command === "build");
|
|
1440
|
+
await emitSchemaFacts(CLIENT_ENV_PREFIXES);
|
|
1126
1441
|
},
|
|
1127
1442
|
async configResolved(config) {
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1443
|
+
command = config.command;
|
|
1444
|
+
await emitSchemaFacts(CLIENT_ENV_PREFIXES);
|
|
1445
|
+
if (command === "build") {
|
|
1446
|
+
const local = loadLocalEnv(root, { onWarn: (message) => voidWarn(message) });
|
|
1447
|
+
for (const [key, value] of Object.entries(local)) if (process.env[key] === void 0 && config.env[key] === value) delete config.env[key];
|
|
1448
|
+
}
|
|
1449
|
+
await applyClientValuesToViteEnv(config);
|
|
1450
|
+
if (command === "build" && envFile) {
|
|
1451
|
+
const { validateAllEnv } = await loadSchemaModule();
|
|
1452
|
+
const report = await validateAllEnv({
|
|
1453
|
+
...config.env,
|
|
1454
|
+
...process.env
|
|
1455
|
+
});
|
|
1456
|
+
const clientKey = (key) => key.startsWith(CLIENT_ENV_PREFIX$2);
|
|
1457
|
+
const missing = report.missing.filter(clientKey);
|
|
1458
|
+
const invalid = report.invalid.filter(({ key }) => clientKey(key));
|
|
1459
|
+
if (missing.length > 0 || invalid.length > 0) {
|
|
1460
|
+
const lines = ["Client env validation failed:"];
|
|
1461
|
+
for (const key of missing) lines.push(` • ${key} is required — set it in the build shell or add a schema default`);
|
|
1462
|
+
for (const { key, messages } of invalid) lines.push(` • ${key}: ${messages.join("; ")}`);
|
|
1463
|
+
throw new Error(lines.join("\n"));
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1131
1466
|
if (envFile && config.define) await warnOnDefineOverlap(config.define);
|
|
1132
1467
|
},
|
|
1133
1468
|
async configureServer(server) {
|
|
@@ -1144,8 +1479,8 @@ function envSchemaPlugin(root, options = {}) {
|
|
|
1144
1479
|
voidLog("env.ts changed — regenerating types");
|
|
1145
1480
|
regenerateTypes();
|
|
1146
1481
|
await importUserEnv();
|
|
1147
|
-
await
|
|
1148
|
-
await
|
|
1482
|
+
await emitSchemaFacts(CLIENT_ENV_PREFIXES);
|
|
1483
|
+
await applyClientValuesToViteEnv(server.config);
|
|
1149
1484
|
await validateAndWarn();
|
|
1150
1485
|
server.ws.send({ type: "full-reload" });
|
|
1151
1486
|
}
|
|
@@ -1158,6 +1493,7 @@ function envSchemaPlugin(root, options = {}) {
|
|
|
1158
1493
|
}
|
|
1159
1494
|
//#endregion
|
|
1160
1495
|
//#region src/plugin-framework-triggers.ts
|
|
1496
|
+
const DISPATCH_FILE_MODE = 384;
|
|
1161
1497
|
/** Absolute path of the generated dispatch file. Stable across the dev process. */
|
|
1162
1498
|
function frameworkTriggersDispatchPath(root) {
|
|
1163
1499
|
return join(root, ".void", "dev-triggers.ts");
|
|
@@ -1174,7 +1510,10 @@ function writeFrameworkTriggersDispatch(root, devTriggerToken) {
|
|
|
1174
1510
|
const queues = scanQueuesSync(root, paths.queuesDir);
|
|
1175
1511
|
const target = frameworkTriggersDispatchPath(root);
|
|
1176
1512
|
mkdirSync(dirname(target), { recursive: true });
|
|
1177
|
-
writeFileSync(target, generateModule(paths.cronsDir, paths.queuesDir, jobs, queues, devTriggerToken));
|
|
1513
|
+
writeFileSync(target, generateModule(paths.cronsDir, paths.queuesDir, jobs, queues, devTriggerToken), { mode: DISPATCH_FILE_MODE });
|
|
1514
|
+
if (process.platform !== "win32") try {
|
|
1515
|
+
chmodSync(target, DISPATCH_FILE_MODE);
|
|
1516
|
+
} catch {}
|
|
1178
1517
|
}
|
|
1179
1518
|
/**
|
|
1180
1519
|
* Writes a real file at `<root>/.void/dev-triggers.ts` exporting
|
|
@@ -1616,24 +1955,12 @@ function astroDevTriggerInjectPlugin(root) {
|
|
|
1616
1955
|
//#endregion
|
|
1617
1956
|
//#region src/plugin-migration.ts
|
|
1618
1957
|
function readDatabaseUrl(root) {
|
|
1619
|
-
|
|
1620
|
-
if (!existsSync(envPath)) return;
|
|
1621
|
-
const content = readFileSync(envPath, "utf-8");
|
|
1622
|
-
for (const line of content.split("\n")) {
|
|
1623
|
-
const trimmed = line.trim();
|
|
1624
|
-
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
1625
|
-
const eqIndex = trimmed.indexOf("=");
|
|
1626
|
-
if (eqIndex === -1) continue;
|
|
1627
|
-
if (trimmed.slice(0, eqIndex).trim() !== "DATABASE_URL") continue;
|
|
1628
|
-
let value = trimmed.slice(eqIndex + 1).trim();
|
|
1629
|
-
if (value.startsWith("\"") && value.endsWith("\"") || value.startsWith("'") && value.endsWith("'")) value = value.slice(1, -1);
|
|
1630
|
-
return value;
|
|
1631
|
-
}
|
|
1958
|
+
return loadLocalEnv(root).DATABASE_URL;
|
|
1632
1959
|
}
|
|
1633
1960
|
/**
|
|
1634
1961
|
* Vite plugin that runs local migrations on dev server startup.
|
|
1635
1962
|
* For SQLite/D1: applies migrations to the local miniflare database.
|
|
1636
|
-
* For PostgreSQL: connects via DATABASE_URL from .env.
|
|
1963
|
+
* For PostgreSQL/MySQL: connects via DATABASE_URL from .env.
|
|
1637
1964
|
*/
|
|
1638
1965
|
function migrationPlugin(root, dialect, databaseId = "local", persistRoot = join(root, ".void"), auth) {
|
|
1639
1966
|
return {
|
|
@@ -1644,35 +1971,34 @@ function migrationPlugin(root, dialect, databaseId = "local", persistRoot = join
|
|
|
1644
1971
|
const hasSqlMigrations = existsSync(migrationsDir);
|
|
1645
1972
|
if (!hasSqlMigrations && !auth?.enabled) return;
|
|
1646
1973
|
try {
|
|
1647
|
-
if (hasSqlMigrations && dialect
|
|
1974
|
+
if (hasSqlMigrations && dialect !== "sqlite") {
|
|
1648
1975
|
const url = readDatabaseUrl(root);
|
|
1649
1976
|
if (!url) {
|
|
1650
1977
|
const warn = () => {
|
|
1651
1978
|
console.log();
|
|
1652
|
-
voidError(
|
|
1979
|
+
voidError(`DATABASE_URL not found in .env — skipping ${dialect === "mysql" ? "MySQL" : "PostgreSQL"} migrations.`);
|
|
1653
1980
|
};
|
|
1654
1981
|
if (server.httpServer) server.httpServer.once("listening", () => setTimeout(warn, 100));
|
|
1655
1982
|
else warn();
|
|
1656
1983
|
return;
|
|
1657
1984
|
}
|
|
1658
|
-
const {
|
|
1659
|
-
const {
|
|
1660
|
-
const { validateMigrations } = await import("./validate-Cw_RLeTj.mjs").then((n) => n.i);
|
|
1985
|
+
const { collectMigrations } = await import("./validate-Bihr8WBi.mjs").then((n) => n.l);
|
|
1986
|
+
const { validateMigrations } = await import("./validate-Bihr8WBi.mjs").then((n) => n.i);
|
|
1661
1987
|
const allMigrations = collectMigrations(migrationsDir);
|
|
1662
|
-
const
|
|
1663
|
-
const
|
|
1664
|
-
const
|
|
1665
|
-
if (
|
|
1666
|
-
validateMigrations(
|
|
1988
|
+
const appliedNames = dialect === "mysql" ? await import("./runner-mysql-CgRFl3s6.mjs").then((n) => n.n).then((runner) => runner.getMySqlAppliedMigrations(url)) : await import("./runner-pg-DCkWPsWS.mjs").then((n) => n.n).then((runner) => runner.getPgAppliedMigrations(url));
|
|
1989
|
+
const appliedSet = new Set(appliedNames);
|
|
1990
|
+
const pending = allMigrations.filter((migration) => !appliedSet.has(migration.name));
|
|
1991
|
+
if (pending.length > 0) try {
|
|
1992
|
+
validateMigrations(pending);
|
|
1667
1993
|
} catch (err) {
|
|
1668
1994
|
voidWarn(err instanceof Error ? err.message : String(err));
|
|
1669
1995
|
}
|
|
1670
|
-
const applied = await runPgMigrations(migrationsDir, url);
|
|
1996
|
+
const applied = dialect === "mysql" ? await import("./runner-mysql-CgRFl3s6.mjs").then((n) => n.n).then((runner) => runner.runMySqlMigrations(migrationsDir, url)) : await import("./runner-pg-DCkWPsWS.mjs").then((n) => n.n).then((runner) => runner.runPgMigrations(migrationsDir, url));
|
|
1671
1997
|
if (applied.length > 0) voidLog(`Applied ${applied.length} migration(s): ${applied.join(", ")}`);
|
|
1672
1998
|
} else if (hasSqlMigrations) {
|
|
1673
|
-
const { runMigrations, getMiniflareDatabasePath, getAppliedMigrations } = await import("./
|
|
1674
|
-
const { collectMigrations } = await import("./validate-
|
|
1675
|
-
const { validateMigrations } = await import("./validate-
|
|
1999
|
+
const { runMigrations, getMiniflareDatabasePath, getAppliedMigrations } = await import("./local-d1-BE8KBbMy.mjs").then((n) => n.i);
|
|
2000
|
+
const { collectMigrations } = await import("./validate-Bihr8WBi.mjs").then((n) => n.l);
|
|
2001
|
+
const { validateMigrations } = await import("./validate-Bihr8WBi.mjs").then((n) => n.i);
|
|
1676
2002
|
const dbPath = getMiniflareDatabasePath(persistRoot, databaseId);
|
|
1677
2003
|
const allMigrations = collectMigrations(migrationsDir);
|
|
1678
2004
|
const appliedRows = await getAppliedMigrations(dbPath);
|
|
@@ -1687,7 +2013,7 @@ function migrationPlugin(root, dialect, databaseId = "local", persistRoot = join
|
|
|
1687
2013
|
if (applied.length > 0) voidLog(`Applied ${applied.length} migration(s): ${applied.join(", ")}`);
|
|
1688
2014
|
}
|
|
1689
2015
|
if (auth?.enabled) {
|
|
1690
|
-
const { runLocalVoidAuthMigrations } = await import("./node-
|
|
2016
|
+
const { runLocalVoidAuthMigrations } = await import("./node-BkaXcpAc.mjs");
|
|
1691
2017
|
await runLocalVoidAuthMigrations(root, dialect, persistRoot, databaseId, auth.configPath);
|
|
1692
2018
|
voidLog("Applied Better Auth migrations");
|
|
1693
2019
|
}
|
|
@@ -1775,6 +2101,14 @@ function nodeTargetPlugin(target) {
|
|
|
1775
2101
|
throw new Error(`target: '${id}' is not available with target '${target}'. CF bindings require target: "cloudflare".`);
|
|
1776
2102
|
}
|
|
1777
2103
|
},
|
|
2104
|
+
renderChunk(code, chunk) {
|
|
2105
|
+
if (!code.includes("import.meta.voidClientDirectory")) return null;
|
|
2106
|
+
const clientPath = relative(dirname(chunk.fileName), "../client");
|
|
2107
|
+
return {
|
|
2108
|
+
code: code.replaceAll("import.meta.voidClientDirectory", `new URL(${JSON.stringify(`${clientPath}/`)}, import.meta.url)`),
|
|
2109
|
+
map: null
|
|
2110
|
+
};
|
|
2111
|
+
},
|
|
1778
2112
|
config(_, { command }) {
|
|
1779
2113
|
if (command !== "build") return;
|
|
1780
2114
|
const root = process.cwd();
|
|
@@ -1839,6 +2173,7 @@ function prerenderPlugin(root, config) {
|
|
|
1839
2173
|
apply: "build",
|
|
1840
2174
|
async closeBundle() {
|
|
1841
2175
|
if (config.output !== "static") return;
|
|
2176
|
+
if (process.env.VOID_DEPLOY_BUILD === "1") return;
|
|
1842
2177
|
if (this.environment?.name !== "client") return;
|
|
1843
2178
|
setShowTimestamp(false);
|
|
1844
2179
|
const distDir = resolveDistDir(root);
|
|
@@ -1851,12 +2186,15 @@ function prerenderPlugin(root, config) {
|
|
|
1851
2186
|
});
|
|
1852
2187
|
else {
|
|
1853
2188
|
const persistDir = join(root, ".void");
|
|
2189
|
+
const workerDirName = resolveWorkerDirName(distDir);
|
|
2190
|
+
const workerDir = join(distDir, workerDirName);
|
|
2191
|
+
const remoteMode = resolveRemoteMode(config.remote);
|
|
1854
2192
|
result = await prerenderPages({
|
|
1855
2193
|
root,
|
|
1856
|
-
workerDir
|
|
2194
|
+
workerDir,
|
|
1857
2195
|
clientDir,
|
|
1858
2196
|
persistDir,
|
|
1859
|
-
remoteMode
|
|
2197
|
+
remoteMode,
|
|
1860
2198
|
projectId: process.env.VOID_DEPLOY_PROJECT_ID || void 0
|
|
1861
2199
|
});
|
|
1862
2200
|
}
|
|
@@ -2535,10 +2873,11 @@ function pushDefaultErrorPageHelpers(lines, options) {
|
|
|
2535
2873
|
* - Middleware registered via app.use()
|
|
2536
2874
|
* - Routes registered with lazy-loaded handlers and auto-conversion
|
|
2537
2875
|
*/
|
|
2538
|
-
function compileRouteTable(scan, routesDir, middlewareDir, jobsDir, queuesDir, ssr, options, pages = null, mergedRevalidate) {
|
|
2876
|
+
function compileRouteTable(scan, routesDir, middlewareDir, jobsDir, queuesDir, ssr, options, pages = null, mergedRevalidate, isrPages, isrPathRevalidate) {
|
|
2539
2877
|
const lines = [];
|
|
2540
2878
|
const auth = options.auth;
|
|
2541
2879
|
const webSockets = scan.websockets ?? [];
|
|
2880
|
+
const managedDispatch = options.nodeTarget !== true && options.dev !== true && options.managedDispatch === true;
|
|
2542
2881
|
lines.push(`import { AsyncLocalStorage } from "node:async_hooks";`);
|
|
2543
2882
|
lines.push(`import { Hono } from ${JSON.stringify(options.honoPath)};`);
|
|
2544
2883
|
lines.push(`import { convertReturnValue } from ${JSON.stringify(options.responsePath)};`);
|
|
@@ -2557,7 +2896,7 @@ function compileRouteTable(scan, routesDir, middlewareDir, jobsDir, queuesDir, s
|
|
|
2557
2896
|
if (auth.authSchemaPath) lines.push(`import { migrationSchema as __voidAuthMigrationSchema } from ${JSON.stringify(auth.authSchemaPath)};`);
|
|
2558
2897
|
if (auth.authConfigPath) lines.push(`import __voidAuthConfig from ${JSON.stringify(auth.authConfigPath)};`);
|
|
2559
2898
|
}
|
|
2560
|
-
if (webSockets.length > 0 && options.webSocketRuntimePath) lines.push(`import { createWebSocketDurableObject as __createWebSocketDurableObject,
|
|
2899
|
+
if ((webSockets.length > 0 || options.webSocketTombstones?.length) && options.webSocketRuntimePath) lines.push(`import { createWebSocketDurableObject as __createWebSocketDurableObject, createWebSocketTombstoneDurableObject as __createWebSocketTombstoneDurableObject, forwardWebSocketRequest as __forwardWebSocketRequest } from ${JSON.stringify(options.webSocketRuntimePath)};`);
|
|
2561
2900
|
if (options.hasLive && options.liveRuntimePath) lines.push(`import { createLiveDurableObject as __createLiveDurableObject } from ${JSON.stringify(options.liveRuntimePath)};`);
|
|
2562
2901
|
lines.push("");
|
|
2563
2902
|
for (let i = 0; i < scan.middleware.length; i++) {
|
|
@@ -2642,7 +2981,7 @@ function compileRouteTable(scan, routesDir, middlewareDir, jobsDir, queuesDir, s
|
|
|
2642
2981
|
lines.push("");
|
|
2643
2982
|
ensureMergeQueryHelperEmitted(lines);
|
|
2644
2983
|
lines.push("app.use(async (c, next) => {");
|
|
2645
|
-
if (
|
|
2984
|
+
if (managedDispatch) {
|
|
2646
2985
|
lines.push(" if (!__voidOriginalUrls.has(c.req.raw)) {");
|
|
2647
2986
|
lines.push(" const __h = c.req.raw.headers.get(\"X-Void-Original-URL\");");
|
|
2648
2987
|
lines.push(" if (__h != null) {");
|
|
@@ -2692,7 +3031,7 @@ function compileRouteTable(scan, routesDir, middlewareDir, jobsDir, queuesDir, s
|
|
|
2692
3031
|
else lines.push(" await requestContext.run({ request: c.req.raw, executionCtx: c.executionCtx }, next);");
|
|
2693
3032
|
lines.push("});");
|
|
2694
3033
|
lines.push("");
|
|
2695
|
-
const emitEdgeRules =
|
|
3034
|
+
const emitEdgeRules = !managedDispatch;
|
|
2696
3035
|
if (emitEdgeRules && options.redirectRules?.length) compileRoutingRulesMiddleware(lines, options.redirectRules, options.dev === true, options.nodeTarget === true);
|
|
2697
3036
|
if (emitEdgeRules && options.headerRules?.length) compileHeaderMiddleware(lines, options.headerRules);
|
|
2698
3037
|
if (auth) {
|
|
@@ -2703,6 +3042,14 @@ function compileRouteTable(scan, routesDir, middlewareDir, jobsDir, queuesDir, s
|
|
|
2703
3042
|
}
|
|
2704
3043
|
for (let i = 0; i < scan.middleware.length; i++) lines.push(`app.use(middleware${i});`);
|
|
2705
3044
|
if (scan.middleware.length > 0) lines.push("");
|
|
3045
|
+
for (let i = 0; i < webSockets.length; i++) {
|
|
3046
|
+
const route = webSockets[i];
|
|
3047
|
+
lines.push(`app.all(${JSON.stringify(route.pattern)}, async (c, next) => {`);
|
|
3048
|
+
lines.push(` if (c.req.raw.headers.get("upgrade")?.toLowerCase() !== "websocket") return next();`);
|
|
3049
|
+
lines.push(` return __forwardWebSocketRequest(c.req.raw, c.env, __voidWebSocketRoutes[${i}]);`);
|
|
3050
|
+
lines.push("});");
|
|
3051
|
+
}
|
|
3052
|
+
if (webSockets.length > 0) lines.push("");
|
|
2706
3053
|
if (auth) {
|
|
2707
3054
|
lines.push("app.all(\"/api/auth\", async (c) => {");
|
|
2708
3055
|
lines.push(` return handleVoidAuthRequest(c, __voidAuthOptions${auth.authDatabasePath ? ", __voidAuthDatabase" : ""});`);
|
|
@@ -2760,21 +3107,10 @@ function compileRouteTable(scan, routesDir, middlewareDir, jobsDir, queuesDir, s
|
|
|
2760
3107
|
className: route.className,
|
|
2761
3108
|
bindingName: route.bindingName
|
|
2762
3109
|
})))};`);
|
|
2763
|
-
lines.push("export async function __voidHandleWebSocket(request, env) {");
|
|
2764
|
-
lines.push(" return __handleWebSocketUpgrade(request, env, __voidWebSocketRoutes);");
|
|
2765
|
-
lines.push("}");
|
|
2766
|
-
lines.push("");
|
|
2767
|
-
for (let i = 0; i < webSockets.length; i++) {
|
|
2768
|
-
const route = webSockets[i];
|
|
2769
|
-
lines.push(`app.all(${JSON.stringify(route.pattern)}, async (c) => {`);
|
|
2770
|
-
lines.push(` return __forwardWebSocketRequest(c.req.raw, c.env, __voidWebSocketRoutes[${i}]);`);
|
|
2771
|
-
lines.push("});");
|
|
2772
|
-
}
|
|
2773
|
-
lines.push("");
|
|
2774
|
-
} else {
|
|
2775
|
-
lines.push("export async function __voidHandleWebSocket() { return null; }");
|
|
2776
3110
|
lines.push("");
|
|
2777
3111
|
}
|
|
3112
|
+
for (const className of options.webSocketTombstones ?? []) lines.push(`export const ${className} = __createWebSocketTombstoneDurableObject(${JSON.stringify(className)});`);
|
|
3113
|
+
if (options.webSocketTombstones?.length) lines.push("");
|
|
2778
3114
|
if (options.hasLive) {
|
|
2779
3115
|
lines.push("export const VoidLiveStreamDurableObject = __createLiveDurableObject();");
|
|
2780
3116
|
lines.push("");
|
|
@@ -2899,7 +3235,7 @@ window.__vite_plugin_react_preamble_installed__ = true;
|
|
|
2899
3235
|
lines.push(`app.notFound(async (c) => {`);
|
|
2900
3236
|
if (options.nodeTarget && options.fallbackRules?.length) emitFallbackRulesCheck(lines, options.fallbackRules, options.dev === true, " ", options.nodeTarget === true);
|
|
2901
3237
|
lines.push(` if (!shouldHandleSsrRequest(c)) {`);
|
|
2902
|
-
if (!options.nodeTarget &&
|
|
3238
|
+
if (!options.nodeTarget && emitEdgeRules && options.fallbackRules?.length) {
|
|
2903
3239
|
lines.push(` const __assetRes = await fetchFromAssets(c);`);
|
|
2904
3240
|
lines.push(` if (__assetRes.status !== 404) return __assetRes;`);
|
|
2905
3241
|
emitFallbackRulesCheck(lines, options.fallbackRules, options.dev === true, " ", false);
|
|
@@ -2910,16 +3246,16 @@ window.__vite_plugin_react_preamble_installed__ = true;
|
|
|
2910
3246
|
lines.push(` return renderSsrResponse(c, mod);`);
|
|
2911
3247
|
lines.push(`});`);
|
|
2912
3248
|
lines.push("");
|
|
2913
|
-
} else if ((options.
|
|
3249
|
+
} else if (emitEdgeRules && (options.fallbackRules?.length || !options.nodeTarget && options.headerRules?.length) && !(pages && scan.pages.pages.length > 0)) {
|
|
2914
3250
|
lines.push(`app.notFound(async (c) => {`);
|
|
2915
|
-
if (!options.nodeTarget
|
|
3251
|
+
if (!options.nodeTarget) {
|
|
2916
3252
|
lines.push(` const assets = c.env?.ASSETS;`);
|
|
2917
3253
|
lines.push(` if (assets && typeof assets.fetch === "function") {`);
|
|
2918
3254
|
lines.push(` const __assetRes = await assets.fetch(c.req.raw);`);
|
|
2919
3255
|
lines.push(` if (__assetRes.status !== 404) return __assetRes;`);
|
|
2920
3256
|
lines.push(` }`);
|
|
2921
3257
|
}
|
|
2922
|
-
emitFallbackRulesCheck(lines, options.fallbackRules, options.dev === true, " ", options.nodeTarget === true);
|
|
3258
|
+
if (options.fallbackRules?.length) emitFallbackRulesCheck(lines, options.fallbackRules, options.dev === true, " ", options.nodeTarget === true);
|
|
2923
3259
|
lines.push(` return __voidMarkNoMatch(c.req.raw, new Response("Not Found", { status: 404 }));`);
|
|
2924
3260
|
lines.push(`});`);
|
|
2925
3261
|
lines.push("");
|
|
@@ -2931,22 +3267,20 @@ window.__vite_plugin_react_preamble_installed__ = true;
|
|
|
2931
3267
|
}
|
|
2932
3268
|
lines.push("");
|
|
2933
3269
|
lines.push("export async function scheduled(controller, env, ctx) {");
|
|
2934
|
-
lines.push("
|
|
3270
|
+
lines.push(" const tasks = [];");
|
|
2935
3271
|
for (let i = 0; i < scan.jobs.length; i++) {
|
|
2936
3272
|
const job = scan.jobs[i];
|
|
2937
3273
|
const filePath = JSON.stringify(`${jobsDir}/${job.filePath}`);
|
|
2938
|
-
|
|
2939
|
-
|
|
3274
|
+
lines.push(` if (job${i}Crons.includes(controller.cron)) {`);
|
|
3275
|
+
lines.push(" tasks.push((async () => {");
|
|
2940
3276
|
lines.push(` const mod = await import(${filePath});`);
|
|
2941
|
-
lines.push(" if (typeof mod.default === 'function')
|
|
2942
|
-
lines.push("
|
|
2943
|
-
lines.push("
|
|
2944
|
-
lines.push(" return;");
|
|
2945
|
-
lines.push(" }");
|
|
3277
|
+
lines.push(" if (typeof mod.default === 'function') await mod.default(controller, env, ctx);");
|
|
3278
|
+
lines.push(" })());");
|
|
3279
|
+
lines.push(" }");
|
|
2946
3280
|
}
|
|
2947
|
-
lines.push("
|
|
2948
|
-
lines.push("
|
|
2949
|
-
lines.push("
|
|
3281
|
+
lines.push(" const results = await Promise.allSettled(tasks);");
|
|
3282
|
+
lines.push(" const errors = results.filter(result => result.status === \"rejected\").map(result => result.reason);");
|
|
3283
|
+
lines.push(" if (errors.length) throw new AggregateError(errors, \"Scheduled jobs failed\");");
|
|
2950
3284
|
lines.push("}");
|
|
2951
3285
|
lines.push("");
|
|
2952
3286
|
} else {
|
|
@@ -2970,10 +3304,14 @@ window.__vite_plugin_react_preamble_installed__ = true;
|
|
|
2970
3304
|
lines.push("");
|
|
2971
3305
|
}
|
|
2972
3306
|
if (scan.queues.length > 0) {
|
|
2973
|
-
|
|
3307
|
+
lines.push(generateQueueResolverSource(scan.queues.map((queue) => queue.name)));
|
|
2974
3308
|
lines.push("");
|
|
2975
3309
|
lines.push("export async function __processQueue(payload, env) {");
|
|
2976
3310
|
lines.push(" const queueSuffix = payload.queue;");
|
|
3311
|
+
lines.push(" const __queueIndex = __resolveQueueIndex(queueSuffix);");
|
|
3312
|
+
lines.push(" if (__queueIndex === -1) {");
|
|
3313
|
+
lines.push(" return { ok: false, error: `No unambiguous queue handler matches \"${String(queueSuffix)}\"` };");
|
|
3314
|
+
lines.push(" }");
|
|
2977
3315
|
lines.push(" const __decisions = new Map();");
|
|
2978
3316
|
lines.push(" function __wrapMsg(m) {");
|
|
2979
3317
|
lines.push(" let decided = false;");
|
|
@@ -2992,12 +3330,14 @@ window.__vite_plugin_react_preamble_installed__ = true;
|
|
|
2992
3330
|
lines.push(" };");
|
|
2993
3331
|
lines.push(" let __ok = true;");
|
|
2994
3332
|
lines.push(" try {");
|
|
3333
|
+
lines.push(" switch (__queueIndex) {");
|
|
2995
3334
|
for (let i = 0; i < scan.queues.length; i++) {
|
|
2996
3335
|
const q = scan.queues[i];
|
|
2997
|
-
|
|
2998
|
-
lines.push(`
|
|
2999
|
-
lines.push(
|
|
3000
|
-
lines.push("
|
|
3336
|
+
lines.push(` case ${i}: {`);
|
|
3337
|
+
lines.push(` const mod = await import(${JSON.stringify(`${queuesDir}/${q.filePath}`)});`);
|
|
3338
|
+
lines.push(" if (typeof mod.default === 'function') await mod.default(batch, env);");
|
|
3339
|
+
lines.push(" break;");
|
|
3340
|
+
lines.push(" }");
|
|
3001
3341
|
}
|
|
3002
3342
|
lines.push(" }");
|
|
3003
3343
|
lines.push(" } catch { __ok = false; }");
|
|
@@ -3018,6 +3358,63 @@ window.__vite_plugin_react_preamble_installed__ = true;
|
|
|
3018
3358
|
lines.push("app.post(\"/__void/queue\", __queueHandler);");
|
|
3019
3359
|
lines.push("");
|
|
3020
3360
|
}
|
|
3361
|
+
const email = scan.email;
|
|
3362
|
+
const emailDir = options.emailDir;
|
|
3363
|
+
if (emailDir && email && (email.addresses.length > 0 || email.defaultHandler)) {
|
|
3364
|
+
if (email.defaultHandler) lines.push(`const __emailDefault = () => import(${JSON.stringify(`${emailDir}/${email.defaultHandler}`)});`);
|
|
3365
|
+
for (let i = 0; i < email.addresses.length; i++) {
|
|
3366
|
+
const def = email.addresses[i];
|
|
3367
|
+
lines.push(`const __emailAddr${i} = () => import(${JSON.stringify(`${emailDir}/${def.filePath}`)});`);
|
|
3368
|
+
}
|
|
3369
|
+
if (email.addresses.length > 0) {
|
|
3370
|
+
lines.push("const __emailPatterns = [");
|
|
3371
|
+
for (let i = 0; i < email.addresses.length; i++) {
|
|
3372
|
+
const def = email.addresses[i];
|
|
3373
|
+
const path = `${emailDir}/${def.filePath}`;
|
|
3374
|
+
lines.push(` { re: new RegExp(${JSON.stringify(def.pattern.regexSource)}, "i"), params: ${JSON.stringify(def.pattern.paramNames)}, path: ${JSON.stringify(path)}, load: __emailAddr${i} },`);
|
|
3375
|
+
}
|
|
3376
|
+
lines.push("];");
|
|
3377
|
+
}
|
|
3378
|
+
lines.push("");
|
|
3379
|
+
lines.push("export async function __emailHandler(message, env, ctx, __opts) {");
|
|
3380
|
+
lines.push(" const __platformTo = message ? message.__voidPlatformTo : undefined;");
|
|
3381
|
+
lines.push(" const __to = String((__platformTo ?? (message && message.to)) || \"\");");
|
|
3382
|
+
lines.push(" const __localFull = __to.split(\"@\")[0] || \"\";");
|
|
3383
|
+
lines.push(" let __local = __localFull;");
|
|
3384
|
+
lines.push(" if (__opts && __opts.slug) {");
|
|
3385
|
+
lines.push(" const __plus = __localFull.indexOf(\"+\");");
|
|
3386
|
+
lines.push(" __local = __plus === -1 ? \"\" : __localFull.slice(__plus + 1);");
|
|
3387
|
+
lines.push(" }");
|
|
3388
|
+
if (email.addresses.length > 0) {
|
|
3389
|
+
lines.push(" for (const __p of __emailPatterns) {");
|
|
3390
|
+
lines.push(" const __m = __p.re.exec(__local);");
|
|
3391
|
+
lines.push(" if (!__m) continue;");
|
|
3392
|
+
lines.push(" const __params = {};");
|
|
3393
|
+
lines.push(" for (let __i = 0; __i < __p.params.length; __i++) {");
|
|
3394
|
+
lines.push(" __params[__p.params[__i]] = __m[__i + 1];");
|
|
3395
|
+
lines.push(" }");
|
|
3396
|
+
lines.push(" const __mod = await __p.load();");
|
|
3397
|
+
lines.push(" if (typeof __mod.default !== \"function\") {");
|
|
3398
|
+
lines.push(" throw new Error(\"email handler at \" + __p.path + \" has no default export\");");
|
|
3399
|
+
lines.push(" }");
|
|
3400
|
+
lines.push(" return await __mod.default(message, env, ctx, { params: __params });");
|
|
3401
|
+
lines.push(" }");
|
|
3402
|
+
}
|
|
3403
|
+
if (email.defaultHandler) {
|
|
3404
|
+
const defaultPath = `${emailDir}/${email.defaultHandler}`;
|
|
3405
|
+
lines.push(" const __dmod = await __emailDefault();");
|
|
3406
|
+
lines.push(" if (typeof __dmod.default !== \"function\") {");
|
|
3407
|
+
lines.push(` throw new Error("email handler at " + ${JSON.stringify(defaultPath)} + " has no default export");`);
|
|
3408
|
+
lines.push(" }");
|
|
3409
|
+
lines.push(" return await __dmod.default(message, env, ctx, { params: {} });");
|
|
3410
|
+
} else {
|
|
3411
|
+
lines.push(" if (typeof message.setReject === \"function\") {");
|
|
3412
|
+
lines.push(" message.setReject(\"no handler matched recipient \\\"\" + __to + \"\\\" — add email/_default.ts to handle unmatched mail\");");
|
|
3413
|
+
lines.push(" }");
|
|
3414
|
+
}
|
|
3415
|
+
lines.push("}");
|
|
3416
|
+
lines.push("");
|
|
3417
|
+
}
|
|
3021
3418
|
if (options.migrationHandlerPath && (options.migrations?.length || auth)) {
|
|
3022
3419
|
const d1BindingName = options.bindingNames?.d1;
|
|
3023
3420
|
lines.push(`import { createMigrationHandler as __createMigrationHandler } from ${JSON.stringify(options.migrationHandlerPath)};`);
|
|
@@ -3136,6 +3533,8 @@ window.__vite_plugin_react_preamble_installed__ = true;
|
|
|
3136
3533
|
lines.push(`export const __VOID_BUILD_KEY = ${JSON.stringify(crypto.randomUUID())};`);
|
|
3137
3534
|
lines.push(`export const __VOID_DEV_TRIGGER_TOKEN = ${JSON.stringify(options.devTriggerToken ?? crypto.randomUUID())};`);
|
|
3138
3535
|
lines.push(`export const __VOID_ISR_REVALIDATE = ${JSON.stringify(mergedRevalidate)};`);
|
|
3536
|
+
lines.push(`export const __VOID_ISR_PAGES = ${JSON.stringify(isrPages)};`);
|
|
3537
|
+
lines.push(`export const __VOID_ISR_PATH_REVALIDATE = ${JSON.stringify(isrPathRevalidate)};`);
|
|
3139
3538
|
lines.push(`export const __VOID_ISR_DEPLOYMENT_ID = ${JSON.stringify(crypto.randomUUID())};`);
|
|
3140
3539
|
lines.push("");
|
|
3141
3540
|
lines.push(`export default app;`);
|
|
@@ -3540,7 +3939,7 @@ function compilePageRoutes(lines, scan, pages, options) {
|
|
|
3540
3939
|
lines.push(` }`);
|
|
3541
3940
|
lines.push(` const assetRes = await fetchPagesAsset(c);`);
|
|
3542
3941
|
lines.push(` if (assetRes.status !== 404) return assetRes;`);
|
|
3543
|
-
if ((options.nodeTarget
|
|
3942
|
+
if (!(options.nodeTarget !== true && options.dev !== true && options.managedDispatch === true) && options.fallbackRules?.length) emitFallbackRulesCheck(lines, options.fallbackRules, options.dev === true, " ", options.nodeTarget === true);
|
|
3544
3943
|
lines.push(` if (path.includes("/.")) {`);
|
|
3545
3944
|
lines.push(` return serveCustomErrorPage(c, 404, "Not Found");`);
|
|
3546
3945
|
lines.push(` }`);
|
|
@@ -3633,7 +4032,11 @@ ${fallthroughCode}
|
|
|
3633
4032
|
* remote mode (`__VOID_REMOTE`) and replace local bindings with
|
|
3634
4033
|
* proxy-backed versions.
|
|
3635
4034
|
*/
|
|
3636
|
-
function
|
|
4035
|
+
function deriveEmailRuntimePath(runtimeEnvPath) {
|
|
4036
|
+
return runtimeEnvPath.replace(/_?env(\.[^/]+)?$/, (_m, ext) => "email" + (ext ?? ""));
|
|
4037
|
+
}
|
|
4038
|
+
function compileWorkerEntry(options = {}) {
|
|
4039
|
+
const { hasQueues = false, remote, assetsDir = "assets", webSocketClasses = [], runtimeEnvPath = "void/_env", runtimeEmailPath, envSchemaModule, sandbox, serveSpaFallback = false, hasEmail = false, live, isr, notFound = "none", durableObjects = [] } = options;
|
|
3637
4040
|
const remotePath = remote?.remotePath;
|
|
3638
4041
|
const remoteBindingNames = JSON.stringify(remote?.bindingNames);
|
|
3639
4042
|
const createRemoteEnvCall = `createRemoteEnv(env${remote?.bindingNames ? `, ${remoteBindingNames}` : ""})`;
|
|
@@ -3649,10 +4052,13 @@ function compileWorkerEntry(hasQueues = false, remote, assetsDir = "assets", web
|
|
|
3649
4052
|
const liveRouteImport = hasLive ? ", VoidLiveStreamDurableObject" : "";
|
|
3650
4053
|
const liveRuntimeImport = hasLive ? `import { __setLiveBindingName } from "void/live";\n` : "";
|
|
3651
4054
|
const liveExport = hasLive ? liveClassName === "VoidLiveStreamDurableObject" ? `export { VoidLiveStreamDurableObject };\n__setLiveBindingName(${JSON.stringify(liveBindingName)});\n` : `export { VoidLiveStreamDurableObject as ${liveClassName} };\n__setLiveBindingName(${JSON.stringify(liveBindingName)});\n` : "";
|
|
4055
|
+
const durableObjectImports = durableObjects.map(({ filePath }, index) => `import __voidDurableObject${index} from ${JSON.stringify(filePath)};`).join("\n");
|
|
4056
|
+
const durableObjectExports = durableObjects.map(({ bindingName, className }, index) => `__voidDurableObject${index}.__bind(${JSON.stringify(bindingName)});\nexport const ${className} = __voidDurableObject${index}.class;`).join("\n");
|
|
3652
4057
|
const runtimeEnvImport = `import { withRuntimeEnv } from ${JSON.stringify(runtimeEnvPath)};\n`;
|
|
3653
4058
|
const remoteImport = remote ? `import { createRemoteEnv } from ${JSON.stringify(remote.remotePath)};\n` : "";
|
|
3654
4059
|
const envSchemaImport = envSchemaModule ? `import ${JSON.stringify(envSchemaModule.importPath)};\nimport { _validateEnvOnce } from ${JSON.stringify(envSchemaModule.helperPath)};\n` : "";
|
|
3655
4060
|
const envValidateCall = envSchemaModule ? " await _validateEnvOnce(env);\n" : "";
|
|
4061
|
+
const fetchEnvValidateCall = envSchemaModule ? " if (request.method !== \"POST\" || new URL(request.url).pathname !== \"/__void/prerender-paths\") await _validateEnvOnce(env);\n" : "";
|
|
3656
4062
|
const exactNames = isr ? INTERNAL_BINDING_EXACT_NAMES : [];
|
|
3657
4063
|
const prefixCheck = [...INTERNAL_BINDING_PREFIXES.map((p) => `prop.startsWith(${JSON.stringify(p)})`), ...exactNames.map((n) => `prop === ${JSON.stringify(n)}`)].join(" || ");
|
|
3658
4064
|
const filterBindingsHelper = `
|
|
@@ -3679,19 +4085,17 @@ function __filterInternalBindings(env) {
|
|
|
3679
4085
|
}
|
|
3680
4086
|
`;
|
|
3681
4087
|
const assetHelper = compileAssetFallbackHelper(assetsDir, serveSpaFallback, notFound);
|
|
3682
|
-
const isrImport = isr ? `import { handleIsr } from ${JSON.stringify(isr.runtimePath)};\nimport { __VOID_ISR_REVALIDATE, __VOID_ISR_DEPLOYMENT_ID } from 'virtual:void-routes';\n` : "";
|
|
4088
|
+
const isrImport = isr ? `import { handleIsr } from ${JSON.stringify(isr.runtimePath)};\nimport { __VOID_ISR_REVALIDATE, __VOID_ISR_PAGES, __VOID_ISR_PATH_REVALIDATE, __VOID_ISR_DEPLOYMENT_ID } from 'virtual:void-routes';\n` : "";
|
|
3683
4089
|
const isrEnvCapture = isr ? ` env.__VOID_ISR_DEPLOYMENT_ID ??= __VOID_ISR_DEPLOYMENT_ID;\n env.__VOID_ISR_HOST = new URL(request.url).hostname;\n` : "";
|
|
3684
4090
|
const isrDeploymentStamp = isr ? ` env.__VOID_ISR_DEPLOYMENT_ID ??= __VOID_ISR_DEPLOYMENT_ID;\n` : "";
|
|
3685
4091
|
const renderBlock = isr ? ` const __render = async (req) => serveWithAssets(req, env, await app.fetch(req, userEnv, ctx));
|
|
3686
|
-
if (env.ISR_CACHE) {
|
|
3687
|
-
const __isr = await handleIsr(request, env, ctx, { revalidate: __VOID_ISR_REVALIDATE, deploymentId: __VOID_ISR_DEPLOYMENT_ID }, __render);
|
|
4092
|
+
if (env.ISR_CACHE && request.headers.get("upgrade")?.toLowerCase() !== "websocket") {
|
|
4093
|
+
const __isr = await handleIsr(request, env, ctx, { revalidate: __VOID_ISR_REVALIDATE, pages: __VOID_ISR_PAGES, pathRevalidate: __VOID_ISR_PATH_REVALIDATE, deploymentId: __VOID_ISR_DEPLOYMENT_ID, queryAllowlist: ${JSON.stringify(isr?.queryAllowlist)} }, __render);
|
|
3688
4094
|
if (__isr) return __isr;
|
|
3689
4095
|
}
|
|
3690
4096
|
return __render(request);` : ` return serveWithAssets(request, env, await app.fetch(request, userEnv, ctx));`;
|
|
3691
4097
|
const fetchHandler = remotePath ? `async (request, env, ctx) => {
|
|
3692
|
-
${
|
|
3693
|
-
if (ws) return ws;
|
|
3694
|
-
if (env.__VOID_REMOTE === "1") env = ${createRemoteEnvCall};
|
|
4098
|
+
${fetchEnvValidateCall} if (env.__VOID_REMOTE === "1") env = ${createRemoteEnvCall};
|
|
3695
4099
|
${isrEnvCapture} return __withRawEnv(env, () => {
|
|
3696
4100
|
const userEnv = __filterInternalBindings(env);
|
|
3697
4101
|
return withRuntimeEnv(env, async () => {
|
|
@@ -3701,9 +4105,7 @@ ${renderBlock}
|
|
|
3701
4105
|
});
|
|
3702
4106
|
});
|
|
3703
4107
|
}` : `async (request, env, ctx) => {
|
|
3704
|
-
${
|
|
3705
|
-
if (ws) return ws;
|
|
3706
|
-
${isrEnvCapture} return __withRawEnv(env, () => {
|
|
4108
|
+
${fetchEnvValidateCall}${isrEnvCapture} return __withRawEnv(env, () => {
|
|
3707
4109
|
const userEnv = __filterInternalBindings(env);
|
|
3708
4110
|
return withRuntimeEnv(env, async () => {
|
|
3709
4111
|
const internal = await __handleInternal(request, env, ctx);
|
|
@@ -3740,11 +4142,40 @@ ${isrDeploymentStamp} const userEnv = __filterInternalBindings(env);
|
|
|
3740
4142
|
${envValidateCall}${isrDeploymentStamp} const userEnv = __filterInternalBindings(env);
|
|
3741
4143
|
return withRuntimeEnv(env, () => scheduled(controller, userEnv, ctx));
|
|
3742
4144
|
}`;
|
|
3743
|
-
|
|
3744
|
-
|
|
4145
|
+
const emailImport = hasEmail ? ", __emailHandler" : "";
|
|
4146
|
+
const emailRuntimePath = runtimeEmailPath ?? deriveEmailRuntimePath(runtimeEnvPath);
|
|
4147
|
+
const emailProxyImport = hasEmail ? `import { createMessageProxy as __createMessageProxy, enactEmailActions as __enactEmailActions, isForwardableEmailMessage as __isForwardableEmailMessage } from ${JSON.stringify(emailRuntimePath)};\n` : "";
|
|
4148
|
+
const emailHandler = hasEmail ? remotePath ? `async function handleEmail(envelope, env, ctx) {
|
|
4149
|
+
${envValidateCall} if (env.__VOID_REMOTE === "1") env = ${createRemoteEnvCall};
|
|
4150
|
+
const userEnv = __filterInternalBindings(env);
|
|
4151
|
+
const __slug = typeof env.__VOID_PROJECT_SLUG === "string" && env.__VOID_PROJECT_SLUG.length > 0 ? env.__VOID_PROJECT_SLUG : undefined;
|
|
4152
|
+
const { message, getActions } = __createMessageProxy(envelope, { slug: __slug });
|
|
4153
|
+
await __withRawEnv(env, () => withRuntimeEnv(env, () => __emailHandler(message, userEnv, ctx, { slug: __slug })));
|
|
4154
|
+
const __actions = getActions();
|
|
4155
|
+
if (__isForwardableEmailMessage(envelope)) await __enactEmailActions(envelope, __actions);
|
|
4156
|
+
return __actions;
|
|
4157
|
+
}` : `async function handleEmail(envelope, env, ctx) {
|
|
4158
|
+
${envValidateCall} const userEnv = __filterInternalBindings(env);
|
|
4159
|
+
const __slug = typeof env.__VOID_PROJECT_SLUG === "string" && env.__VOID_PROJECT_SLUG.length > 0 ? env.__VOID_PROJECT_SLUG : undefined;
|
|
4160
|
+
const { message, getActions } = __createMessageProxy(envelope, { slug: __slug });
|
|
4161
|
+
await __withRawEnv(env, () => withRuntimeEnv(env, () => __emailHandler(message, userEnv, ctx, { slug: __slug })));
|
|
4162
|
+
const __actions = getActions();
|
|
4163
|
+
if (__isForwardableEmailMessage(envelope)) await __enactEmailActions(envelope, __actions);
|
|
4164
|
+
return __actions;
|
|
4165
|
+
}` : "";
|
|
4166
|
+
const entryImport = `import { WorkerEntrypoint } from "cloudflare:workers";\n`;
|
|
4167
|
+
const fetchDeclaration = `const __voidFetch = ${fetchHandler};`;
|
|
4168
|
+
const entryClass = `export default class extends WorkerEntrypoint {
|
|
4169
|
+
async fetch(request) { return __voidFetch(request, this.env, this.ctx); }
|
|
4170
|
+
async scheduled(controller) { return handleScheduled(controller, this.env, this.ctx); }
|
|
4171
|
+
${hasQueues ? ` async queue(batch) { return __voidQueue(batch, this.env, this.ctx); }\n` : ""}${hasEmail ? ` async email(envelope) { return handleEmail(envelope, this.env, this.ctx); }\n` : ""}}`;
|
|
4172
|
+
if (hasQueues) return `${sandboxImport}${entryImport}${liveRuntimeImport}import app, { scheduled, __voidCollectPrerenderPaths, __voidHandleInternalRoute, __withRawEnv, __processQueue${emailImport}${webSocketClasses.length > 0 ? `, ${webSocketClasses.join(", ")}` : ""}${liveRouteImport} } from 'virtual:void-routes';
|
|
4173
|
+
${durableObjectImports}\n${runtimeEnvImport}${emailProxyImport}${envSchemaImport}${remoteImport}${isrImport}${filterBindingsHelper}${assetHelper}
|
|
3745
4174
|
${internalRouteHelper}
|
|
4175
|
+
${fetchDeclaration}
|
|
3746
4176
|
${scheduledHandler}
|
|
3747
|
-
|
|
4177
|
+
${emailHandler}
|
|
4178
|
+
async function __voidQueue(batch, env, ctx) {
|
|
3748
4179
|
${envValidateCall}${remotePath ? ` if (env.__VOID_REMOTE === "1") env = ${createRemoteEnvCall};\n` : ""}${isrDeploymentStamp} const userEnv = __filterInternalBindings(env);
|
|
3749
4180
|
const messages = [...batch.messages].map(m => ({
|
|
3750
4181
|
id: m.id, timestamp: m.timestamp.toISOString(),
|
|
@@ -3768,15 +4199,19 @@ ${envValidateCall}${remotePath ? ` if (env.__VOID_REMOTE === "1") env = ${creat
|
|
|
3768
4199
|
${webSocketClasses.map((name) => `export { ${name} };`).join("\n")}
|
|
3769
4200
|
${liveExport}
|
|
3770
4201
|
${sandboxExport}
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
4202
|
+
${durableObjectExports}
|
|
4203
|
+
${entryClass}`;
|
|
4204
|
+
return `${sandboxImport}${entryImport}${liveRuntimeImport}import app, { scheduled, __voidCollectPrerenderPaths, __voidHandleInternalRoute, __withRawEnv${emailImport}${webSocketClasses.length > 0 ? `, ${webSocketClasses.join(", ")}` : ""}${liveRouteImport} } from 'virtual:void-routes';
|
|
4205
|
+
${durableObjectImports}\n${runtimeEnvImport}${emailProxyImport}${envSchemaImport}${remoteImport}${isrImport}${filterBindingsHelper}${assetHelper}
|
|
3774
4206
|
${internalRouteHelper}
|
|
4207
|
+
${fetchDeclaration}
|
|
3775
4208
|
${scheduledHandler}
|
|
4209
|
+
${emailHandler}
|
|
3776
4210
|
${webSocketClasses.map((name) => `export { ${name} };`).join("\n")}
|
|
3777
4211
|
${liveExport}
|
|
3778
4212
|
${sandboxExport}
|
|
3779
|
-
|
|
4213
|
+
${durableObjectExports}
|
|
4214
|
+
${entryClass}`;
|
|
3780
4215
|
}
|
|
3781
4216
|
/**
|
|
3782
4217
|
* Generate the app module — exports the Hono app with static asset serving.
|
|
@@ -3792,11 +4227,17 @@ export default { fetch: ${fetchHandler}, scheduled: handleScheduled };`;
|
|
|
3792
4227
|
function compileNodeApp(target, honoPath, envSchemaModule) {
|
|
3793
4228
|
const staticImport = target === "bun" ? `import { serveStatic } from "hono/bun";` : target === "deno" ? `import { serveStatic } from "hono/deno";` : `import { serveStatic } from "@hono/node-server/serve-static";`;
|
|
3794
4229
|
const envSchemaImport = envSchemaModule ? `import ${JSON.stringify(envSchemaModule.importPath)};\nimport { _validateEnvOnce } from ${JSON.stringify(envSchemaModule.helperPath)};\n` : "";
|
|
3795
|
-
const envMiddleware = envSchemaModule ? `app.use("*", async (c, next) => { await _validateEnvOnce(${target === "deno" ? "Deno.env.toObject()" : "process.env"}); return next(); });\n` : "";
|
|
4230
|
+
const envMiddleware = envSchemaModule ? `app.use("*", async (c, next) => { if (c.req.method !== "POST" || c.req.path !== "/__void/prerender-paths") await _validateEnvOnce(${target === "deno" ? "Deno.env.toObject()" : "process.env"}); return next(); });\n` : "";
|
|
3796
4231
|
return `${staticImport}
|
|
4232
|
+
import { fileURLToPath } from "node:url";
|
|
3797
4233
|
import { Hono } from ${JSON.stringify(honoPath)};
|
|
3798
4234
|
import innerApp, { __voidCollectPrerenderPaths } from "virtual:void-routes";
|
|
3799
4235
|
${envSchemaImport}
|
|
4236
|
+
// Resolved by nodeTargetPlugin for this emitted chunk, including shared chunks.
|
|
4237
|
+
const clientRoot = fileURLToPath(import.meta.voidClientDirectory);
|
|
4238
|
+
const assetApp = new Hono();
|
|
4239
|
+
assetApp.get("*", serveStatic({ root: clientRoot }));
|
|
4240
|
+
const assets = { fetch: (request) => assetApp.fetch(request) };
|
|
3800
4241
|
const app = new Hono();
|
|
3801
4242
|
${envMiddleware}app.post("/__void/prerender-paths", async (c) => {
|
|
3802
4243
|
const __expected = c.env?.__VOID_PROXY_TOKEN;
|
|
@@ -3807,8 +4248,8 @@ ${envMiddleware}app.post("/__void/prerender-paths", async (c) => {
|
|
|
3807
4248
|
const paths = await __voidCollectPrerenderPaths(c.req.raw);
|
|
3808
4249
|
return c.json({ paths });
|
|
3809
4250
|
});
|
|
3810
|
-
app.
|
|
3811
|
-
app.all("*", (c) => innerApp.fetch(c.req.raw));
|
|
4251
|
+
app.get("/assets/*", (c) => assets.fetch(c.req.raw));
|
|
4252
|
+
app.all("*", (c) => innerApp.fetch(c.req.raw, { ...c.env, ASSETS: assets }));
|
|
3812
4253
|
export default app;`;
|
|
3813
4254
|
}
|
|
3814
4255
|
/**
|
|
@@ -4252,6 +4693,7 @@ const RESOLVE_ID_FILTER = /^(virtual:void-(routes|client-worker(?::(react|vue|sv
|
|
|
4252
4693
|
const LOAD_ID_FILTER = /^virtual:void-(routes|client-worker(?::(react|vue|svelte|solid))?|client-browser(?::(react|vue|svelte|solid))?)$/;
|
|
4253
4694
|
function routingPlugin(root, options) {
|
|
4254
4695
|
let scan = null;
|
|
4696
|
+
let routeEnvironment = "prod";
|
|
4255
4697
|
let ssr = null;
|
|
4256
4698
|
let authConfigPath = null;
|
|
4257
4699
|
const paths = readProjectPaths(root);
|
|
@@ -4259,6 +4701,7 @@ function routingPlugin(root, options) {
|
|
|
4259
4701
|
const middlewareDir = paths.middlewareDir;
|
|
4260
4702
|
const jobsDir = paths.cronsDir;
|
|
4261
4703
|
const queuesDir = paths.queuesDir;
|
|
4704
|
+
const emailDir = paths.emailDir;
|
|
4262
4705
|
const pagesDir = paths.pagesDir;
|
|
4263
4706
|
const ssrDir = paths.ssrDir;
|
|
4264
4707
|
const authConfigPaths = new Set(paths.authConfigCandidates.map((path) => normalizePath(path)));
|
|
@@ -4267,9 +4710,14 @@ function routingPlugin(root, options) {
|
|
|
4267
4710
|
const normalizedMiddlewareDir = normalizePath(middlewareDir);
|
|
4268
4711
|
const normalizedJobsDir = normalizePath(jobsDir);
|
|
4269
4712
|
const normalizedQueuesDir = normalizePath(queuesDir);
|
|
4713
|
+
const normalizedEmailDir = normalizePath(emailDir);
|
|
4270
4714
|
const normalizedPagesDir = normalizePath(pagesDir);
|
|
4271
4715
|
const normalizedSsrDir = normalizePath(ssrDir);
|
|
4272
4716
|
const ssrEntryAbsPaths = new Set([...SSR_SERVER_ENTRY_RELATIVE_PATHS, ...SSR_CLIENT_ENTRY_RELATIVE_PATHS].map((path) => normalizePath(join(ssrDir, path.split("/").pop()))));
|
|
4717
|
+
function hasEmailHandlers() {
|
|
4718
|
+
const email = scan?.email;
|
|
4719
|
+
return Boolean(email && (email.addresses.length > 0 || email.defaultHandler));
|
|
4720
|
+
}
|
|
4273
4721
|
function isInDirectory(path, directory) {
|
|
4274
4722
|
return path === directory || path.startsWith(directory + "/");
|
|
4275
4723
|
}
|
|
@@ -4286,7 +4734,8 @@ function routingPlugin(root, options) {
|
|
|
4286
4734
|
async function rescan() {
|
|
4287
4735
|
scan = await scanRoutes(root, {
|
|
4288
4736
|
output: options.output,
|
|
4289
|
-
paths
|
|
4737
|
+
paths,
|
|
4738
|
+
environment: routeEnvironment
|
|
4290
4739
|
});
|
|
4291
4740
|
authConfigPath = findVoidAuthConfig(root, paths);
|
|
4292
4741
|
const entries = validateSsrEntries(root, paths);
|
|
@@ -4327,16 +4776,20 @@ function routingPlugin(root, options) {
|
|
|
4327
4776
|
responsePath: resolveFile("#self/response"),
|
|
4328
4777
|
handlerPath: resolveFile("#self/handler"),
|
|
4329
4778
|
runtimeEnvPath: resolveFile("#self/_env"),
|
|
4779
|
+
runtimeEmailPath: resolveFile("#self/email"),
|
|
4780
|
+
emailDir,
|
|
4330
4781
|
projectRoot: root,
|
|
4331
4782
|
homeDir: homedir(),
|
|
4332
4783
|
webSocketRuntimePath: resolveFile("#self/runtime/ws-server"),
|
|
4333
4784
|
liveRuntimePath: resolveFile("#self/runtime/live-server"),
|
|
4334
4785
|
hasLive: options.live !== void 0,
|
|
4786
|
+
webSocketTombstones: options.websocketTombstones,
|
|
4335
4787
|
reactRefresh: false,
|
|
4336
4788
|
dev: false,
|
|
4337
4789
|
devTriggerToken: options.devTriggerToken,
|
|
4338
4790
|
auth: null,
|
|
4339
4791
|
nodeTarget: !!options.target,
|
|
4792
|
+
managedDispatch: false,
|
|
4340
4793
|
explicitPrerenderPaths: options.prerenderPaths,
|
|
4341
4794
|
bindingHandlerPath: options.target ? void 0 : resolveFile("#self/remote/binding-handler"),
|
|
4342
4795
|
bindingNames: options.bindingNames
|
|
@@ -4364,7 +4817,7 @@ function routingPlugin(root, options) {
|
|
|
4364
4817
|
const config = readConfig(root);
|
|
4365
4818
|
const dialect = getDatabaseDialect(config);
|
|
4366
4819
|
compileOptions.auth = {
|
|
4367
|
-
authRuntimePath: dialect === "postgresql" ? join(runtimeDir, "better-auth-pg.mjs") : join(runtimeDir, "better-auth.mjs"),
|
|
4820
|
+
authRuntimePath: dialect === "postgresql" ? join(runtimeDir, "better-auth-pg.mjs") : dialect === "mysql" ? join(runtimeDir, "better-auth-mysql.mjs") : join(runtimeDir, "better-auth.mjs"),
|
|
4368
4821
|
authConfigPath,
|
|
4369
4822
|
authDatabasePath: null,
|
|
4370
4823
|
authSchemaPath: null,
|
|
@@ -4379,7 +4832,10 @@ function routingPlugin(root, options) {
|
|
|
4379
4832
|
providers: compileOptions.auth.providers,
|
|
4380
4833
|
userConfig: await loadVoidAuthConfig(compileOptions.auth.authConfigPath)
|
|
4381
4834
|
};
|
|
4382
|
-
const env =
|
|
4835
|
+
const env = {
|
|
4836
|
+
...resolvedConfig?.command === "serve" ? loadLocalEnv(root) : {},
|
|
4837
|
+
...process.env
|
|
4838
|
+
};
|
|
4383
4839
|
const schemaPath = join(outDir, "better-auth-schema.ts");
|
|
4384
4840
|
const databasePath = join(outDir, "better-auth-db.ts");
|
|
4385
4841
|
writeFileIfChanged(schemaPath, generateVoidAuthDrizzleSchema(authRuntime, env));
|
|
@@ -4393,6 +4849,8 @@ function routingPlugin(root, options) {
|
|
|
4393
4849
|
}
|
|
4394
4850
|
let resolvedConfig = null;
|
|
4395
4851
|
let isrRevalidate;
|
|
4852
|
+
let isrPages;
|
|
4853
|
+
let isrPathRevalidate;
|
|
4396
4854
|
function resolveAuthClientPath(config) {
|
|
4397
4855
|
if (config.plugins.some((plugin) => plugin.name === "void-react:pages")) return explicitAuthClientPaths.react;
|
|
4398
4856
|
if (config.plugins.some((plugin) => plugin.name === "void-vue:pages")) return explicitAuthClientPaths.vue;
|
|
@@ -4473,11 +4931,20 @@ function routingPlugin(root, options) {
|
|
|
4473
4931
|
if (options.target) {
|
|
4474
4932
|
writeFileIfChanged(join(outDir, "app.ts"), compileNodeApp(options.target, compileOptions.honoPath, getEnvSchemaModule()));
|
|
4475
4933
|
writeFileIfChanged(join(outDir, "index.ts"), compileNodeServer(options.target));
|
|
4476
|
-
} else writeFileIfChanged(join(outDir, "entry.ts"), compileWorkerEntry(
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4934
|
+
} else writeFileIfChanged(join(outDir, "entry.ts"), compileWorkerEntry({
|
|
4935
|
+
remote,
|
|
4936
|
+
webSocketClasses: options.websocketTombstones,
|
|
4937
|
+
runtimeEnvPath: compileOptions.runtimeEnvPath,
|
|
4938
|
+
runtimeEmailPath: compileOptions.runtimeEmailPath,
|
|
4939
|
+
envSchemaModule: getEnvSchemaModule(),
|
|
4940
|
+
sandbox: options.hasSandbox ? {
|
|
4941
|
+
bindingName: options.sandboxBindingName,
|
|
4942
|
+
className: options.sandboxClassName,
|
|
4943
|
+
runtimePath: sandboxRuntimePath
|
|
4944
|
+
} : false,
|
|
4945
|
+
live: options.live,
|
|
4946
|
+
durableObjects: options.durableObjects
|
|
4947
|
+
}));
|
|
4481
4948
|
return {
|
|
4482
4949
|
name: "void:routing",
|
|
4483
4950
|
enforce: "pre",
|
|
@@ -4493,6 +4960,8 @@ function routingPlugin(root, options) {
|
|
|
4493
4960
|
}
|
|
4494
4961
|
},
|
|
4495
4962
|
config(_, env) {
|
|
4963
|
+
routeEnvironment = env.command === "serve" && !env.isPreview ? "dev" : "prod";
|
|
4964
|
+
compileOptions.managedDispatch = !options.target && env.command === "build" && Boolean(process.env.VOID_DEPLOY_PROJECT_ID);
|
|
4496
4965
|
if (env.command === "serve" && options.isAuthEnabled()) return { resolve: { alias: [
|
|
4497
4966
|
"client",
|
|
4498
4967
|
"react",
|
|
@@ -4526,11 +4995,11 @@ function routingPlugin(root, options) {
|
|
|
4526
4995
|
if (!options.target) {
|
|
4527
4996
|
const migrationsDir = paths.migrationsDir;
|
|
4528
4997
|
if (existsSync(migrationsDir) || compileOptions.auth) {
|
|
4529
|
-
const { collectMigrations } = await import("./validate-
|
|
4530
|
-
const { buildMigrationPlanBundle } = await import("./validate-
|
|
4998
|
+
const { collectMigrations } = await import("./validate-Bihr8WBi.mjs").then((n) => n.l);
|
|
4999
|
+
const { buildMigrationPlanBundle } = await import("./validate-Bihr8WBi.mjs").then((n) => n.s);
|
|
4531
5000
|
const migrations = existsSync(migrationsDir) ? collectMigrations(migrationsDir) : [];
|
|
4532
5001
|
const dialect = getDatabaseDialect(readConfig(root));
|
|
4533
|
-
compileOptions.migrationHandlerPath = resolveFile(dialect === "postgresql" ? "#self/runtime/migration-handler-pg" : "#self/runtime/migration-handler");
|
|
5002
|
+
compileOptions.migrationHandlerPath = resolveFile(dialect === "postgresql" ? "#self/runtime/migration-handler-pg" : dialect === "mysql" ? "#self/runtime/migration-handler-mysql" : "#self/runtime/migration-handler");
|
|
4534
5003
|
compileOptions.migrations = migrations;
|
|
4535
5004
|
compileOptions.migrationPlanBundle = dialect === "sqlite" ? buildMigrationPlanBundle(migrations) : void 0;
|
|
4536
5005
|
compileOptions.migrationDialect = dialect;
|
|
@@ -4540,15 +5009,37 @@ function routingPlugin(root, options) {
|
|
|
4540
5009
|
writeFileIfChanged(join(outDir, "app.ts"), compileNodeApp(options.target, compileOptions.honoPath, getEnvSchemaModule()));
|
|
4541
5010
|
writeFileIfChanged(join(outDir, "index.ts"), compileNodeServer(options.target));
|
|
4542
5011
|
} else {
|
|
4543
|
-
const
|
|
5012
|
+
const buildConfig = readConfig(root);
|
|
5013
|
+
const merged = collectRevalidate(buildConfig, scan.pages);
|
|
5014
|
+
const configuredRevalidate = buildConfig.routing?.revalidate;
|
|
4544
5015
|
const emitIsr = !options.target && resolvedConfig?.command === "build" && !process.env.VOID_DEPLOY_PROJECT_ID && hasRevalidate(merged);
|
|
4545
5016
|
isrRevalidate = emitIsr ? merged : void 0;
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
} :
|
|
5017
|
+
isrPages = emitIsr ? collectPages(scan.pages, configuredRevalidate) : void 0;
|
|
5018
|
+
isrPathRevalidate = emitIsr && configuredRevalidate && typeof configuredRevalidate === "object" ? configuredRevalidate : void 0;
|
|
5019
|
+
const isr = emitIsr ? {
|
|
5020
|
+
runtimePath: resolveFile("@void/isr/runtime"),
|
|
5021
|
+
queryAllowlist: buildConfig.routing?.revalidateQueryAllowlist
|
|
5022
|
+
} : void 0;
|
|
5023
|
+
writeFileIfChanged(join(outDir, "entry.ts"), compileWorkerEntry({
|
|
5024
|
+
hasQueues: scan.queues.length > 0,
|
|
5025
|
+
remote,
|
|
5026
|
+
assetsDir: resolvedConfig?.build.assetsDir,
|
|
5027
|
+
webSocketClasses: [...(scan.websockets ?? []).map((route) => route.className), ...options.websocketTombstones ?? []],
|
|
5028
|
+
runtimeEnvPath: compileOptions.runtimeEnvPath,
|
|
5029
|
+
runtimeEmailPath: compileOptions.runtimeEmailPath,
|
|
5030
|
+
envSchemaModule: getEnvSchemaModule(),
|
|
5031
|
+
sandbox: options.hasSandbox ? {
|
|
5032
|
+
bindingName: options.sandboxBindingName,
|
|
5033
|
+
className: options.sandboxClassName,
|
|
5034
|
+
runtimePath: sandboxRuntimePath
|
|
5035
|
+
} : false,
|
|
5036
|
+
hasEmail: hasEmailHandlers(),
|
|
5037
|
+
serveSpaFallback: shouldServeSpaFallback(),
|
|
5038
|
+
live: options.live,
|
|
5039
|
+
isr,
|
|
5040
|
+
notFound: currentNotFoundHandling(),
|
|
5041
|
+
durableObjects: options.durableObjects
|
|
5042
|
+
}));
|
|
4552
5043
|
}
|
|
4553
5044
|
},
|
|
4554
5045
|
resolveId: {
|
|
@@ -4573,14 +5064,14 @@ function routingPlugin(root, options) {
|
|
|
4573
5064
|
}
|
|
4574
5065
|
if (id !== VIRTUAL_ROUTES_ID) return;
|
|
4575
5066
|
if (!scan) await rescan();
|
|
4576
|
-
return compileRouteTable(scan, routesDir, middlewareDir, jobsDir, queuesDir, ssr, compileOptions, getPagesCompileOptions(), isrRevalidate);
|
|
5067
|
+
return compileRouteTable(scan, routesDir, middlewareDir, jobsDir, queuesDir, ssr, compileOptions, getPagesCompileOptions(), isrRevalidate, isrPages, isrPathRevalidate);
|
|
4577
5068
|
}
|
|
4578
5069
|
},
|
|
4579
5070
|
configureServer(devServer) {
|
|
4580
5071
|
const watcher = devServer.watcher;
|
|
4581
5072
|
const handleFileChange = async (path, event) => {
|
|
4582
5073
|
const normalizedPath = normalizePath(path);
|
|
4583
|
-
const sourceConventionChanged = isInDirectory(normalizedPath, normalizedRoutesDir) || isInDirectory(normalizedPath, normalizedMiddlewareDir) || isInDirectory(normalizedPath, normalizedJobsDir) || isInDirectory(normalizedPath, normalizedQueuesDir) || isInDirectory(normalizedPath, normalizedPagesDir) || isPotentialAuthConfigPath(normalizedPath) || isPotentialEnvFilePath(normalizedPath);
|
|
5074
|
+
const sourceConventionChanged = isInDirectory(normalizedPath, normalizedRoutesDir) || isInDirectory(normalizedPath, normalizedMiddlewareDir) || isInDirectory(normalizedPath, normalizedJobsDir) || isInDirectory(normalizedPath, normalizedQueuesDir) || isInDirectory(normalizedPath, normalizedEmailDir) || isInDirectory(normalizedPath, normalizedPagesDir) || isPotentialAuthConfigPath(normalizedPath) || isPotentialEnvFilePath(normalizedPath);
|
|
4584
5075
|
if (!sourceConventionChanged && !isInDirectory(normalizedPath, normalizedSsrDir) && !isPotentialEnvFilePath(normalizedPath)) return;
|
|
4585
5076
|
if (!sourceConventionChanged && isInDirectory(normalizedPath, normalizedSsrDir) && !ssrEntryAbsPaths.has(normalizedPath)) return;
|
|
4586
5077
|
await rescan();
|
|
@@ -4595,11 +5086,26 @@ function routingPlugin(root, options) {
|
|
|
4595
5086
|
if (options.target) {
|
|
4596
5087
|
writeFileIfChanged(join(outDir, "app.ts"), compileNodeApp(options.target, compileOptions.honoPath, getEnvSchemaModule()));
|
|
4597
5088
|
writeFileIfChanged(join(outDir, "index.ts"), compileNodeServer(options.target));
|
|
4598
|
-
} else writeFileIfChanged(join(outDir, "entry.ts"), compileWorkerEntry(
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
5089
|
+
} else writeFileIfChanged(join(outDir, "entry.ts"), compileWorkerEntry({
|
|
5090
|
+
hasQueues: scan.queues.length > 0,
|
|
5091
|
+
remote,
|
|
5092
|
+
assetsDir: resolvedConfig?.build.assetsDir,
|
|
5093
|
+
webSocketClasses: [...(scan.websockets ?? []).map((route) => route.className), ...options.websocketTombstones ?? []],
|
|
5094
|
+
runtimeEnvPath: compileOptions.runtimeEnvPath,
|
|
5095
|
+
runtimeEmailPath: compileOptions.runtimeEmailPath,
|
|
5096
|
+
envSchemaModule: getEnvSchemaModule(),
|
|
5097
|
+
sandbox: options.hasSandbox ? {
|
|
5098
|
+
bindingName: options.sandboxBindingName,
|
|
5099
|
+
className: options.sandboxClassName,
|
|
5100
|
+
runtimePath: sandboxRuntimePath
|
|
5101
|
+
} : false,
|
|
5102
|
+
hasEmail: hasEmailHandlers(),
|
|
5103
|
+
serveSpaFallback: shouldServeSpaFallback(),
|
|
5104
|
+
live: options.live,
|
|
5105
|
+
isr: void 0,
|
|
5106
|
+
notFound: currentNotFoundHandling(),
|
|
5107
|
+
durableObjects: options.durableObjects
|
|
5108
|
+
}));
|
|
4603
5109
|
const structural = event !== "change";
|
|
4604
5110
|
const pageManifestChanged = isInDirectory(normalizedPath, normalizedPagesDir) && (structural || normalizedPath.endsWith(".md"));
|
|
4605
5111
|
for (const env of Object.values(devServer.environments)) {
|
|
@@ -4657,6 +5163,13 @@ function routingPlugin(root, options) {
|
|
|
4657
5163
|
* The token is local to the project and only honored by a worker bound to
|
|
4658
5164
|
* localhost; treat it like the rest of `.void/` — disposable scratch state,
|
|
4659
5165
|
* safe to remove manually if desired.
|
|
5166
|
+
*
|
|
5167
|
+
* The file is owner-only (0600). It is the one credential the dev-inbox
|
|
5168
|
+
* routes accept, and loopback is reachable by every account on the host,
|
|
5169
|
+
* so a default-umask 0644 file would hand any other local user the raw MIME,
|
|
5170
|
+
* the DELETE, and the capture endpoint. A file persisted by an earlier
|
|
5171
|
+
* release is tightened in place, never rotated. Windows has no group/other
|
|
5172
|
+
* bits — `mode` and `chmod` only toggle write there — so it is left alone.
|
|
4660
5173
|
*/
|
|
4661
5174
|
/**
|
|
4662
5175
|
* Best-effort detection of `vite build` (and `vite preview`) so we can skip
|
|
@@ -4671,6 +5184,7 @@ function isViteBuildOrPreview() {
|
|
|
4671
5184
|
const subcommand = process.argv[2];
|
|
4672
5185
|
return subcommand === "build" || subcommand === "preview";
|
|
4673
5186
|
}
|
|
5187
|
+
const DEV_TRIGGER_TOKEN_FILE_MODE = 384;
|
|
4674
5188
|
function getOrCreateDevTriggerToken(root) {
|
|
4675
5189
|
const tokenPath = join(root, ".void", "dev-trigger-token");
|
|
4676
5190
|
const readExisting = () => {
|
|
@@ -4681,12 +5195,21 @@ function getOrCreateDevTriggerToken(root) {
|
|
|
4681
5195
|
return;
|
|
4682
5196
|
}
|
|
4683
5197
|
};
|
|
5198
|
+
const tightenExisting = () => {
|
|
5199
|
+
if (process.platform === "win32") return;
|
|
5200
|
+
try {
|
|
5201
|
+
if ((statSync(tokenPath).mode & 63) !== 0) chmodSync(tokenPath, DEV_TRIGGER_TOKEN_FILE_MODE);
|
|
5202
|
+
} catch {}
|
|
5203
|
+
};
|
|
4684
5204
|
const existing = readExisting();
|
|
4685
|
-
if (existing)
|
|
5205
|
+
if (existing) {
|
|
5206
|
+
tightenExisting();
|
|
5207
|
+
return existing;
|
|
5208
|
+
}
|
|
4686
5209
|
mkdirSync(join(root, ".void"), { recursive: true });
|
|
4687
5210
|
const fresh = crypto.randomUUID();
|
|
4688
5211
|
try {
|
|
4689
|
-
const fd = openSync(tokenPath, "wx");
|
|
5212
|
+
const fd = openSync(tokenPath, "wx", DEV_TRIGGER_TOKEN_FILE_MODE);
|
|
4690
5213
|
try {
|
|
4691
5214
|
writeSync(fd, fresh);
|
|
4692
5215
|
} finally {
|
|
@@ -4770,7 +5293,7 @@ function generateClassATriggerWrapper(root, framework, original, isBuild, assets
|
|
|
4770
5293
|
const outDir = join(root, ".void");
|
|
4771
5294
|
mkdirSync(outDir, { recursive: true });
|
|
4772
5295
|
const wrapperPath = join(outDir, `${framework}-trigger-wrapper.ts`);
|
|
4773
|
-
|
|
5296
|
+
const body = isBuild ? `// @ts-nocheck — Auto-generated by Void for vite build. Do NOT edit.
|
|
4774
5297
|
import original from ${JSON.stringify(original)};
|
|
4775
5298
|
|
|
4776
5299
|
export default {
|
|
@@ -4792,7 +5315,8 @@ export default {
|
|
|
4792
5315
|
return original.fetch(request, env, ctx);
|
|
4793
5316
|
},
|
|
4794
5317
|
};
|
|
4795
|
-
|
|
5318
|
+
`;
|
|
5319
|
+
writeFileIfChanged(wrapperPath, body);
|
|
4796
5320
|
return wrapperPath;
|
|
4797
5321
|
}
|
|
4798
5322
|
/** Generate a worker entry for vinext Pages Router projects. */
|
|
@@ -4850,16 +5374,49 @@ function hasBinding(list, name) {
|
|
|
4850
5374
|
/**
|
|
4851
5375
|
* Decide whether to inject a Workers AI binding into the built wrangler config.
|
|
4852
5376
|
*
|
|
4853
|
-
*
|
|
4854
|
-
*
|
|
5377
|
+
* Builds use the production binding. During dev, a project explicitly saved
|
|
5378
|
+
* with the direct Cloudflare destination uses Cloudflare's remote binding;
|
|
5379
|
+
* managed and unsaved projects keep using the Void HTTPS proxy.
|
|
4855
5380
|
*
|
|
4856
5381
|
* `!resolvedAi` is load-bearing: mergeBindings' return is defu-merged over the
|
|
4857
5382
|
* resolved root-wrangler config and wins, so skipping when the user already
|
|
4858
5383
|
* declared an `ai` binding avoids clobbering theirs. `!resultAi` is harmless
|
|
4859
5384
|
* defense-in-depth (nothing else in mergeBindings sets `result.ai`).
|
|
4860
5385
|
*/
|
|
4861
|
-
function shouldBindWorkersAi(command, needsAI, resolvedAi, resultAi) {
|
|
4862
|
-
return needsAI && command === "build" && !resultAi && !resolvedAi;
|
|
5386
|
+
function shouldBindWorkersAi(command, needsAI, resolvedAi, resultAi, directCloudflareDev = false) {
|
|
5387
|
+
return needsAI && (command === "build" || command === "serve" && directCloudflareDev) && !resultAi && !resolvedAi;
|
|
5388
|
+
}
|
|
5389
|
+
/**
|
|
5390
|
+
* Decide whether to inject the `void dev` email-inbox loopback var.
|
|
5391
|
+
*
|
|
5392
|
+
* The dev inbox buffer lives in the Vite dev server's Node process;
|
|
5393
|
+
* `sendEmail` runs in workerd and reaches it by fetching the inbox capture
|
|
5394
|
+
* endpoint through the worker's assets binding, which
|
|
5395
|
+
* `@cloudflare/vite-plugin` wires straight into the dev server's middleware
|
|
5396
|
+
* stack. The var carries that binding's NAME (`ASSETS` for a Void app, or
|
|
5397
|
+
* whatever a Class A framework's own wrangler config declares) and its
|
|
5398
|
+
* presence is what arms the dev path at runtime — so it must never reach a
|
|
5399
|
+
* production build's `wrangler.json`, exactly like the `__VOID_TOKEN`
|
|
5400
|
+
* credential gate.
|
|
5401
|
+
*
|
|
5402
|
+
* Gated on `routeEnvironment`, not on `command`: `vite preview` also reports
|
|
5403
|
+
* `command: 'serve'`, but it runs the BUILT worker whose assets binding is a
|
|
5404
|
+
* real asset directory rather than a dev-server loopback. `routeEnvironment`
|
|
5405
|
+
* is the existing `command === 'serve' && !isPreview` distinction.
|
|
5406
|
+
*
|
|
5407
|
+
* Without an assets binding there is no loopback, so injecting the var would
|
|
5408
|
+
* only arm a path that must then fail; gate on it instead.
|
|
5409
|
+
*/
|
|
5410
|
+
function shouldInjectEmailDevInboxVar(routeEnvironment, needsEmail, assetsBinding) {
|
|
5411
|
+
return routeEnvironment === "dev" && !!needsEmail && typeof assetsBinding === "string" && !!assetsBinding;
|
|
5412
|
+
}
|
|
5413
|
+
/** Resolve the runtime Workers AI binding, preserving a root Wrangler declaration. */
|
|
5414
|
+
function resolveWorkersAiBindingName(resolvedAi, configuredName) {
|
|
5415
|
+
if (typeof resolvedAi === "object" && resolvedAi !== null) {
|
|
5416
|
+
const binding = resolvedAi.binding;
|
|
5417
|
+
if (typeof binding === "string") return binding;
|
|
5418
|
+
}
|
|
5419
|
+
return configuredName ?? "AI";
|
|
4863
5420
|
}
|
|
4864
5421
|
const CLOUDFLARE_BUILTIN_IMPORT = /^cloudflare:/;
|
|
4865
5422
|
const SANDBOX_SDK_IMPORT = "@cloudflare/sandbox";
|
|
@@ -4956,9 +5513,11 @@ function readVoidDevCredentials(root) {
|
|
|
4956
5513
|
const token = getToken(root);
|
|
4957
5514
|
if (!token) return { status: "no-token" };
|
|
4958
5515
|
const staging = isStagingMode(root) || void 0;
|
|
5516
|
+
const apiUrl = getApiUrl(root);
|
|
4959
5517
|
const project = readProjectConfig(root);
|
|
4960
5518
|
if (!project) return {
|
|
4961
5519
|
status: "no-project",
|
|
5520
|
+
apiUrl,
|
|
4962
5521
|
token,
|
|
4963
5522
|
staging
|
|
4964
5523
|
};
|
|
@@ -4966,22 +5525,21 @@ function readVoidDevCredentials(root) {
|
|
|
4966
5525
|
status: "ok",
|
|
4967
5526
|
token,
|
|
4968
5527
|
projectId: project.projectId,
|
|
5528
|
+
proxyUrl: getProxyUrl(root),
|
|
4969
5529
|
staging
|
|
4970
5530
|
};
|
|
4971
5531
|
}
|
|
4972
|
-
const DEFAULT_API_URL = "https://api.void.cloud";
|
|
4973
|
-
const STAGING_API_URL = "https://api.staging.void.cloud";
|
|
4974
5532
|
/**
|
|
4975
5533
|
* Interactive AI setup prompt shown during dev server startup when the user
|
|
4976
5534
|
* has a token but no linked project. Runs as fire-and-forget so it doesn't
|
|
4977
5535
|
* block the server. On completion, writes project.json and restarts the server.
|
|
4978
5536
|
*/
|
|
4979
|
-
async function runAiSetupPrompt(root, token,
|
|
4980
|
-
const { select, text, isCancel, log } = await import("./
|
|
4981
|
-
const { PlatformClient } = await import("./client-
|
|
4982
|
-
const { writeProjectConfig } = await import("./
|
|
4983
|
-
const { inferDefaultSlug } = await import("./resolve-project
|
|
4984
|
-
const client = new PlatformClient(token,
|
|
5537
|
+
async function runAiSetupPrompt(root, token, apiUrl, server) {
|
|
5538
|
+
const { select, text, isCancel, log } = await import("./output-tFQLLj26.mjs").then((n) => n.T);
|
|
5539
|
+
const { PlatformClient } = await import("./client-CyCHWSO_.mjs").then((n) => n.r);
|
|
5540
|
+
const { attachSelectedPlatform, writeProjectConfig } = await import("./auth-W9WII-mN.mjs").then((n) => n.y);
|
|
5541
|
+
const { inferDefaultSlug } = await import("./resolve-project--Vxawf7z.mjs").then((n) => n.i);
|
|
5542
|
+
const client = new PlatformClient(token, apiUrl);
|
|
4985
5543
|
let projects;
|
|
4986
5544
|
try {
|
|
4987
5545
|
projects = await client.listProjects();
|
|
@@ -5006,8 +5564,8 @@ async function runAiSetupPrompt(root, token, staging, server) {
|
|
|
5006
5564
|
let projectId;
|
|
5007
5565
|
let slug;
|
|
5008
5566
|
if (result === "__create__") {
|
|
5009
|
-
const { validateProjectSlug } = await import("./create-project-
|
|
5010
|
-
const { createProjectWithSlugRetry } = await import("./create-project-
|
|
5567
|
+
const { validateProjectSlug } = await import("./create-project-DMV-csEm.mjs").then((n) => n.a);
|
|
5568
|
+
const { createProjectWithSlugRetry } = await import("./create-project-DMV-csEm.mjs").then((n) => n.t);
|
|
5011
5569
|
let created;
|
|
5012
5570
|
try {
|
|
5013
5571
|
created = await createProjectWithSlugRetry(client, inferDefaultSlug(root), async (defaultSlug) => {
|
|
@@ -5017,7 +5575,7 @@ async function runAiSetupPrompt(root, token, staging, server) {
|
|
|
5017
5575
|
initialValue: defaultSlug,
|
|
5018
5576
|
validate: validateProjectSlug
|
|
5019
5577
|
});
|
|
5020
|
-
if (isCancel(slugResult)) return;
|
|
5578
|
+
if (isCancel(slugResult) || typeof slugResult === "symbol") return;
|
|
5021
5579
|
return slugResult.trim();
|
|
5022
5580
|
});
|
|
5023
5581
|
} catch (err) {
|
|
@@ -5032,10 +5590,10 @@ async function runAiSetupPrompt(root, token, staging, server) {
|
|
|
5032
5590
|
projectId = project.id;
|
|
5033
5591
|
slug = project.slug;
|
|
5034
5592
|
}
|
|
5035
|
-
writeProjectConfig(root, {
|
|
5593
|
+
writeProjectConfig(root, attachSelectedPlatform(root, {
|
|
5036
5594
|
projectId,
|
|
5037
5595
|
slug
|
|
5038
|
-
});
|
|
5596
|
+
}, client.apiUrl));
|
|
5039
5597
|
log.success(`Linked to ${import_picocolors.default.blue(slug)}`);
|
|
5040
5598
|
await server.restart();
|
|
5041
5599
|
}
|
|
@@ -5059,10 +5617,12 @@ async function runAiSetupPrompt(root, token, staging, server) {
|
|
|
5059
5617
|
*/
|
|
5060
5618
|
function voidPlugin(options) {
|
|
5061
5619
|
const root = process.cwd();
|
|
5620
|
+
const directCloudflareDestination = readDeploymentPlatform(root) === "cloudflare";
|
|
5062
5621
|
warnIfPackageJsonIsNotEsm(root);
|
|
5063
5622
|
const devTriggerToken = isViteBuildOrPreview() ? crypto.randomUUID() : getOrCreateDevTriggerToken(root);
|
|
5064
5623
|
const config = readConfig(root);
|
|
5065
5624
|
const paths = resolveProjectPaths(root, config);
|
|
5625
|
+
let routeEnvironment = "prod";
|
|
5066
5626
|
assertNoRootSourceConventionConflicts(paths);
|
|
5067
5627
|
const dialect = getDatabaseDialect(config);
|
|
5068
5628
|
const detected = detectFramework(root);
|
|
@@ -5070,6 +5630,13 @@ function voidPlugin(options) {
|
|
|
5070
5630
|
const scanDirs = config.inference?.scanDirs ?? (detected ? FRAMEWORK_SCAN_DIRS : void 0);
|
|
5071
5631
|
const inferenceOptions = config.inference?.bindings ? { bindings: config.inference.bindings } : void 0;
|
|
5072
5632
|
const bindingNames = resolveBindingNames(config.inference?.bindings);
|
|
5633
|
+
const frameworkOwnsCloudflareRuntime = detected !== void 0 && (detected.class === "b" || detected.class === "c");
|
|
5634
|
+
const localD1PersistRoot = frameworkOwnsCloudflareRuntime ? join(root, ".wrangler", "state") : options?.persistTo ?? join(root, ".void");
|
|
5635
|
+
const localD1 = resolveLocalD1Target(root, {
|
|
5636
|
+
bindingName: bindingNames?.d1 ?? "DB",
|
|
5637
|
+
persistRoot: localD1PersistRoot
|
|
5638
|
+
});
|
|
5639
|
+
writeLocalD1PersistState(root, !isNodeTarget(config.target) && !frameworkOwnsCloudflareRuntime ? options?.persistTo : void 0);
|
|
5073
5640
|
const inferredBindings = inferProjectBindings(root, {
|
|
5074
5641
|
...inferenceOptions,
|
|
5075
5642
|
paths
|
|
@@ -5084,6 +5651,8 @@ function voidPlugin(options) {
|
|
|
5084
5651
|
if (detected && authEnabled) throw new Error("auth: Void-managed Better Auth is only supported in Void apps. Use Better Auth's official integration for this framework instead.");
|
|
5085
5652
|
if (detected && bindings.needsSandbox) throw new Error("sandbox: Cloudflare Sandboxes are currently supported in Void apps only.");
|
|
5086
5653
|
if (detected && bindings.needsLive) throw new Error("live: void/live is currently supported in Void apps only.");
|
|
5654
|
+
const hasInboundEmail = hasEmailHandlers(scanEmailHandlersSync(paths.sourceRoot));
|
|
5655
|
+
if (detected && hasInboundEmail) throw new Error("email: inbound email handlers are only supported in Void apps. Remove the email/ directory — `sendEmail` from void/email keeps working.");
|
|
5087
5656
|
const STUB_PREFIX = "\0void-client-stub:";
|
|
5088
5657
|
const SERVER_ONLY_STUBS = {
|
|
5089
5658
|
"void/db": "export const db = {}; export const createDb = () => ({});",
|
|
@@ -5100,12 +5669,37 @@ function voidPlugin(options) {
|
|
|
5100
5669
|
this.reason = reason;
|
|
5101
5670
|
}
|
|
5102
5671
|
}
|
|
5672
|
+
export class SandboxUnavailableError extends Error {
|
|
5673
|
+
constructor(message = 'Managed Sandbox is unavailable on this Void platform.') {
|
|
5674
|
+
super(message);
|
|
5675
|
+
this.name = 'SandboxUnavailableError';
|
|
5676
|
+
}
|
|
5677
|
+
}
|
|
5103
5678
|
export async function getSandbox() {
|
|
5104
5679
|
throw new Error('void/sandbox is server-only and cannot be imported by browser code.');
|
|
5105
5680
|
}
|
|
5106
5681
|
export const sandbox = { get: getSandbox };
|
|
5107
5682
|
`,
|
|
5108
|
-
"void/
|
|
5683
|
+
"void/email": `
|
|
5684
|
+
const serverOnly = (name) => () => {
|
|
5685
|
+
throw new Error(name + ' is server-only and cannot be imported by browser code.');
|
|
5686
|
+
};
|
|
5687
|
+
export const sendEmail = serverOnly('sendEmail');
|
|
5688
|
+
export const createEmail = serverOnly('createEmail');
|
|
5689
|
+
export const defineEmail = serverOnly('defineEmail');
|
|
5690
|
+
export const parseEmail = serverOnly('parseEmail');
|
|
5691
|
+
export const replyEmail = serverOnly('replyEmail');
|
|
5692
|
+
export const createMessageProxy = serverOnly('createMessageProxy');
|
|
5693
|
+
`,
|
|
5694
|
+
"void/email/testing": `
|
|
5695
|
+
const serverOnly = (name) => () => {
|
|
5696
|
+
throw new Error(name + ' is server-only and cannot be imported by browser code.');
|
|
5697
|
+
};
|
|
5698
|
+
export const createEmailTestHarness = serverOnly('createEmailTestHarness');
|
|
5699
|
+
export const createInboundTestHarness = serverOnly('createInboundTestHarness');
|
|
5700
|
+
`,
|
|
5701
|
+
"void/live": "",
|
|
5702
|
+
"void/durable": ""
|
|
5109
5703
|
};
|
|
5110
5704
|
const STUB_RESOLVE_FILTER = new RegExp(`^(${Object.keys(SERVER_ONLY_STUBS).join("|").replaceAll("/", "\\/")})$`);
|
|
5111
5705
|
const STUB_LOAD_FILTER = new RegExp(`^\\0void-client-stub:`);
|
|
@@ -5116,7 +5710,7 @@ function voidPlugin(options) {
|
|
|
5116
5710
|
filter: { id: STUB_RESOLVE_FILTER },
|
|
5117
5711
|
handler(id) {
|
|
5118
5712
|
if (this.environment?.name === "client") {
|
|
5119
|
-
if (id === "void/live") this.error("void/live is server-only and cannot be imported by browser code. Import void/live/client instead.");
|
|
5713
|
+
if (id === "void/live" || id === "void/durable") this.error(id === "void/live" ? "void/live is server-only and cannot be imported by browser code. Import void/live/client instead." : "void/durable is server-only and cannot be imported by browser code.");
|
|
5120
5714
|
return STUB_PREFIX + id;
|
|
5121
5715
|
}
|
|
5122
5716
|
}
|
|
@@ -5128,16 +5722,40 @@ function voidPlugin(options) {
|
|
|
5128
5722
|
}
|
|
5129
5723
|
}
|
|
5130
5724
|
};
|
|
5725
|
+
const serverRuntimeOptimizerPlugin = {
|
|
5726
|
+
name: "void:server-runtime-optimizer",
|
|
5727
|
+
configEnvironment(name) {
|
|
5728
|
+
if (name !== "client") return { optimizeDeps: { exclude: ["void"] } };
|
|
5729
|
+
}
|
|
5730
|
+
};
|
|
5131
5731
|
const queues = framework ? [] : scanQueuesSync(root, paths.queuesDir);
|
|
5132
5732
|
const websocketRoutes = framework ? [] : scanWebSocketRoutesSync(root, paths);
|
|
5733
|
+
const durableObjects = scanDurableObjectModules(root);
|
|
5734
|
+
if (detected && durableObjects.length > 0) throw new Error("durable: durable-objects/ is currently supported in Void apps only, not framework adapter mode.");
|
|
5735
|
+
for (const module of durableObjects) {
|
|
5736
|
+
const websocketCollision = websocketRoutes.find((route) => route.bindingName === module.bindingName || route.className === module.className);
|
|
5737
|
+
if (websocketCollision) throw new Error(`durable: durable-objects/${module.filePath.split("/").pop()} conflicts with WebSocket route '${websocketCollision.filePath}'. Rename one of the files.`);
|
|
5738
|
+
if (sandboxConfig && (sandboxConfig.binding === module.bindingName || sandboxConfig.className === module.className)) throw new Error(`durable: durable-objects/${module.filePath.split("/").pop()} conflicts with the configured Sandbox binding or class. Rename the Durable Object file.`);
|
|
5739
|
+
}
|
|
5740
|
+
let websocketTombstones = [];
|
|
5741
|
+
if (!isNodeTarget(config.target)) {
|
|
5742
|
+
syncWranglerDurableObjects(root, durableObjects);
|
|
5743
|
+
const productionWebSocketRoutes = websocketRoutes.filter((route) => isRouteEnabledForEnvironment(route, "prod"));
|
|
5744
|
+
syncWranglerWebSockets(root, productionWebSocketRoutes);
|
|
5745
|
+
websocketTombstones = readWranglerWebSocketTombstones(root, productionWebSocketRoutes);
|
|
5746
|
+
}
|
|
5133
5747
|
const liveConfig = !isNodeTarget(config.target) ? bindings.needsLive ? resolveLiveBindingConfig(root, {
|
|
5134
|
-
reservedBindings: websocketRoutes.map((route) => route.bindingName),
|
|
5135
|
-
reservedClasses: [
|
|
5748
|
+
reservedBindings: [...websocketRoutes.map((route) => route.bindingName), ...durableObjects.map((module) => module.bindingName)],
|
|
5749
|
+
reservedClasses: [
|
|
5750
|
+
...websocketRoutes.map((route) => route.className),
|
|
5751
|
+
...durableObjects.map((module) => module.className),
|
|
5752
|
+
sandboxConfig?.className
|
|
5753
|
+
]
|
|
5136
5754
|
}) : readExistingLiveBindingConfig(root) : void 0;
|
|
5137
5755
|
if (detected && (detected.class === "b" || detected.class === "c")) {
|
|
5138
|
-
const frameworkPersistRoot =
|
|
5756
|
+
const frameworkPersistRoot = localD1.persistRoot;
|
|
5139
5757
|
const syncFrameworkCompat = (compat) => {
|
|
5140
|
-
if (ensureWranglerCompatibilityDate(root, compat.compatibilityDate)) voidLog("Synced compatibility_date to
|
|
5758
|
+
if (ensureWranglerCompatibilityDate(root, compat.compatibilityDate)) voidLog("Synced compatibility_date to Cloudflare config");
|
|
5141
5759
|
};
|
|
5142
5760
|
const wranglerCompatPlugin = {
|
|
5143
5761
|
name: "void:wrangler-compat",
|
|
@@ -5145,7 +5763,7 @@ function voidPlugin(options) {
|
|
|
5145
5763
|
config(_, env) {
|
|
5146
5764
|
syncFrameworkCompat(ensureWranglerCompat(root, config));
|
|
5147
5765
|
if (env.command !== "serve") return;
|
|
5148
|
-
if (ensureWranglerNodejsAlsFlag(root)) voidLog("Synced nodejs_als to
|
|
5766
|
+
if (ensureWranglerNodejsAlsFlag(root)) voidLog("Synced nodejs_als to Cloudflare config");
|
|
5149
5767
|
},
|
|
5150
5768
|
buildStart() {
|
|
5151
5769
|
syncFrameworkCompat(ensureWranglerCompat(root, config));
|
|
@@ -5202,6 +5820,7 @@ function voidPlugin(options) {
|
|
|
5202
5820
|
...nuxtVite8WebSocketCompatPlugin ? [nuxtVite8WebSocketCompatPlugin] : [],
|
|
5203
5821
|
svelteKitHooksInjectPlugin,
|
|
5204
5822
|
clientStubsPlugin,
|
|
5823
|
+
serverRuntimeOptimizerPlugin,
|
|
5205
5824
|
bindingRuntimePlugin(bindingNames),
|
|
5206
5825
|
envSchemaPlugin(root),
|
|
5207
5826
|
envClientGuardPlugin(root),
|
|
@@ -5209,9 +5828,10 @@ function voidPlugin(options) {
|
|
|
5209
5828
|
drizzlePlugin(root, false, dialect, {
|
|
5210
5829
|
d1BindingName: bindingNames?.d1,
|
|
5211
5830
|
forceVirtualDb: authEnabled || bindingNames?.d1 !== void 0,
|
|
5831
|
+
localD1DatabaseId: localD1.databaseId,
|
|
5212
5832
|
localD1PersistRoot: frameworkPersistRoot
|
|
5213
5833
|
}),
|
|
5214
|
-
migrationPlugin(root, dialect,
|
|
5834
|
+
migrationPlugin(root, dialect, localD1.databaseId, frameworkPersistRoot, { enabled: false }),
|
|
5215
5835
|
devTriggersHintPlugin(root, {
|
|
5216
5836
|
framework: true,
|
|
5217
5837
|
devTriggerToken
|
|
@@ -5224,6 +5844,10 @@ function voidPlugin(options) {
|
|
|
5224
5844
|
}
|
|
5225
5845
|
const remoteMode = resolveRemoteMode(config.remote);
|
|
5226
5846
|
const workerConfig = {};
|
|
5847
|
+
const jobs = scanJobsSync(root, paths.cronsDir);
|
|
5848
|
+
if (jobs.length > 0) workerConfig.triggers = { crons: [...new Set(jobs.flatMap((job) => job.crons))] };
|
|
5849
|
+
let envSchemaFacts;
|
|
5850
|
+
let assetRouting;
|
|
5227
5851
|
if (config.worker?.vars) workerConfig.vars = { ...config.worker.vars };
|
|
5228
5852
|
let viteCommand = "build";
|
|
5229
5853
|
const wranglerCompat = isNodeTarget(config.target) ? void 0 : readWranglerCompat(root, config);
|
|
@@ -5231,17 +5855,35 @@ function voidPlugin(options) {
|
|
|
5231
5855
|
workerConfig.compatibility_date = wranglerCompat.compatibilityDate;
|
|
5232
5856
|
if (wranglerCompat.compatibilityFlags) workerConfig.compatibility_flags = wranglerCompat.compatibilityFlags;
|
|
5233
5857
|
}
|
|
5858
|
+
if (config.worker?.limits?.cpu_ms) workerConfig.limits = { cpu_ms: config.worker.limits.cpu_ms };
|
|
5234
5859
|
const inspectorPortEnv = process.env.VOID_INSPECTOR_PORT;
|
|
5235
5860
|
const inspectorPort = inspectorPortEnv === "false" ? false : typeof inspectorPortEnv === "string" && inspectorPortEnv.length > 0 ? Number.parseInt(inspectorPortEnv, 10) : void 0;
|
|
5236
5861
|
const inspectorPortOption = inspectorPort === false ? { inspectorPort: false } : typeof inspectorPort === "number" ? { inspectorPort } : {};
|
|
5237
5862
|
const outDir = join(root, ".void");
|
|
5238
5863
|
mkdirSync(outDir, { recursive: true });
|
|
5239
5864
|
function mergeBindings(resolved) {
|
|
5865
|
+
const environmentWebsocketRoutes = websocketRoutes.filter((route) => isRouteEnabledForEnvironment(route, routeEnvironment));
|
|
5240
5866
|
const result = { ...workerConfig };
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5867
|
+
result.compatibility_flags = [.../* @__PURE__ */ new Set([...result.compatibility_flags ?? [], ...resolved.compatibility_flags ?? []])];
|
|
5868
|
+
resolved.compatibility_flags = [];
|
|
5869
|
+
if (envSchemaFacts || authEnabled && process.env["VOID_CLOUDFLARE_DEPLOY_BUILD"] === "1") {
|
|
5870
|
+
const plaintextVars = {
|
|
5871
|
+
...resolved.vars ?? {},
|
|
5872
|
+
...result.vars ?? {}
|
|
5873
|
+
};
|
|
5874
|
+
const plaintextServerKeys = (envSchemaFacts?.serverKeys ?? []).filter((key) => key in plaintextVars);
|
|
5875
|
+
if (viteCommand === "build" && plaintextServerKeys.length > 0) throw new Error(`Server env keys cannot be Worker plaintext vars: ${plaintextServerKeys.join(", ")}. Remove them from worker.vars/wrangler vars and set them with the remote secret store.`);
|
|
5876
|
+
const configuredRequired = resolved.secrets?.required ?? [];
|
|
5877
|
+
const required = [.../* @__PURE__ */ new Set([
|
|
5878
|
+
...configuredRequired,
|
|
5879
|
+
...envSchemaFacts?.requiredServerKeys ?? [],
|
|
5880
|
+
...authEnabled && process.env["VOID_CLOUDFLARE_DEPLOY_BUILD"] === "1" ? ["BETTER_AUTH_SECRET"] : []
|
|
5881
|
+
])];
|
|
5882
|
+
if (required.length > 0) result.secrets = { required };
|
|
5883
|
+
}
|
|
5884
|
+
if (workerConfig.assets && resolved.assets) {
|
|
5885
|
+
delete resolved.assets.not_found_handling;
|
|
5886
|
+
delete resolved.assets.run_worker_first;
|
|
5245
5887
|
}
|
|
5246
5888
|
const d1Name = bindingNames?.d1 ?? "DB";
|
|
5247
5889
|
const d1 = [];
|
|
@@ -5263,10 +5905,41 @@ function voidPlugin(options) {
|
|
|
5263
5905
|
binding: r2Name,
|
|
5264
5906
|
bucket_name: "default"
|
|
5265
5907
|
}];
|
|
5266
|
-
|
|
5267
|
-
|
|
5908
|
+
const resolvedAi = resolved.ai;
|
|
5909
|
+
const resultAi = result.ai;
|
|
5910
|
+
const aiBindingName = resolveWorkersAiBindingName(resolvedAi, bindingNames?.ai);
|
|
5911
|
+
if (viteCommand === "serve" && bindings.needsAI && directCloudflareDestination && !resultAi && typeof resolvedAi === "object" && resolvedAi !== null && "binding" in resolvedAi && typeof resolvedAi.binding === "string") result.ai = {
|
|
5912
|
+
...resolvedAi,
|
|
5913
|
+
remote: true
|
|
5914
|
+
};
|
|
5915
|
+
else if (shouldBindWorkersAi(viteCommand, bindings.needsAI, resolvedAi, resultAi, directCloudflareDestination)) result.ai = {
|
|
5916
|
+
binding: aiBindingName,
|
|
5917
|
+
...viteCommand === "serve" && { remote: true }
|
|
5918
|
+
};
|
|
5919
|
+
if (aiBindingName !== "AI" || config.ai?.gateway) {
|
|
5268
5920
|
const vars = result.vars ?? {};
|
|
5269
|
-
vars.
|
|
5921
|
+
if (aiBindingName !== "AI") vars.__VOID_AI_BINDING = aiBindingName;
|
|
5922
|
+
if (config.ai?.gateway) vars.__VOID_AI_GATEWAY = config.ai.gateway;
|
|
5923
|
+
result.vars = vars;
|
|
5924
|
+
}
|
|
5925
|
+
const emailDevInboxBinding = workerConfig.assets?.binding ?? resolved.assets?.binding;
|
|
5926
|
+
if (shouldInjectEmailDevInboxVar(routeEnvironment, bindings.needsEmail, emailDevInboxBinding)) {
|
|
5927
|
+
const vars = result.vars ?? {};
|
|
5928
|
+
vars[DEV_INBOX_ENV_VAR] = emailDevInboxBinding;
|
|
5929
|
+
vars[DEV_INBOX_TOKEN_ENV_VAR] = devTriggerToken;
|
|
5930
|
+
result.vars = vars;
|
|
5931
|
+
}
|
|
5932
|
+
if (viteCommand === "serve" && bindings.needsEmail) {
|
|
5933
|
+
const sendEmail = resolved.send_email;
|
|
5934
|
+
if (Array.isArray(sendEmail)) {
|
|
5935
|
+
const kept = sendEmail.filter((entry) => entry?.name !== SEND_EMAIL_BINDING);
|
|
5936
|
+
if (kept.length > 0) resolved.send_email = kept;
|
|
5937
|
+
else delete resolved.send_email;
|
|
5938
|
+
}
|
|
5939
|
+
}
|
|
5940
|
+
if (viteCommand === "serve" && config.email?.from) {
|
|
5941
|
+
const vars = result.vars ?? {};
|
|
5942
|
+
vars.__VOID_EMAIL_FROM = config.email.from;
|
|
5270
5943
|
result.vars = vars;
|
|
5271
5944
|
}
|
|
5272
5945
|
if (queues.length > 0) result.queues = {
|
|
@@ -5282,17 +5955,40 @@ function voidPlugin(options) {
|
|
|
5282
5955
|
...q.retryDelay != null && { retry_delay: q.retryDelay }
|
|
5283
5956
|
}))
|
|
5284
5957
|
};
|
|
5285
|
-
if (
|
|
5958
|
+
if (environmentWebsocketRoutes.length > 0) {
|
|
5286
5959
|
const existingDurableObjectBindings = resolved.durable_objects?.bindings ?? [];
|
|
5287
|
-
const
|
|
5960
|
+
for (const route of environmentWebsocketRoutes) {
|
|
5961
|
+
const conflict = existingDurableObjectBindings.find((binding) => binding.name === route.bindingName && binding.class_name !== route.className);
|
|
5962
|
+
if (conflict) throw new Error(`websocket: binding '${route.bindingName}' is already configured for class '${conflict.class_name}', but '${route.filePath}' requires '${route.className}'.`);
|
|
5963
|
+
}
|
|
5964
|
+
const missingDurableObjectBindings = environmentWebsocketRoutes.filter((route) => !existingDurableObjectBindings.some((binding) => binding.name === route.bindingName)).map((route) => ({
|
|
5288
5965
|
name: route.bindingName,
|
|
5289
5966
|
class_name: route.className
|
|
5290
5967
|
}));
|
|
5291
5968
|
if (missingDurableObjectBindings.length > 0) result.durable_objects = { bindings: [...existingDurableObjectBindings, ...missingDurableObjectBindings] };
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5969
|
+
const currentMigrations = resolved.migrations;
|
|
5970
|
+
const planned = appendSqliteClassMigration(Array.isArray(currentMigrations) ? currentMigrations : [], environmentWebsocketRoutes.map((route) => route.className), "void-ws-v1", existingDurableObjectBindings.map((binding) => binding.class_name));
|
|
5971
|
+
if (planned.added) result.migrations = planned.migrations;
|
|
5972
|
+
}
|
|
5973
|
+
if (durableObjects.length > 0) {
|
|
5974
|
+
const existingBindings = (result.durable_objects ?? resolved.durable_objects)?.bindings ?? [];
|
|
5975
|
+
for (const module of durableObjects) {
|
|
5976
|
+
const conflict = existingBindings.find((binding) => binding.name === module.bindingName && binding.class_name !== module.className);
|
|
5977
|
+
if (conflict) throw new Error(`durable: binding '${module.bindingName}' is already configured for class '${conflict.class_name}', but durable-objects/ requires '${module.className}'.`);
|
|
5978
|
+
}
|
|
5979
|
+
const additions = durableObjects.filter((module) => !existingBindings.some((binding) => binding.name === module.bindingName)).map((module) => ({
|
|
5980
|
+
name: module.bindingName,
|
|
5981
|
+
class_name: module.className
|
|
5982
|
+
}));
|
|
5983
|
+
if (additions.length > 0) result.durable_objects = { bindings: [...existingBindings, ...additions] };
|
|
5984
|
+
const currentMigrations = result.migrations ?? resolved.migrations;
|
|
5985
|
+
const existingMigrations = Array.isArray(currentMigrations) ? currentMigrations : [];
|
|
5986
|
+
for (const module of durableObjects) if (existingMigrations.find((migration) => migration.tag === module.migrationTag && !migration.new_sqlite_classes?.includes(module.className))) throw new Error(`durable: migration tag '${module.migrationTag}' is already used by another Durable Object migration.`);
|
|
5987
|
+
const migrationAdditions = durableObjects.filter((module) => !existingMigrations.some((migration) => migration.tag === module.migrationTag || migration.new_sqlite_classes?.includes(module.className))).map((module) => ({
|
|
5988
|
+
tag: module.migrationTag,
|
|
5989
|
+
new_sqlite_classes: [module.className]
|
|
5990
|
+
}));
|
|
5991
|
+
if (migrationAdditions.length > 0) result.migrations = [...existingMigrations, ...migrationAdditions];
|
|
5296
5992
|
}
|
|
5297
5993
|
if (bindings.needsSandbox && sandboxConfig) {
|
|
5298
5994
|
const existingDurableObjectBindings = (result.durable_objects ?? resolved.durable_objects)?.bindings ?? [];
|
|
@@ -5329,12 +6025,13 @@ function voidPlugin(options) {
|
|
|
5329
6025
|
new_sqlite_classes: [liveConfig.className]
|
|
5330
6026
|
}];
|
|
5331
6027
|
}
|
|
5332
|
-
if (viteCommand === "serve" && bindings.needsAI) {
|
|
6028
|
+
if (viteCommand === "serve" && bindings.needsAI && !directCloudflareDestination) {
|
|
5333
6029
|
const credentials = readVoidDevCredentials(root);
|
|
5334
6030
|
if (credentials.status === "ok") {
|
|
5335
6031
|
const vars = result.vars ?? {};
|
|
5336
6032
|
vars.__VOID_TOKEN = credentials.token;
|
|
5337
6033
|
vars.__VOID_PROJECT_ID = credentials.projectId;
|
|
6034
|
+
vars.__VOID_PROXY_URL = credentials.proxyUrl;
|
|
5338
6035
|
if (credentials.staging) vars.__VOID_STAGING = "1";
|
|
5339
6036
|
result.vars = vars;
|
|
5340
6037
|
}
|
|
@@ -5343,7 +6040,7 @@ function voidPlugin(options) {
|
|
|
5343
6040
|
const credentials = readVoidDevCredentials(root);
|
|
5344
6041
|
if (credentials.status === "ok") {
|
|
5345
6042
|
const vars = result.vars ?? {};
|
|
5346
|
-
vars.__VOID_PROXY_URL = credentials.
|
|
6043
|
+
vars.__VOID_PROXY_URL = credentials.proxyUrl;
|
|
5347
6044
|
vars.__VOID_TOKEN = credentials.token;
|
|
5348
6045
|
vars.__VOID_PROJECT_ID = credentials.projectId;
|
|
5349
6046
|
vars.__VOID_REMOTE = "1";
|
|
@@ -5352,31 +6049,34 @@ function voidPlugin(options) {
|
|
|
5352
6049
|
}
|
|
5353
6050
|
return result;
|
|
5354
6051
|
}
|
|
5355
|
-
function
|
|
5356
|
-
|
|
5357
|
-
for (const [key, value] of Object.entries(defaults)) if (vars[key] === void 0) vars[key] = value;
|
|
5358
|
-
workerConfig.vars = vars;
|
|
6052
|
+
function applyEnvSchema(facts) {
|
|
6053
|
+
envSchemaFacts = facts;
|
|
5359
6054
|
}
|
|
5360
|
-
let voidDeployBuildConfig;
|
|
5361
6055
|
const envPlugin = {
|
|
5362
6056
|
name: "void:env",
|
|
5363
|
-
|
|
5364
|
-
config(userConfig, { mode, command }) {
|
|
6057
|
+
config(userConfig, { command, isPreview }) {
|
|
5365
6058
|
viteCommand = command;
|
|
6059
|
+
routeEnvironment = command === "serve" && !isPreview ? "dev" : "prod";
|
|
6060
|
+
if (command === "serve" && directCloudflareDestination && bindings.needsAI) process.env.CLOUDFLARE_AUTH_USE_KEYRING = "true";
|
|
6061
|
+
if (!framework && !isNodeTarget(config.target)) {
|
|
6062
|
+
managedCloudflareBuild = command === "build" && Boolean(process.env.VOID_DEPLOY_PROJECT_ID);
|
|
6063
|
+
assetRoutingPublicDir = userConfig.publicDir === false ? null : typeof userConfig.publicDir === "string" ? resolve(root, userConfig.publicDir) : join(root, "public");
|
|
6064
|
+
assetRouting = resolveConfiguredAssetRoutingPolicy();
|
|
6065
|
+
applyAssetRoutingPolicy(assetRouting);
|
|
6066
|
+
}
|
|
5366
6067
|
const ignored = ["**/.void/**"];
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
};
|
|
6068
|
+
if (command === "serve") {
|
|
6069
|
+
const local = loadLocalEnv(root, { onWarn: (message) => voidWarn(message) });
|
|
6070
|
+
const { sanitized: env, stripped } = stripInternalEnvKeys(local);
|
|
6071
|
+
if (stripped.length > 0) voidWarn(`Ignoring internal env keys from .env: ${stripped.join(", ")}. These are reserved for Void runtime use.`);
|
|
6072
|
+
workerConfig.vars = {
|
|
6073
|
+
...workerConfig.vars,
|
|
6074
|
+
...env
|
|
6075
|
+
};
|
|
6076
|
+
if (isPreview) for (const [key, value] of Object.entries(env)) process.env[key] ??= value;
|
|
6077
|
+
}
|
|
5378
6078
|
const assets = workerConfig.assets;
|
|
5379
|
-
if (command === "serve" && assets?.run_worker_first?.includes("/**")) assets.run_worker_first = [...DEV_ASSET_ROUTING_EXCLUSIONS, "/**"];
|
|
6079
|
+
if (command === "serve" && !isPreview && assets?.run_worker_first?.includes("/**")) assets.run_worker_first = [...DEV_ASSET_ROUTING_EXCLUSIONS, "/**"];
|
|
5380
6080
|
const watchConfig = { server: { watch: { ignored } } };
|
|
5381
6081
|
if (!isNodeTarget(config.target) && config.output !== "static") {
|
|
5382
6082
|
const envNames = framework === "vinext-app" ? ["rsc", "ssr"] : ["ssr"];
|
|
@@ -5414,20 +6114,22 @@ function voidPlugin(options) {
|
|
|
5414
6114
|
voidWarn("Falling back to local bindings.");
|
|
5415
6115
|
});
|
|
5416
6116
|
}
|
|
5417
|
-
if (bindings.needsAI) {
|
|
6117
|
+
if (bindings.needsAI && !directCloudflareDestination) {
|
|
5418
6118
|
const credentials = readVoidDevCredentials(root);
|
|
5419
6119
|
if (credentials.status === "no-token") afterReady(() => {
|
|
5420
6120
|
console.log();
|
|
5421
6121
|
voidWarn("AI requires authentication. Run `void auth login`, then restart the dev server.");
|
|
5422
6122
|
});
|
|
5423
|
-
else if (credentials.status === "no-project")
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
6123
|
+
else if (credentials.status === "no-project") {
|
|
6124
|
+
if (process.stdin.isTTY) afterReady(() => {
|
|
6125
|
+
console.log();
|
|
6126
|
+
runAiSetupPrompt(root, credentials.token, credentials.apiUrl, server);
|
|
6127
|
+
});
|
|
6128
|
+
else afterReady(() => {
|
|
6129
|
+
console.log();
|
|
6130
|
+
voidWarn("AI requires a linked project. Run `void project link` to set one up.");
|
|
6131
|
+
});
|
|
6132
|
+
}
|
|
5431
6133
|
}
|
|
5432
6134
|
}
|
|
5433
6135
|
};
|
|
@@ -5444,7 +6146,8 @@ function voidPlugin(options) {
|
|
|
5444
6146
|
if (hintShown) return;
|
|
5445
6147
|
if (!watchDirs.some((d) => path.startsWith(d))) return;
|
|
5446
6148
|
try {
|
|
5447
|
-
const
|
|
6149
|
+
const code = readFileSync(path, "utf-8");
|
|
6150
|
+
const fileBindings = inferBindingsFromSource(code, path.split("/").pop());
|
|
5448
6151
|
const newBindings = [];
|
|
5449
6152
|
if (autoDetectBindings) {
|
|
5450
6153
|
if (fileBindings.needsD1 && !bindings.needsD1) newBindings.push("D1 (void/db)");
|
|
@@ -5452,6 +6155,7 @@ function voidPlugin(options) {
|
|
|
5452
6155
|
if (fileBindings.needsR2 && !bindings.needsR2) newBindings.push("R2 (void/storage)");
|
|
5453
6156
|
if (fileBindings.needsAI && !bindings.needsAI) newBindings.push("AI (void/ai)");
|
|
5454
6157
|
if (fileBindings.needsSandbox && !bindings.needsSandbox) newBindings.push("Sandbox (void/sandbox)");
|
|
6158
|
+
if (fileBindings.needsEmail && !bindings.needsEmail) newBindings.push("Email (void/email)");
|
|
5455
6159
|
}
|
|
5456
6160
|
if (autoDetectAuth && fileBindings.needsAuth) newBindings.push("Auth (void/auth)");
|
|
5457
6161
|
if (newBindings.length > 0) {
|
|
@@ -5478,18 +6182,15 @@ function voidPlugin(options) {
|
|
|
5478
6182
|
};
|
|
5479
6183
|
if (framework) {
|
|
5480
6184
|
workerConfig.main = getFrameworkEntry(framework, root, devTriggerToken, config.routing?.notFound);
|
|
6185
|
+
let notFoundIgnoredWarned = false;
|
|
5481
6186
|
const frameworkBuildWrapperPlugin = {
|
|
5482
6187
|
name: "void:framework-build-wrapper",
|
|
5483
|
-
config(_userConfig, env) {
|
|
5484
|
-
const notFound = config.routing?.notFound;
|
|
5485
|
-
if (env.command !== "build" || notFound === void 0) return;
|
|
5486
|
-
workerConfig.assets = {
|
|
5487
|
-
...workerConfig.assets,
|
|
5488
|
-
not_found_handling: notFound
|
|
5489
|
-
};
|
|
5490
|
-
},
|
|
5491
6188
|
configResolved(resolved) {
|
|
5492
6189
|
if (resolved.command !== "build") return;
|
|
6190
|
+
if (config.routing?.notFound !== void 0 && !process.env.VOID_DEPLOY_BUILD && !notFoundIgnoredWarned) {
|
|
6191
|
+
notFoundIgnoredWarned = true;
|
|
6192
|
+
voidWarn(`Void generates no asset routing policy for a ${framework} build, so "routing.notFound" in void.json is not written to the built worker config. During a self-hosted build and direct Cloudflare deployment, it takes effect only if your own Cloudflare config declares a complete \`assets\` policy (\`binding\`, \`directory\`, \`not_found_handling\`, \`run_worker_first\`); otherwise Cloudflare's default applies. Managed \`void deploy\` supplies the policy for you.`);
|
|
6193
|
+
}
|
|
5493
6194
|
generateClassATriggerWrapper(root, framework, getOriginalFrameworkEntry(framework, root), true, resolved.build.assetsDir, config.routing?.notFound);
|
|
5494
6195
|
}
|
|
5495
6196
|
};
|
|
@@ -5517,19 +6218,22 @@ function voidPlugin(options) {
|
|
|
5517
6218
|
createWranglerCompatPersistPlugin(root, config),
|
|
5518
6219
|
restartPlugin(),
|
|
5519
6220
|
bindingWatchPlugin,
|
|
6221
|
+
...bindings.needsEmail ? [emailDevInboxPlugin({ devTriggerToken })] : [],
|
|
5520
6222
|
envPlugin,
|
|
5521
|
-
envSchemaPlugin(root, {
|
|
6223
|
+
envSchemaPlugin(root, { onSchema: applyEnvSchema }),
|
|
5522
6224
|
envClientGuardPlugin(root),
|
|
5523
6225
|
envClientFoldPlugin(),
|
|
5524
6226
|
clientStubsPlugin,
|
|
6227
|
+
serverRuntimeOptimizerPlugin,
|
|
5525
6228
|
bindingRuntimePlugin(bindingNames),
|
|
5526
6229
|
drizzlePlugin(root, false, getDatabaseDialect(config), {
|
|
5527
6230
|
d1BindingName: bindingNames?.d1,
|
|
5528
6231
|
forceVirtualDb: authEnabled || bindingNames?.d1 !== void 0,
|
|
5529
|
-
|
|
6232
|
+
localD1DatabaseId: localD1.databaseId,
|
|
6233
|
+
localD1PersistRoot: localD1.persistRoot,
|
|
5530
6234
|
redirectDbTypePaths
|
|
5531
6235
|
}),
|
|
5532
|
-
migrationPlugin(root, getDatabaseDialect(config)),
|
|
6236
|
+
migrationPlugin(root, getDatabaseDialect(config), localD1.databaseId, localD1.persistRoot),
|
|
5533
6237
|
...vinextCompat ? [vinextCompat] : [],
|
|
5534
6238
|
frameworkBuildWrapperPlugin,
|
|
5535
6239
|
frameworkTriggersPlugin(root, { devTriggerToken }),
|
|
@@ -5539,7 +6243,7 @@ function voidPlugin(options) {
|
|
|
5539
6243
|
}),
|
|
5540
6244
|
...cloudflare({
|
|
5541
6245
|
...inspectorPortOption,
|
|
5542
|
-
persistState: { path:
|
|
6246
|
+
persistState: { path: localD1.persistRoot },
|
|
5543
6247
|
auxiliaryWorkers: options?.auxiliaryWorkers,
|
|
5544
6248
|
viteEnvironment,
|
|
5545
6249
|
config: mergeBindings
|
|
@@ -5553,10 +6257,13 @@ function voidPlugin(options) {
|
|
|
5553
6257
|
if (config.remote) voidWarn("\"remote\" in void.json is ignored with target: \"" + config.target + "\"");
|
|
5554
6258
|
if (bindings.needsSandbox) throw new Error(`sandbox: Cloudflare Sandboxes require target: "cloudflare". They are not available with target: '${config.target}'.`);
|
|
5555
6259
|
if (bindings.needsLive) throw new Error(`live: void/live requires target: "cloudflare". It is not available with target: '${config.target}'.`);
|
|
6260
|
+
if (durableObjects.length > 0) throw new Error(`durable: durable-objects/ requires target: "cloudflare". It is not available with target: '${config.target}'.`);
|
|
6261
|
+
if (hasInboundEmail) throw new Error(`email: inbound email handlers (email/) require target: "cloudflare". They are not available with target: '${config.target}'.`);
|
|
5556
6262
|
if (config.routing?.revalidate) voidWarn("\"routing.revalidate\" in void.json is ignored with target: \"" + config.target + "\" (edge caching is CF-only)");
|
|
5557
6263
|
return [
|
|
5558
6264
|
restartPlugin(),
|
|
5559
6265
|
envPlugin,
|
|
6266
|
+
serverRuntimeOptimizerPlugin,
|
|
5560
6267
|
envSchemaPlugin(root),
|
|
5561
6268
|
...pagesDevCssAssetsPlugin(root, devTriggerToken),
|
|
5562
6269
|
routingPlugin(root, {
|
|
@@ -5574,28 +6281,43 @@ function voidPlugin(options) {
|
|
|
5574
6281
|
];
|
|
5575
6282
|
}
|
|
5576
6283
|
const existingFlags = workerConfig.compatibility_flags ?? [];
|
|
5577
|
-
const
|
|
6284
|
+
const needsNodejsCompat = authEnabled || dialect !== "sqlite" || bindings.needsSandbox;
|
|
6285
|
+
const normalizedFlags = normalizeWranglerCompatibilityFlags(existingFlags, { needsNodejsCompat });
|
|
5578
6286
|
if (normalizedFlags && normalizedFlags !== existingFlags) workerConfig.compatibility_flags = normalizedFlags;
|
|
5579
|
-
const jobs = scanJobsSync(root, paths.cronsDir);
|
|
5580
6287
|
const ssrEntry = validateSsrEntry(root, paths);
|
|
5581
6288
|
const hasPages = existsSync(paths.pagesDir);
|
|
5582
6289
|
const hasMiddleware = scanMiddlewareSync(root, paths).length > 0;
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
6290
|
+
let assetRoutingPublicDir = join(root, "public");
|
|
6291
|
+
let managedCloudflareBuild = false;
|
|
6292
|
+
function resolveConfiguredAssetRoutingPolicy() {
|
|
6293
|
+
const routePatterns = scanRoutePatternsSync(root, paths, routeEnvironment);
|
|
6294
|
+
const environmentWebsocketRoutes = websocketRoutes.filter((route) => isRouteEnabledForEnvironment(route, routeEnvironment));
|
|
6295
|
+
const policy = resolveAssetRoutingPolicy({
|
|
6296
|
+
isSsr: Boolean(ssrEntry),
|
|
6297
|
+
hasPages,
|
|
6298
|
+
hasApiRoutes: hasApiRoutes(routePatterns) || hasApiRoutes(environmentWebsocketRoutes) || authEnabled,
|
|
6299
|
+
hasDocumentRoutes: hasDocumentRoutes(routePatterns),
|
|
6300
|
+
hasMiddleware,
|
|
6301
|
+
hasWebSockets: hasDocumentRoutes(environmentWebsocketRoutes),
|
|
6302
|
+
authEnabled,
|
|
6303
|
+
liveEnabled: liveConfig !== void 0,
|
|
6304
|
+
notFound: config.routing?.notFound
|
|
6305
|
+
});
|
|
6306
|
+
const rules = mergeRoutingRules({
|
|
6307
|
+
dir: assetRoutingPublicDir,
|
|
6308
|
+
routing: config.routing
|
|
6309
|
+
});
|
|
6310
|
+
if (!managedCloudflareBuild && (rules.headerRules.length > 0 || rules.redirectRules.length > 0 || (rules.fallbackRules?.length ?? 0) > 0)) {
|
|
6311
|
+
policy.assetConfig.run_worker_first = ["/**"];
|
|
6312
|
+
if (rules.fallbackRules?.length && policy.assetConfig.not_found_handling === "single-page-application") {
|
|
6313
|
+
policy.assetConfig.not_found_handling = "none";
|
|
6314
|
+
policy.workerSpaFallback = true;
|
|
6315
|
+
}
|
|
6316
|
+
}
|
|
6317
|
+
return policy;
|
|
6318
|
+
}
|
|
6319
|
+
assetRouting = resolveConfiguredAssetRoutingPolicy();
|
|
5597
6320
|
workerConfig.main = join(root, ".void", "entry.ts");
|
|
5598
|
-
if (jobs.length > 0) workerConfig.triggers = { crons: jobs.flatMap((job) => job.crons) };
|
|
5599
6321
|
function applyAssetRoutingPolicy(policy) {
|
|
5600
6322
|
workerConfig.assets = {
|
|
5601
6323
|
binding: "ASSETS",
|
|
@@ -5617,11 +6339,13 @@ function voidPlugin(options) {
|
|
|
5617
6339
|
createWranglerCompatPersistPlugin(root, config),
|
|
5618
6340
|
restartPlugin(),
|
|
5619
6341
|
bindingWatchPlugin,
|
|
6342
|
+
...bindings.needsEmail ? [emailDevInboxPlugin({ devTriggerToken })] : [],
|
|
5620
6343
|
envPlugin,
|
|
5621
|
-
envSchemaPlugin(root, {
|
|
6344
|
+
envSchemaPlugin(root, { onSchema: applyEnvSchema }),
|
|
5622
6345
|
envClientGuardPlugin(root),
|
|
5623
6346
|
envClientFoldPlugin(),
|
|
5624
6347
|
clientStubsPlugin,
|
|
6348
|
+
serverRuntimeOptimizerPlugin,
|
|
5625
6349
|
bindingRuntimePlugin(bindingNames),
|
|
5626
6350
|
...bindings.needsSandbox ? [createSandboxSdkResolvePlugin()] : [],
|
|
5627
6351
|
...pagesDevCssAssetsPlugin(root, devTriggerToken),
|
|
@@ -5638,14 +6362,17 @@ function voidPlugin(options) {
|
|
|
5638
6362
|
sandboxBindingName: sandboxConfig?.binding,
|
|
5639
6363
|
sandboxClassName: sandboxConfig?.className,
|
|
5640
6364
|
live: liveConfig,
|
|
6365
|
+
durableObjects,
|
|
6366
|
+
websocketTombstones,
|
|
5641
6367
|
onDevAssetRoutingPolicyChange: updateDevAssetRoutingPolicy
|
|
5642
6368
|
}),
|
|
5643
6369
|
drizzlePlugin(root, true, dialect, {
|
|
5644
6370
|
d1BindingName: bindingNames?.d1,
|
|
5645
6371
|
forceVirtualDb: authEnabled || bindingNames?.d1 !== void 0,
|
|
5646
|
-
|
|
6372
|
+
localD1DatabaseId: localD1.databaseId,
|
|
6373
|
+
localD1PersistRoot: localD1.persistRoot
|
|
5647
6374
|
}),
|
|
5648
|
-
migrationPlugin(root, dialect,
|
|
6375
|
+
migrationPlugin(root, dialect, localD1.databaseId, localD1.persistRoot, {
|
|
5649
6376
|
enabled: authEnabled,
|
|
5650
6377
|
configPath: authConfigPath
|
|
5651
6378
|
}),
|
|
@@ -5656,7 +6383,7 @@ function voidPlugin(options) {
|
|
|
5656
6383
|
}),
|
|
5657
6384
|
...cloudflare({
|
|
5658
6385
|
...inspectorPortOption,
|
|
5659
|
-
persistState: { path:
|
|
6386
|
+
persistState: { path: localD1.persistRoot },
|
|
5660
6387
|
auxiliaryWorkers: options?.auxiliaryWorkers,
|
|
5661
6388
|
viteEnvironment: { name: DEFAULT_WORKER_ENVIRONMENT_NAME },
|
|
5662
6389
|
config: mergeBindings
|
|
@@ -5664,4 +6391,4 @@ function voidPlugin(options) {
|
|
|
5664
6391
|
];
|
|
5665
6392
|
}
|
|
5666
6393
|
//#endregion
|
|
5667
|
-
export { VoidAssetRewriteError, basicAuth, defer, defineHandler, defineHead, defineMiddleware, defineQueue, defineRender, defineScheduled, shouldBindWorkersAi, voidPlugin };
|
|
6394
|
+
export { VoidAssetRewriteError, basicAuth, defer, defineHandler, defineHead, defineMiddleware, defineQueue, defineRender, defineScheduled, resolveWorkersAiBindingName, shouldBindWorkersAi, shouldInjectEmailDevInboxVar, voidPlugin };
|