void 0.10.13 → 0.20.1
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-CAH62yDU.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-CJvZvPQO.mjs} +6 -4
- package/dist/{cache-C11V8Fxq.mjs → cache-BlNeQjuP.mjs} +9 -5
- package/dist/{cancel-deploy-fwFYF04b.mjs → cancel-deploy-CmlAZ9P6.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 +1735 -165
- 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-Clirrol3.mjs} +120 -463
- package/dist/cloudflare-auth-B1QtTO1b.mjs +217 -0
- package/dist/cloudflare-cmd-B6_OZx2V.mjs +62 -0
- package/dist/cloudflare-connect-j5D4hhrG.mjs +56 -0
- package/dist/cloudflare-operations-CPTpRW6d.mjs +566 -0
- package/dist/{config-qHGgPuWT.mjs → config-BQFq7QvD.mjs} +75 -41
- package/dist/{config-CutEMNGJ.mjs → config-NOG_U1aK.mjs} +10 -15
- package/dist/connect-C04Wdy_h.mjs +79 -0
- package/dist/{create-project-DsYvl3TB.mjs → create-project-ChGZ1DFd.mjs} +26 -16
- package/dist/database-provider.d.mts +21 -0
- package/dist/database-provider.mjs +6 -0
- package/dist/{db-C0i0sYMS.mjs → db-D2d_mUsB.mjs} +612 -117
- package/dist/{delete-mh6p-zkQ.mjs → delete-D8GigDk8.mjs} +9 -6
- package/dist/{deploy-jBJT1fUT.mjs → deploy-iXZ3F0N6.mjs} +3252 -1995
- 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-B1VmoSr0.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-uKyQYUVY.mjs +1016 -0
- package/dist/{entry-D7yy4xVH.mjs → entry-DU3oDoQ3.mjs} +2 -2
- package/dist/env-BcQzYgoG.mjs +73 -0
- package/dist/env-D4Emu-M_.mjs +95 -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-BzXf3Jh2.mjs → gen-DI2YwdBM.mjs} +70 -15
- package/dist/generate-RTK8_kK1.mjs +47 -0
- package/dist/{github-cmd-DKcGUNsj.mjs → github-cmd-xItS5Zwf.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-ChAADPQu.mjs → headers-D8QfRX9Y.mjs} +12 -10
- package/dist/inbound-2d0zi2yS.mjs +706 -0
- package/dist/inbound-afAcWeQ9.d.mts +363 -0
- package/dist/index.d.mts +61 -34
- package/dist/index.mjs +1012 -293
- package/dist/{init-7JCAcKNQ.mjs → init-BD-9THgn.mjs} +329 -271
- package/dist/link-RMdgjF1v.mjs +52 -0
- package/dist/{list-CPwFDZ_c.mjs → list-3F52R_yO.mjs} +37 -5
- package/dist/{runner-kapo9aPs.mjs → local-d1-D2I6Ox5F.mjs} +116 -6
- package/dist/{login-BT3H8PN3.mjs → login-pV69H-ZO.mjs} +17 -15
- package/dist/{logs-Bt313ax7.mjs → logs-DFHHD6wE.mjs} +16 -2
- package/dist/mime-BJD7d_qL.mjs +1216 -0
- package/dist/neon-DHwd2zvC.mjs +54 -0
- package/dist/{node-pRg81HqV.mjs → node-Dk3H2jmU.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-DxJ2FRwR.mjs +123 -0
- package/dist/platform-domain-ChvbJkdy.mjs +228 -0
- package/dist/platform-lifecycle-DN4MzJF_.mjs +4450 -0
- package/dist/platform-management-Db2PXw0B.mjs +698 -0
- package/dist/platform-recovery-C_YO-tIs.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-BvvgAz-3.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-Mo0V9yKS.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-CPx2ZxsH.mjs → provision-Blnstcm2.mjs} +78 -45
- package/dist/r2-conditions-D1Wk8i7b.mjs +30 -0
- package/dist/{requests-B8sZxaFM.mjs → requests-BcKOVpRg.mjs} +5 -3
- package/dist/{resolve-project-BBMtLLV9.mjs → resolve-project--Vxawf7z.mjs} +2 -2
- package/dist/rollback-Bx85-0xh.mjs +166 -0
- package/dist/{rolldown-runtime-DJK8HYOj.mjs → rolldown-runtime-rQ84J-ij.mjs} +1 -1
- package/dist/{route-types-z1jtHEi_.mjs → route-types-Da-DpyUp.mjs} +77 -25
- package/dist/routes-stub.d.mts +22 -23
- package/dist/runner-mysql-7BPUNGmL.mjs +61 -0
- package/dist/{runner-pg-CHM76xuC.mjs → runner-pg-BkEza-dX.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-ChWt4pX1.mjs → scan-BMH4rzlv.mjs} +42 -19
- package/dist/{scan-NU4xKGci.mjs → scan-CpK-57ug.mjs} +5 -4
- package/dist/{secret-Dt32J6RI.mjs → secret-ByhJ9AMl.mjs} +62 -5
- package/dist/{skills-CLjN0uUO.mjs → skills-Q46GZMO-.mjs} +6 -4
- package/dist/sqlite-validation-BzKMWnO4.mjs +25 -0
- 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-tBBN_dXH.mjs} +4 -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 +22 -3
- 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 +99 -25
- 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 +12 -10
- package/skills/void/docs/guide/email.md +640 -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 +264 -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 +5 -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 +15 -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 +665 -160
- package/skills/void/docs/reference/config.md +67 -27
- package/skills/void/docs/reference/resource-inference.md +13 -9
- package/skills/void/docs/reference/structure.md +9 -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 -221
- 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-iXZ3F0N6.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-D2I6Ox5F.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-D2I6Ox5F.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-tBBN_dXH.mjs").then((n) => n.l);
|
|
1986
|
+
const { validateMigrations } = await import("./validate-tBBN_dXH.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-7BPUNGmL.mjs").then((n) => n.n).then((runner) => runner.getMySqlAppliedMigrations(url)) : await import("./runner-pg-BkEza-dX.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-7BPUNGmL.mjs").then((n) => n.n).then((runner) => runner.runMySqlMigrations(migrationsDir, url)) : await import("./runner-pg-BkEza-dX.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-D2I6Ox5F.mjs").then((n) => n.i);
|
|
2000
|
+
const { collectMigrations } = await import("./validate-tBBN_dXH.mjs").then((n) => n.l);
|
|
2001
|
+
const { validateMigrations } = await import("./validate-tBBN_dXH.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-Dk3H2jmU.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,42 @@ ${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 __relayed = typeof envelope.viaDomain === "string" && envelope.viaDomain.length > 0;
|
|
4152
|
+
const __slug = __relayed ? undefined : (typeof env.__VOID_PROJECT_SLUG === "string" && env.__VOID_PROJECT_SLUG.length > 0 ? env.__VOID_PROJECT_SLUG : undefined);
|
|
4153
|
+
const { message, getActions } = __createMessageProxy(envelope, { slug: __slug });
|
|
4154
|
+
await __withRawEnv(env, () => withRuntimeEnv(env, () => __emailHandler(message, userEnv, ctx, { slug: __slug })));
|
|
4155
|
+
const __actions = getActions();
|
|
4156
|
+
if (__isForwardableEmailMessage(envelope)) await __enactEmailActions(envelope, __actions);
|
|
4157
|
+
return __actions;
|
|
4158
|
+
}` : `async function handleEmail(envelope, env, ctx) {
|
|
4159
|
+
${envValidateCall} const userEnv = __filterInternalBindings(env);
|
|
4160
|
+
const __relayed = typeof envelope.viaDomain === "string" && envelope.viaDomain.length > 0;
|
|
4161
|
+
const __slug = __relayed ? undefined : (typeof env.__VOID_PROJECT_SLUG === "string" && env.__VOID_PROJECT_SLUG.length > 0 ? env.__VOID_PROJECT_SLUG : undefined);
|
|
4162
|
+
const { message, getActions } = __createMessageProxy(envelope, { slug: __slug });
|
|
4163
|
+
await __withRawEnv(env, () => withRuntimeEnv(env, () => __emailHandler(message, userEnv, ctx, { slug: __slug })));
|
|
4164
|
+
const __actions = getActions();
|
|
4165
|
+
if (__isForwardableEmailMessage(envelope)) await __enactEmailActions(envelope, __actions);
|
|
4166
|
+
return __actions;
|
|
4167
|
+
}` : "";
|
|
4168
|
+
const entryImport = `import { WorkerEntrypoint } from "cloudflare:workers";\n`;
|
|
4169
|
+
const fetchDeclaration = `const __voidFetch = ${fetchHandler};`;
|
|
4170
|
+
const entryClass = `export default class extends WorkerEntrypoint {
|
|
4171
|
+
async fetch(request) { return __voidFetch(request, this.env, this.ctx); }
|
|
4172
|
+
async scheduled(controller) { return handleScheduled(controller, this.env, this.ctx); }
|
|
4173
|
+
${hasQueues ? ` async queue(batch) { return __voidQueue(batch, this.env, this.ctx); }\n` : ""}${hasEmail ? ` async email(envelope) { return handleEmail(envelope, this.env, this.ctx); }\n` : ""}}`;
|
|
4174
|
+
if (hasQueues) return `${sandboxImport}${entryImport}${liveRuntimeImport}import app, { scheduled, __voidCollectPrerenderPaths, __voidHandleInternalRoute, __withRawEnv, __processQueue${emailImport}${webSocketClasses.length > 0 ? `, ${webSocketClasses.join(", ")}` : ""}${liveRouteImport} } from 'virtual:void-routes';
|
|
4175
|
+
${durableObjectImports}\n${runtimeEnvImport}${emailProxyImport}${envSchemaImport}${remoteImport}${isrImport}${filterBindingsHelper}${assetHelper}
|
|
3745
4176
|
${internalRouteHelper}
|
|
4177
|
+
${fetchDeclaration}
|
|
3746
4178
|
${scheduledHandler}
|
|
3747
|
-
|
|
4179
|
+
${emailHandler}
|
|
4180
|
+
async function __voidQueue(batch, env, ctx) {
|
|
3748
4181
|
${envValidateCall}${remotePath ? ` if (env.__VOID_REMOTE === "1") env = ${createRemoteEnvCall};\n` : ""}${isrDeploymentStamp} const userEnv = __filterInternalBindings(env);
|
|
3749
4182
|
const messages = [...batch.messages].map(m => ({
|
|
3750
4183
|
id: m.id, timestamp: m.timestamp.toISOString(),
|
|
@@ -3768,15 +4201,19 @@ ${envValidateCall}${remotePath ? ` if (env.__VOID_REMOTE === "1") env = ${creat
|
|
|
3768
4201
|
${webSocketClasses.map((name) => `export { ${name} };`).join("\n")}
|
|
3769
4202
|
${liveExport}
|
|
3770
4203
|
${sandboxExport}
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
4204
|
+
${durableObjectExports}
|
|
4205
|
+
${entryClass}`;
|
|
4206
|
+
return `${sandboxImport}${entryImport}${liveRuntimeImport}import app, { scheduled, __voidCollectPrerenderPaths, __voidHandleInternalRoute, __withRawEnv${emailImport}${webSocketClasses.length > 0 ? `, ${webSocketClasses.join(", ")}` : ""}${liveRouteImport} } from 'virtual:void-routes';
|
|
4207
|
+
${durableObjectImports}\n${runtimeEnvImport}${emailProxyImport}${envSchemaImport}${remoteImport}${isrImport}${filterBindingsHelper}${assetHelper}
|
|
3774
4208
|
${internalRouteHelper}
|
|
4209
|
+
${fetchDeclaration}
|
|
3775
4210
|
${scheduledHandler}
|
|
4211
|
+
${emailHandler}
|
|
3776
4212
|
${webSocketClasses.map((name) => `export { ${name} };`).join("\n")}
|
|
3777
4213
|
${liveExport}
|
|
3778
4214
|
${sandboxExport}
|
|
3779
|
-
|
|
4215
|
+
${durableObjectExports}
|
|
4216
|
+
${entryClass}`;
|
|
3780
4217
|
}
|
|
3781
4218
|
/**
|
|
3782
4219
|
* Generate the app module — exports the Hono app with static asset serving.
|
|
@@ -3792,11 +4229,17 @@ export default { fetch: ${fetchHandler}, scheduled: handleScheduled };`;
|
|
|
3792
4229
|
function compileNodeApp(target, honoPath, envSchemaModule) {
|
|
3793
4230
|
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
4231
|
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` : "";
|
|
4232
|
+
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
4233
|
return `${staticImport}
|
|
4234
|
+
import { fileURLToPath } from "node:url";
|
|
3797
4235
|
import { Hono } from ${JSON.stringify(honoPath)};
|
|
3798
4236
|
import innerApp, { __voidCollectPrerenderPaths } from "virtual:void-routes";
|
|
3799
4237
|
${envSchemaImport}
|
|
4238
|
+
// Resolved by nodeTargetPlugin for this emitted chunk, including shared chunks.
|
|
4239
|
+
const clientRoot = fileURLToPath(import.meta.voidClientDirectory);
|
|
4240
|
+
const assetApp = new Hono();
|
|
4241
|
+
assetApp.get("*", serveStatic({ root: clientRoot }));
|
|
4242
|
+
const assets = { fetch: (request) => assetApp.fetch(request) };
|
|
3800
4243
|
const app = new Hono();
|
|
3801
4244
|
${envMiddleware}app.post("/__void/prerender-paths", async (c) => {
|
|
3802
4245
|
const __expected = c.env?.__VOID_PROXY_TOKEN;
|
|
@@ -3807,8 +4250,8 @@ ${envMiddleware}app.post("/__void/prerender-paths", async (c) => {
|
|
|
3807
4250
|
const paths = await __voidCollectPrerenderPaths(c.req.raw);
|
|
3808
4251
|
return c.json({ paths });
|
|
3809
4252
|
});
|
|
3810
|
-
app.
|
|
3811
|
-
app.all("*", (c) => innerApp.fetch(c.req.raw));
|
|
4253
|
+
app.get("/assets/*", (c) => assets.fetch(c.req.raw));
|
|
4254
|
+
app.all("*", (c) => innerApp.fetch(c.req.raw, { ...c.env, ASSETS: assets }));
|
|
3812
4255
|
export default app;`;
|
|
3813
4256
|
}
|
|
3814
4257
|
/**
|
|
@@ -4260,6 +4703,7 @@ function routingPlugin(root, options) {
|
|
|
4260
4703
|
const middlewareDir = paths.middlewareDir;
|
|
4261
4704
|
const jobsDir = paths.cronsDir;
|
|
4262
4705
|
const queuesDir = paths.queuesDir;
|
|
4706
|
+
const emailDir = paths.emailDir;
|
|
4263
4707
|
const pagesDir = paths.pagesDir;
|
|
4264
4708
|
const ssrDir = paths.ssrDir;
|
|
4265
4709
|
const authConfigPaths = new Set(paths.authConfigCandidates.map((path) => normalizePath(path)));
|
|
@@ -4268,9 +4712,14 @@ function routingPlugin(root, options) {
|
|
|
4268
4712
|
const normalizedMiddlewareDir = normalizePath(middlewareDir);
|
|
4269
4713
|
const normalizedJobsDir = normalizePath(jobsDir);
|
|
4270
4714
|
const normalizedQueuesDir = normalizePath(queuesDir);
|
|
4715
|
+
const normalizedEmailDir = normalizePath(emailDir);
|
|
4271
4716
|
const normalizedPagesDir = normalizePath(pagesDir);
|
|
4272
4717
|
const normalizedSsrDir = normalizePath(ssrDir);
|
|
4273
4718
|
const ssrEntryAbsPaths = new Set([...SSR_SERVER_ENTRY_RELATIVE_PATHS, ...SSR_CLIENT_ENTRY_RELATIVE_PATHS].map((path) => normalizePath(join(ssrDir, path.split("/").pop()))));
|
|
4719
|
+
function hasEmailHandlers() {
|
|
4720
|
+
const email = scan?.email;
|
|
4721
|
+
return Boolean(email && (email.addresses.length > 0 || email.defaultHandler));
|
|
4722
|
+
}
|
|
4274
4723
|
function isInDirectory(path, directory) {
|
|
4275
4724
|
return path === directory || path.startsWith(directory + "/");
|
|
4276
4725
|
}
|
|
@@ -4329,16 +4778,20 @@ function routingPlugin(root, options) {
|
|
|
4329
4778
|
responsePath: resolveFile("#self/response"),
|
|
4330
4779
|
handlerPath: resolveFile("#self/handler"),
|
|
4331
4780
|
runtimeEnvPath: resolveFile("#self/_env"),
|
|
4781
|
+
runtimeEmailPath: resolveFile("#self/email"),
|
|
4782
|
+
emailDir,
|
|
4332
4783
|
projectRoot: root,
|
|
4333
4784
|
homeDir: homedir(),
|
|
4334
4785
|
webSocketRuntimePath: resolveFile("#self/runtime/ws-server"),
|
|
4335
4786
|
liveRuntimePath: resolveFile("#self/runtime/live-server"),
|
|
4336
4787
|
hasLive: options.live !== void 0,
|
|
4788
|
+
webSocketTombstones: options.websocketTombstones,
|
|
4337
4789
|
reactRefresh: false,
|
|
4338
4790
|
dev: false,
|
|
4339
4791
|
devTriggerToken: options.devTriggerToken,
|
|
4340
4792
|
auth: null,
|
|
4341
4793
|
nodeTarget: !!options.target,
|
|
4794
|
+
managedDispatch: false,
|
|
4342
4795
|
explicitPrerenderPaths: options.prerenderPaths,
|
|
4343
4796
|
bindingHandlerPath: options.target ? void 0 : resolveFile("#self/remote/binding-handler"),
|
|
4344
4797
|
bindingNames: options.bindingNames
|
|
@@ -4366,7 +4819,7 @@ function routingPlugin(root, options) {
|
|
|
4366
4819
|
const config = readConfig(root);
|
|
4367
4820
|
const dialect = getDatabaseDialect(config);
|
|
4368
4821
|
compileOptions.auth = {
|
|
4369
|
-
authRuntimePath: dialect === "postgresql" ? join(runtimeDir, "better-auth-pg.mjs") : join(runtimeDir, "better-auth.mjs"),
|
|
4822
|
+
authRuntimePath: dialect === "postgresql" ? join(runtimeDir, "better-auth-pg.mjs") : dialect === "mysql" ? join(runtimeDir, "better-auth-mysql.mjs") : join(runtimeDir, "better-auth.mjs"),
|
|
4370
4823
|
authConfigPath,
|
|
4371
4824
|
authDatabasePath: null,
|
|
4372
4825
|
authSchemaPath: null,
|
|
@@ -4381,7 +4834,10 @@ function routingPlugin(root, options) {
|
|
|
4381
4834
|
providers: compileOptions.auth.providers,
|
|
4382
4835
|
userConfig: await loadVoidAuthConfig(compileOptions.auth.authConfigPath)
|
|
4383
4836
|
};
|
|
4384
|
-
const env =
|
|
4837
|
+
const env = {
|
|
4838
|
+
...resolvedConfig?.command === "serve" ? loadLocalEnv(root) : {},
|
|
4839
|
+
...process.env
|
|
4840
|
+
};
|
|
4385
4841
|
const schemaPath = join(outDir, "better-auth-schema.ts");
|
|
4386
4842
|
const databasePath = join(outDir, "better-auth-db.ts");
|
|
4387
4843
|
writeFileIfChanged(schemaPath, generateVoidAuthDrizzleSchema(authRuntime, env));
|
|
@@ -4395,6 +4851,8 @@ function routingPlugin(root, options) {
|
|
|
4395
4851
|
}
|
|
4396
4852
|
let resolvedConfig = null;
|
|
4397
4853
|
let isrRevalidate;
|
|
4854
|
+
let isrPages;
|
|
4855
|
+
let isrPathRevalidate;
|
|
4398
4856
|
function resolveAuthClientPath(config) {
|
|
4399
4857
|
if (config.plugins.some((plugin) => plugin.name === "void-react:pages")) return explicitAuthClientPaths.react;
|
|
4400
4858
|
if (config.plugins.some((plugin) => plugin.name === "void-vue:pages")) return explicitAuthClientPaths.vue;
|
|
@@ -4475,11 +4933,20 @@ function routingPlugin(root, options) {
|
|
|
4475
4933
|
if (options.target) {
|
|
4476
4934
|
writeFileIfChanged(join(outDir, "app.ts"), compileNodeApp(options.target, compileOptions.honoPath, getEnvSchemaModule()));
|
|
4477
4935
|
writeFileIfChanged(join(outDir, "index.ts"), compileNodeServer(options.target));
|
|
4478
|
-
} else writeFileIfChanged(join(outDir, "entry.ts"), compileWorkerEntry(
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4936
|
+
} else writeFileIfChanged(join(outDir, "entry.ts"), compileWorkerEntry({
|
|
4937
|
+
remote,
|
|
4938
|
+
webSocketClasses: options.websocketTombstones,
|
|
4939
|
+
runtimeEnvPath: compileOptions.runtimeEnvPath,
|
|
4940
|
+
runtimeEmailPath: compileOptions.runtimeEmailPath,
|
|
4941
|
+
envSchemaModule: getEnvSchemaModule(),
|
|
4942
|
+
sandbox: options.hasSandbox ? {
|
|
4943
|
+
bindingName: options.sandboxBindingName,
|
|
4944
|
+
className: options.sandboxClassName,
|
|
4945
|
+
runtimePath: sandboxRuntimePath
|
|
4946
|
+
} : false,
|
|
4947
|
+
live: options.live,
|
|
4948
|
+
durableObjects: options.durableObjects
|
|
4949
|
+
}));
|
|
4483
4950
|
return {
|
|
4484
4951
|
name: "void:routing",
|
|
4485
4952
|
enforce: "pre",
|
|
@@ -4496,6 +4963,7 @@ function routingPlugin(root, options) {
|
|
|
4496
4963
|
},
|
|
4497
4964
|
config(_, env) {
|
|
4498
4965
|
routeEnvironment = env.command === "serve" && !env.isPreview ? "dev" : "prod";
|
|
4966
|
+
compileOptions.managedDispatch = !options.target && env.command === "build" && Boolean(process.env.VOID_DEPLOY_PROJECT_ID);
|
|
4499
4967
|
if (env.command === "serve" && options.isAuthEnabled()) return { resolve: { alias: [
|
|
4500
4968
|
"client",
|
|
4501
4969
|
"react",
|
|
@@ -4529,11 +4997,11 @@ function routingPlugin(root, options) {
|
|
|
4529
4997
|
if (!options.target) {
|
|
4530
4998
|
const migrationsDir = paths.migrationsDir;
|
|
4531
4999
|
if (existsSync(migrationsDir) || compileOptions.auth) {
|
|
4532
|
-
const { collectMigrations } = await import("./validate-
|
|
4533
|
-
const { buildMigrationPlanBundle } = await import("./validate-
|
|
5000
|
+
const { collectMigrations } = await import("./validate-tBBN_dXH.mjs").then((n) => n.l);
|
|
5001
|
+
const { buildMigrationPlanBundle } = await import("./validate-tBBN_dXH.mjs").then((n) => n.s);
|
|
4534
5002
|
const migrations = existsSync(migrationsDir) ? collectMigrations(migrationsDir) : [];
|
|
4535
5003
|
const dialect = getDatabaseDialect(readConfig(root));
|
|
4536
|
-
compileOptions.migrationHandlerPath = resolveFile(dialect === "postgresql" ? "#self/runtime/migration-handler-pg" : "#self/runtime/migration-handler");
|
|
5004
|
+
compileOptions.migrationHandlerPath = resolveFile(dialect === "postgresql" ? "#self/runtime/migration-handler-pg" : dialect === "mysql" ? "#self/runtime/migration-handler-mysql" : "#self/runtime/migration-handler");
|
|
4537
5005
|
compileOptions.migrations = migrations;
|
|
4538
5006
|
compileOptions.migrationPlanBundle = dialect === "sqlite" ? buildMigrationPlanBundle(migrations) : void 0;
|
|
4539
5007
|
compileOptions.migrationDialect = dialect;
|
|
@@ -4543,15 +5011,37 @@ function routingPlugin(root, options) {
|
|
|
4543
5011
|
writeFileIfChanged(join(outDir, "app.ts"), compileNodeApp(options.target, compileOptions.honoPath, getEnvSchemaModule()));
|
|
4544
5012
|
writeFileIfChanged(join(outDir, "index.ts"), compileNodeServer(options.target));
|
|
4545
5013
|
} else {
|
|
4546
|
-
const
|
|
5014
|
+
const buildConfig = readConfig(root);
|
|
5015
|
+
const merged = collectRevalidate(buildConfig, scan.pages);
|
|
5016
|
+
const configuredRevalidate = buildConfig.routing?.revalidate;
|
|
4547
5017
|
const emitIsr = !options.target && resolvedConfig?.command === "build" && !process.env.VOID_DEPLOY_PROJECT_ID && hasRevalidate(merged);
|
|
4548
5018
|
isrRevalidate = emitIsr ? merged : void 0;
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
} :
|
|
5019
|
+
isrPages = emitIsr ? collectPages(scan.pages, configuredRevalidate) : void 0;
|
|
5020
|
+
isrPathRevalidate = emitIsr && configuredRevalidate && typeof configuredRevalidate === "object" ? configuredRevalidate : void 0;
|
|
5021
|
+
const isr = emitIsr ? {
|
|
5022
|
+
runtimePath: resolveFile("@void/isr/runtime"),
|
|
5023
|
+
queryAllowlist: buildConfig.routing?.revalidateQueryAllowlist
|
|
5024
|
+
} : void 0;
|
|
5025
|
+
writeFileIfChanged(join(outDir, "entry.ts"), compileWorkerEntry({
|
|
5026
|
+
hasQueues: scan.queues.length > 0,
|
|
5027
|
+
remote,
|
|
5028
|
+
assetsDir: resolvedConfig?.build.assetsDir,
|
|
5029
|
+
webSocketClasses: [...(scan.websockets ?? []).map((route) => route.className), ...options.websocketTombstones ?? []],
|
|
5030
|
+
runtimeEnvPath: compileOptions.runtimeEnvPath,
|
|
5031
|
+
runtimeEmailPath: compileOptions.runtimeEmailPath,
|
|
5032
|
+
envSchemaModule: getEnvSchemaModule(),
|
|
5033
|
+
sandbox: options.hasSandbox ? {
|
|
5034
|
+
bindingName: options.sandboxBindingName,
|
|
5035
|
+
className: options.sandboxClassName,
|
|
5036
|
+
runtimePath: sandboxRuntimePath
|
|
5037
|
+
} : false,
|
|
5038
|
+
hasEmail: hasEmailHandlers(),
|
|
5039
|
+
serveSpaFallback: shouldServeSpaFallback(),
|
|
5040
|
+
live: options.live,
|
|
5041
|
+
isr,
|
|
5042
|
+
notFound: currentNotFoundHandling(),
|
|
5043
|
+
durableObjects: options.durableObjects
|
|
5044
|
+
}));
|
|
4555
5045
|
}
|
|
4556
5046
|
},
|
|
4557
5047
|
resolveId: {
|
|
@@ -4576,14 +5066,14 @@ function routingPlugin(root, options) {
|
|
|
4576
5066
|
}
|
|
4577
5067
|
if (id !== VIRTUAL_ROUTES_ID) return;
|
|
4578
5068
|
if (!scan) await rescan();
|
|
4579
|
-
return compileRouteTable(scan, routesDir, middlewareDir, jobsDir, queuesDir, ssr, compileOptions, getPagesCompileOptions(), isrRevalidate);
|
|
5069
|
+
return compileRouteTable(scan, routesDir, middlewareDir, jobsDir, queuesDir, ssr, compileOptions, getPagesCompileOptions(), isrRevalidate, isrPages, isrPathRevalidate);
|
|
4580
5070
|
}
|
|
4581
5071
|
},
|
|
4582
5072
|
configureServer(devServer) {
|
|
4583
5073
|
const watcher = devServer.watcher;
|
|
4584
5074
|
const handleFileChange = async (path, event) => {
|
|
4585
5075
|
const normalizedPath = normalizePath(path);
|
|
4586
|
-
const sourceConventionChanged = isInDirectory(normalizedPath, normalizedRoutesDir) || isInDirectory(normalizedPath, normalizedMiddlewareDir) || isInDirectory(normalizedPath, normalizedJobsDir) || isInDirectory(normalizedPath, normalizedQueuesDir) || isInDirectory(normalizedPath, normalizedPagesDir) || isPotentialAuthConfigPath(normalizedPath) || isPotentialEnvFilePath(normalizedPath);
|
|
5076
|
+
const sourceConventionChanged = isInDirectory(normalizedPath, normalizedRoutesDir) || isInDirectory(normalizedPath, normalizedMiddlewareDir) || isInDirectory(normalizedPath, normalizedJobsDir) || isInDirectory(normalizedPath, normalizedQueuesDir) || isInDirectory(normalizedPath, normalizedEmailDir) || isInDirectory(normalizedPath, normalizedPagesDir) || isPotentialAuthConfigPath(normalizedPath) || isPotentialEnvFilePath(normalizedPath);
|
|
4587
5077
|
if (!sourceConventionChanged && !isInDirectory(normalizedPath, normalizedSsrDir) && !isPotentialEnvFilePath(normalizedPath)) return;
|
|
4588
5078
|
if (!sourceConventionChanged && isInDirectory(normalizedPath, normalizedSsrDir) && !ssrEntryAbsPaths.has(normalizedPath)) return;
|
|
4589
5079
|
await rescan();
|
|
@@ -4598,11 +5088,26 @@ function routingPlugin(root, options) {
|
|
|
4598
5088
|
if (options.target) {
|
|
4599
5089
|
writeFileIfChanged(join(outDir, "app.ts"), compileNodeApp(options.target, compileOptions.honoPath, getEnvSchemaModule()));
|
|
4600
5090
|
writeFileIfChanged(join(outDir, "index.ts"), compileNodeServer(options.target));
|
|
4601
|
-
} else writeFileIfChanged(join(outDir, "entry.ts"), compileWorkerEntry(
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
5091
|
+
} else writeFileIfChanged(join(outDir, "entry.ts"), compileWorkerEntry({
|
|
5092
|
+
hasQueues: scan.queues.length > 0,
|
|
5093
|
+
remote,
|
|
5094
|
+
assetsDir: resolvedConfig?.build.assetsDir,
|
|
5095
|
+
webSocketClasses: [...(scan.websockets ?? []).map((route) => route.className), ...options.websocketTombstones ?? []],
|
|
5096
|
+
runtimeEnvPath: compileOptions.runtimeEnvPath,
|
|
5097
|
+
runtimeEmailPath: compileOptions.runtimeEmailPath,
|
|
5098
|
+
envSchemaModule: getEnvSchemaModule(),
|
|
5099
|
+
sandbox: options.hasSandbox ? {
|
|
5100
|
+
bindingName: options.sandboxBindingName,
|
|
5101
|
+
className: options.sandboxClassName,
|
|
5102
|
+
runtimePath: sandboxRuntimePath
|
|
5103
|
+
} : false,
|
|
5104
|
+
hasEmail: hasEmailHandlers(),
|
|
5105
|
+
serveSpaFallback: shouldServeSpaFallback(),
|
|
5106
|
+
live: options.live,
|
|
5107
|
+
isr: void 0,
|
|
5108
|
+
notFound: currentNotFoundHandling(),
|
|
5109
|
+
durableObjects: options.durableObjects
|
|
5110
|
+
}));
|
|
4606
5111
|
const structural = event !== "change";
|
|
4607
5112
|
const pageManifestChanged = isInDirectory(normalizedPath, normalizedPagesDir) && (structural || normalizedPath.endsWith(".md"));
|
|
4608
5113
|
for (const env of Object.values(devServer.environments)) {
|
|
@@ -4660,6 +5165,13 @@ function routingPlugin(root, options) {
|
|
|
4660
5165
|
* The token is local to the project and only honored by a worker bound to
|
|
4661
5166
|
* localhost; treat it like the rest of `.void/` — disposable scratch state,
|
|
4662
5167
|
* safe to remove manually if desired.
|
|
5168
|
+
*
|
|
5169
|
+
* The file is owner-only (0600). It is the one credential the dev-inbox
|
|
5170
|
+
* routes accept, and loopback is reachable by every account on the host,
|
|
5171
|
+
* so a default-umask 0644 file would hand any other local user the raw MIME,
|
|
5172
|
+
* the DELETE, and the capture endpoint. A file persisted by an earlier
|
|
5173
|
+
* release is tightened in place, never rotated. Windows has no group/other
|
|
5174
|
+
* bits — `mode` and `chmod` only toggle write there — so it is left alone.
|
|
4663
5175
|
*/
|
|
4664
5176
|
/**
|
|
4665
5177
|
* Best-effort detection of `vite build` (and `vite preview`) so we can skip
|
|
@@ -4674,6 +5186,7 @@ function isViteBuildOrPreview() {
|
|
|
4674
5186
|
const subcommand = process.argv[2];
|
|
4675
5187
|
return subcommand === "build" || subcommand === "preview";
|
|
4676
5188
|
}
|
|
5189
|
+
const DEV_TRIGGER_TOKEN_FILE_MODE = 384;
|
|
4677
5190
|
function getOrCreateDevTriggerToken(root) {
|
|
4678
5191
|
const tokenPath = join(root, ".void", "dev-trigger-token");
|
|
4679
5192
|
const readExisting = () => {
|
|
@@ -4684,12 +5197,21 @@ function getOrCreateDevTriggerToken(root) {
|
|
|
4684
5197
|
return;
|
|
4685
5198
|
}
|
|
4686
5199
|
};
|
|
5200
|
+
const tightenExisting = () => {
|
|
5201
|
+
if (process.platform === "win32") return;
|
|
5202
|
+
try {
|
|
5203
|
+
if ((statSync(tokenPath).mode & 63) !== 0) chmodSync(tokenPath, DEV_TRIGGER_TOKEN_FILE_MODE);
|
|
5204
|
+
} catch {}
|
|
5205
|
+
};
|
|
4687
5206
|
const existing = readExisting();
|
|
4688
|
-
if (existing)
|
|
5207
|
+
if (existing) {
|
|
5208
|
+
tightenExisting();
|
|
5209
|
+
return existing;
|
|
5210
|
+
}
|
|
4689
5211
|
mkdirSync(join(root, ".void"), { recursive: true });
|
|
4690
5212
|
const fresh = crypto.randomUUID();
|
|
4691
5213
|
try {
|
|
4692
|
-
const fd = openSync(tokenPath, "wx");
|
|
5214
|
+
const fd = openSync(tokenPath, "wx", DEV_TRIGGER_TOKEN_FILE_MODE);
|
|
4693
5215
|
try {
|
|
4694
5216
|
writeSync(fd, fresh);
|
|
4695
5217
|
} finally {
|
|
@@ -4773,7 +5295,7 @@ function generateClassATriggerWrapper(root, framework, original, isBuild, assets
|
|
|
4773
5295
|
const outDir = join(root, ".void");
|
|
4774
5296
|
mkdirSync(outDir, { recursive: true });
|
|
4775
5297
|
const wrapperPath = join(outDir, `${framework}-trigger-wrapper.ts`);
|
|
4776
|
-
|
|
5298
|
+
const body = isBuild ? `// @ts-nocheck — Auto-generated by Void for vite build. Do NOT edit.
|
|
4777
5299
|
import original from ${JSON.stringify(original)};
|
|
4778
5300
|
|
|
4779
5301
|
export default {
|
|
@@ -4795,7 +5317,8 @@ export default {
|
|
|
4795
5317
|
return original.fetch(request, env, ctx);
|
|
4796
5318
|
},
|
|
4797
5319
|
};
|
|
4798
|
-
|
|
5320
|
+
`;
|
|
5321
|
+
writeFileIfChanged(wrapperPath, body);
|
|
4799
5322
|
return wrapperPath;
|
|
4800
5323
|
}
|
|
4801
5324
|
/** Generate a worker entry for vinext Pages Router projects. */
|
|
@@ -4853,16 +5376,49 @@ function hasBinding(list, name) {
|
|
|
4853
5376
|
/**
|
|
4854
5377
|
* Decide whether to inject a Workers AI binding into the built wrangler config.
|
|
4855
5378
|
*
|
|
4856
|
-
*
|
|
4857
|
-
*
|
|
5379
|
+
* Builds use the production binding. During dev, a project explicitly saved
|
|
5380
|
+
* with the direct Cloudflare destination uses Cloudflare's remote binding;
|
|
5381
|
+
* managed and unsaved projects keep using the Void HTTPS proxy.
|
|
4858
5382
|
*
|
|
4859
5383
|
* `!resolvedAi` is load-bearing: mergeBindings' return is defu-merged over the
|
|
4860
5384
|
* resolved root-wrangler config and wins, so skipping when the user already
|
|
4861
5385
|
* declared an `ai` binding avoids clobbering theirs. `!resultAi` is harmless
|
|
4862
5386
|
* defense-in-depth (nothing else in mergeBindings sets `result.ai`).
|
|
4863
5387
|
*/
|
|
4864
|
-
function shouldBindWorkersAi(command, needsAI, resolvedAi, resultAi) {
|
|
4865
|
-
return needsAI && command === "build" && !resultAi && !resolvedAi;
|
|
5388
|
+
function shouldBindWorkersAi(command, needsAI, resolvedAi, resultAi, directCloudflareDev = false) {
|
|
5389
|
+
return needsAI && (command === "build" || command === "serve" && directCloudflareDev) && !resultAi && !resolvedAi;
|
|
5390
|
+
}
|
|
5391
|
+
/**
|
|
5392
|
+
* Decide whether to inject the `void dev` email-inbox loopback var.
|
|
5393
|
+
*
|
|
5394
|
+
* The dev inbox buffer lives in the Vite dev server's Node process;
|
|
5395
|
+
* `sendEmail` runs in workerd and reaches it by fetching the inbox capture
|
|
5396
|
+
* endpoint through the worker's assets binding, which
|
|
5397
|
+
* `@cloudflare/vite-plugin` wires straight into the dev server's middleware
|
|
5398
|
+
* stack. The var carries that binding's NAME (`ASSETS` for a Void app, or
|
|
5399
|
+
* whatever a Class A framework's own wrangler config declares) and its
|
|
5400
|
+
* presence is what arms the dev path at runtime — so it must never reach a
|
|
5401
|
+
* production build's `wrangler.json`, exactly like the `__VOID_TOKEN`
|
|
5402
|
+
* credential gate.
|
|
5403
|
+
*
|
|
5404
|
+
* Gated on `routeEnvironment`, not on `command`: `vite preview` also reports
|
|
5405
|
+
* `command: 'serve'`, but it runs the BUILT worker whose assets binding is a
|
|
5406
|
+
* real asset directory rather than a dev-server loopback. `routeEnvironment`
|
|
5407
|
+
* is the existing `command === 'serve' && !isPreview` distinction.
|
|
5408
|
+
*
|
|
5409
|
+
* Without an assets binding there is no loopback, so injecting the var would
|
|
5410
|
+
* only arm a path that must then fail; gate on it instead.
|
|
5411
|
+
*/
|
|
5412
|
+
function shouldInjectEmailDevInboxVar(routeEnvironment, needsEmail, assetsBinding) {
|
|
5413
|
+
return routeEnvironment === "dev" && !!needsEmail && typeof assetsBinding === "string" && !!assetsBinding;
|
|
5414
|
+
}
|
|
5415
|
+
/** Resolve the runtime Workers AI binding, preserving a root Wrangler declaration. */
|
|
5416
|
+
function resolveWorkersAiBindingName(resolvedAi, configuredName) {
|
|
5417
|
+
if (typeof resolvedAi === "object" && resolvedAi !== null) {
|
|
5418
|
+
const binding = resolvedAi.binding;
|
|
5419
|
+
if (typeof binding === "string") return binding;
|
|
5420
|
+
}
|
|
5421
|
+
return configuredName ?? "AI";
|
|
4866
5422
|
}
|
|
4867
5423
|
const CLOUDFLARE_BUILTIN_IMPORT = /^cloudflare:/;
|
|
4868
5424
|
const SANDBOX_SDK_IMPORT = "@cloudflare/sandbox";
|
|
@@ -4959,9 +5515,11 @@ function readVoidDevCredentials(root) {
|
|
|
4959
5515
|
const token = getToken(root);
|
|
4960
5516
|
if (!token) return { status: "no-token" };
|
|
4961
5517
|
const staging = isStagingMode(root) || void 0;
|
|
5518
|
+
const apiUrl = getApiUrl(root);
|
|
4962
5519
|
const project = readProjectConfig(root);
|
|
4963
5520
|
if (!project) return {
|
|
4964
5521
|
status: "no-project",
|
|
5522
|
+
apiUrl,
|
|
4965
5523
|
token,
|
|
4966
5524
|
staging
|
|
4967
5525
|
};
|
|
@@ -4969,22 +5527,21 @@ function readVoidDevCredentials(root) {
|
|
|
4969
5527
|
status: "ok",
|
|
4970
5528
|
token,
|
|
4971
5529
|
projectId: project.projectId,
|
|
5530
|
+
proxyUrl: getProxyUrl(root),
|
|
4972
5531
|
staging
|
|
4973
5532
|
};
|
|
4974
5533
|
}
|
|
4975
|
-
const DEFAULT_API_URL = "https://api.void.cloud";
|
|
4976
|
-
const STAGING_API_URL = "https://api.staging.void.cloud";
|
|
4977
5534
|
/**
|
|
4978
5535
|
* Interactive AI setup prompt shown during dev server startup when the user
|
|
4979
5536
|
* has a token but no linked project. Runs as fire-and-forget so it doesn't
|
|
4980
5537
|
* block the server. On completion, writes project.json and restarts the server.
|
|
4981
5538
|
*/
|
|
4982
|
-
async function runAiSetupPrompt(root, token,
|
|
4983
|
-
const { select, text, isCancel, log } = await import("./
|
|
4984
|
-
const { PlatformClient } = await import("./client-
|
|
4985
|
-
const { writeProjectConfig } = await import("./
|
|
4986
|
-
const { inferDefaultSlug } = await import("./resolve-project
|
|
4987
|
-
const client = new PlatformClient(token,
|
|
5539
|
+
async function runAiSetupPrompt(root, token, apiUrl, server) {
|
|
5540
|
+
const { select, text, isCancel, log } = await import("./output-tFQLLj26.mjs").then((n) => n.T);
|
|
5541
|
+
const { PlatformClient } = await import("./client-Clirrol3.mjs").then((n) => n.r);
|
|
5542
|
+
const { attachSelectedPlatform, writeProjectConfig } = await import("./auth-W9WII-mN.mjs").then((n) => n.y);
|
|
5543
|
+
const { inferDefaultSlug } = await import("./resolve-project--Vxawf7z.mjs").then((n) => n.i);
|
|
5544
|
+
const client = new PlatformClient(token, apiUrl);
|
|
4988
5545
|
let projects;
|
|
4989
5546
|
try {
|
|
4990
5547
|
projects = await client.listProjects();
|
|
@@ -5009,8 +5566,8 @@ async function runAiSetupPrompt(root, token, staging, server) {
|
|
|
5009
5566
|
let projectId;
|
|
5010
5567
|
let slug;
|
|
5011
5568
|
if (result === "__create__") {
|
|
5012
|
-
const { validateProjectSlug } = await import("./create-project-
|
|
5013
|
-
const { createProjectWithSlugRetry } = await import("./create-project-
|
|
5569
|
+
const { validateProjectSlug } = await import("./create-project-ChGZ1DFd.mjs").then((n) => n.a);
|
|
5570
|
+
const { createProjectWithSlugRetry } = await import("./create-project-ChGZ1DFd.mjs").then((n) => n.t);
|
|
5014
5571
|
let created;
|
|
5015
5572
|
try {
|
|
5016
5573
|
created = await createProjectWithSlugRetry(client, inferDefaultSlug(root), async (defaultSlug) => {
|
|
@@ -5020,7 +5577,7 @@ async function runAiSetupPrompt(root, token, staging, server) {
|
|
|
5020
5577
|
initialValue: defaultSlug,
|
|
5021
5578
|
validate: validateProjectSlug
|
|
5022
5579
|
});
|
|
5023
|
-
if (isCancel(slugResult)) return;
|
|
5580
|
+
if (isCancel(slugResult) || typeof slugResult === "symbol") return;
|
|
5024
5581
|
return slugResult.trim();
|
|
5025
5582
|
});
|
|
5026
5583
|
} catch (err) {
|
|
@@ -5035,10 +5592,10 @@ async function runAiSetupPrompt(root, token, staging, server) {
|
|
|
5035
5592
|
projectId = project.id;
|
|
5036
5593
|
slug = project.slug;
|
|
5037
5594
|
}
|
|
5038
|
-
writeProjectConfig(root, {
|
|
5595
|
+
writeProjectConfig(root, attachSelectedPlatform(root, {
|
|
5039
5596
|
projectId,
|
|
5040
5597
|
slug
|
|
5041
|
-
});
|
|
5598
|
+
}, client.apiUrl));
|
|
5042
5599
|
log.success(`Linked to ${import_picocolors.default.blue(slug)}`);
|
|
5043
5600
|
await server.restart();
|
|
5044
5601
|
}
|
|
@@ -5062,6 +5619,7 @@ async function runAiSetupPrompt(root, token, staging, server) {
|
|
|
5062
5619
|
*/
|
|
5063
5620
|
function voidPlugin(options) {
|
|
5064
5621
|
const root = process.cwd();
|
|
5622
|
+
const directCloudflareDestination = readDeploymentPlatform(root) === "cloudflare";
|
|
5065
5623
|
warnIfPackageJsonIsNotEsm(root);
|
|
5066
5624
|
const devTriggerToken = isViteBuildOrPreview() ? crypto.randomUUID() : getOrCreateDevTriggerToken(root);
|
|
5067
5625
|
const config = readConfig(root);
|
|
@@ -5074,6 +5632,13 @@ function voidPlugin(options) {
|
|
|
5074
5632
|
const scanDirs = config.inference?.scanDirs ?? (detected ? FRAMEWORK_SCAN_DIRS : void 0);
|
|
5075
5633
|
const inferenceOptions = config.inference?.bindings ? { bindings: config.inference.bindings } : void 0;
|
|
5076
5634
|
const bindingNames = resolveBindingNames(config.inference?.bindings);
|
|
5635
|
+
const frameworkOwnsCloudflareRuntime = detected !== void 0 && (detected.class === "b" || detected.class === "c");
|
|
5636
|
+
const localD1PersistRoot = frameworkOwnsCloudflareRuntime ? join(root, ".wrangler", "state") : options?.persistTo ?? join(root, ".void");
|
|
5637
|
+
const localD1 = resolveLocalD1Target(root, {
|
|
5638
|
+
bindingName: bindingNames?.d1 ?? "DB",
|
|
5639
|
+
persistRoot: localD1PersistRoot
|
|
5640
|
+
});
|
|
5641
|
+
writeLocalD1PersistState(root, !isNodeTarget(config.target) && !frameworkOwnsCloudflareRuntime ? options?.persistTo : void 0);
|
|
5077
5642
|
const inferredBindings = inferProjectBindings(root, {
|
|
5078
5643
|
...inferenceOptions,
|
|
5079
5644
|
paths
|
|
@@ -5088,6 +5653,8 @@ function voidPlugin(options) {
|
|
|
5088
5653
|
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.");
|
|
5089
5654
|
if (detected && bindings.needsSandbox) throw new Error("sandbox: Cloudflare Sandboxes are currently supported in Void apps only.");
|
|
5090
5655
|
if (detected && bindings.needsLive) throw new Error("live: void/live is currently supported in Void apps only.");
|
|
5656
|
+
const hasInboundEmail = hasEmailHandlers(scanEmailHandlersSync(paths.sourceRoot));
|
|
5657
|
+
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.");
|
|
5091
5658
|
const STUB_PREFIX = "\0void-client-stub:";
|
|
5092
5659
|
const SERVER_ONLY_STUBS = {
|
|
5093
5660
|
"void/db": "export const db = {}; export const createDb = () => ({});",
|
|
@@ -5104,12 +5671,37 @@ function voidPlugin(options) {
|
|
|
5104
5671
|
this.reason = reason;
|
|
5105
5672
|
}
|
|
5106
5673
|
}
|
|
5674
|
+
export class SandboxUnavailableError extends Error {
|
|
5675
|
+
constructor(message = 'Managed Sandbox is unavailable on this Void platform.') {
|
|
5676
|
+
super(message);
|
|
5677
|
+
this.name = 'SandboxUnavailableError';
|
|
5678
|
+
}
|
|
5679
|
+
}
|
|
5107
5680
|
export async function getSandbox() {
|
|
5108
5681
|
throw new Error('void/sandbox is server-only and cannot be imported by browser code.');
|
|
5109
5682
|
}
|
|
5110
5683
|
export const sandbox = { get: getSandbox };
|
|
5111
5684
|
`,
|
|
5112
|
-
"void/
|
|
5685
|
+
"void/email": `
|
|
5686
|
+
const serverOnly = (name) => () => {
|
|
5687
|
+
throw new Error(name + ' is server-only and cannot be imported by browser code.');
|
|
5688
|
+
};
|
|
5689
|
+
export const sendEmail = serverOnly('sendEmail');
|
|
5690
|
+
export const createEmail = serverOnly('createEmail');
|
|
5691
|
+
export const defineEmail = serverOnly('defineEmail');
|
|
5692
|
+
export const parseEmail = serverOnly('parseEmail');
|
|
5693
|
+
export const replyEmail = serverOnly('replyEmail');
|
|
5694
|
+
export const createMessageProxy = serverOnly('createMessageProxy');
|
|
5695
|
+
`,
|
|
5696
|
+
"void/email/testing": `
|
|
5697
|
+
const serverOnly = (name) => () => {
|
|
5698
|
+
throw new Error(name + ' is server-only and cannot be imported by browser code.');
|
|
5699
|
+
};
|
|
5700
|
+
export const createEmailTestHarness = serverOnly('createEmailTestHarness');
|
|
5701
|
+
export const createInboundTestHarness = serverOnly('createInboundTestHarness');
|
|
5702
|
+
`,
|
|
5703
|
+
"void/live": "",
|
|
5704
|
+
"void/durable": ""
|
|
5113
5705
|
};
|
|
5114
5706
|
const STUB_RESOLVE_FILTER = new RegExp(`^(${Object.keys(SERVER_ONLY_STUBS).join("|").replaceAll("/", "\\/")})$`);
|
|
5115
5707
|
const STUB_LOAD_FILTER = new RegExp(`^\\0void-client-stub:`);
|
|
@@ -5120,7 +5712,7 @@ function voidPlugin(options) {
|
|
|
5120
5712
|
filter: { id: STUB_RESOLVE_FILTER },
|
|
5121
5713
|
handler(id) {
|
|
5122
5714
|
if (this.environment?.name === "client") {
|
|
5123
|
-
if (id === "void/live") this.error("void/live is server-only and cannot be imported by browser code. Import void/live/client instead.");
|
|
5715
|
+
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.");
|
|
5124
5716
|
return STUB_PREFIX + id;
|
|
5125
5717
|
}
|
|
5126
5718
|
}
|
|
@@ -5132,16 +5724,40 @@ function voidPlugin(options) {
|
|
|
5132
5724
|
}
|
|
5133
5725
|
}
|
|
5134
5726
|
};
|
|
5727
|
+
const serverRuntimeOptimizerPlugin = {
|
|
5728
|
+
name: "void:server-runtime-optimizer",
|
|
5729
|
+
configEnvironment(name) {
|
|
5730
|
+
if (name !== "client") return { optimizeDeps: { exclude: ["void"] } };
|
|
5731
|
+
}
|
|
5732
|
+
};
|
|
5135
5733
|
const queues = framework ? [] : scanQueuesSync(root, paths.queuesDir);
|
|
5136
5734
|
const websocketRoutes = framework ? [] : scanWebSocketRoutesSync(root, paths);
|
|
5735
|
+
const durableObjects = scanDurableObjectModules(root);
|
|
5736
|
+
if (detected && durableObjects.length > 0) throw new Error("durable: durable-objects/ is currently supported in Void apps only, not framework adapter mode.");
|
|
5737
|
+
for (const module of durableObjects) {
|
|
5738
|
+
const websocketCollision = websocketRoutes.find((route) => route.bindingName === module.bindingName || route.className === module.className);
|
|
5739
|
+
if (websocketCollision) throw new Error(`durable: durable-objects/${module.filePath.split("/").pop()} conflicts with WebSocket route '${websocketCollision.filePath}'. Rename one of the files.`);
|
|
5740
|
+
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.`);
|
|
5741
|
+
}
|
|
5742
|
+
let websocketTombstones = [];
|
|
5743
|
+
if (!isNodeTarget(config.target)) {
|
|
5744
|
+
syncWranglerDurableObjects(root, durableObjects);
|
|
5745
|
+
const productionWebSocketRoutes = websocketRoutes.filter((route) => isRouteEnabledForEnvironment(route, "prod"));
|
|
5746
|
+
syncWranglerWebSockets(root, productionWebSocketRoutes);
|
|
5747
|
+
websocketTombstones = readWranglerWebSocketTombstones(root, productionWebSocketRoutes);
|
|
5748
|
+
}
|
|
5137
5749
|
const liveConfig = !isNodeTarget(config.target) ? bindings.needsLive ? resolveLiveBindingConfig(root, {
|
|
5138
|
-
reservedBindings: websocketRoutes.map((route) => route.bindingName),
|
|
5139
|
-
reservedClasses: [
|
|
5750
|
+
reservedBindings: [...websocketRoutes.map((route) => route.bindingName), ...durableObjects.map((module) => module.bindingName)],
|
|
5751
|
+
reservedClasses: [
|
|
5752
|
+
...websocketRoutes.map((route) => route.className),
|
|
5753
|
+
...durableObjects.map((module) => module.className),
|
|
5754
|
+
sandboxConfig?.className
|
|
5755
|
+
]
|
|
5140
5756
|
}) : readExistingLiveBindingConfig(root) : void 0;
|
|
5141
5757
|
if (detected && (detected.class === "b" || detected.class === "c")) {
|
|
5142
|
-
const frameworkPersistRoot =
|
|
5758
|
+
const frameworkPersistRoot = localD1.persistRoot;
|
|
5143
5759
|
const syncFrameworkCompat = (compat) => {
|
|
5144
|
-
if (ensureWranglerCompatibilityDate(root, compat.compatibilityDate)) voidLog("Synced compatibility_date to
|
|
5760
|
+
if (ensureWranglerCompatibilityDate(root, compat.compatibilityDate)) voidLog("Synced compatibility_date to Cloudflare config");
|
|
5145
5761
|
};
|
|
5146
5762
|
const wranglerCompatPlugin = {
|
|
5147
5763
|
name: "void:wrangler-compat",
|
|
@@ -5149,7 +5765,7 @@ function voidPlugin(options) {
|
|
|
5149
5765
|
config(_, env) {
|
|
5150
5766
|
syncFrameworkCompat(ensureWranglerCompat(root, config));
|
|
5151
5767
|
if (env.command !== "serve") return;
|
|
5152
|
-
if (ensureWranglerNodejsAlsFlag(root)) voidLog("Synced nodejs_als to
|
|
5768
|
+
if (ensureWranglerNodejsAlsFlag(root)) voidLog("Synced nodejs_als to Cloudflare config");
|
|
5153
5769
|
},
|
|
5154
5770
|
buildStart() {
|
|
5155
5771
|
syncFrameworkCompat(ensureWranglerCompat(root, config));
|
|
@@ -5206,6 +5822,7 @@ function voidPlugin(options) {
|
|
|
5206
5822
|
...nuxtVite8WebSocketCompatPlugin ? [nuxtVite8WebSocketCompatPlugin] : [],
|
|
5207
5823
|
svelteKitHooksInjectPlugin,
|
|
5208
5824
|
clientStubsPlugin,
|
|
5825
|
+
serverRuntimeOptimizerPlugin,
|
|
5209
5826
|
bindingRuntimePlugin(bindingNames),
|
|
5210
5827
|
envSchemaPlugin(root),
|
|
5211
5828
|
envClientGuardPlugin(root),
|
|
@@ -5213,9 +5830,10 @@ function voidPlugin(options) {
|
|
|
5213
5830
|
drizzlePlugin(root, false, dialect, {
|
|
5214
5831
|
d1BindingName: bindingNames?.d1,
|
|
5215
5832
|
forceVirtualDb: authEnabled || bindingNames?.d1 !== void 0,
|
|
5833
|
+
localD1DatabaseId: localD1.databaseId,
|
|
5216
5834
|
localD1PersistRoot: frameworkPersistRoot
|
|
5217
5835
|
}),
|
|
5218
|
-
migrationPlugin(root, dialect,
|
|
5836
|
+
migrationPlugin(root, dialect, localD1.databaseId, frameworkPersistRoot, { enabled: false }),
|
|
5219
5837
|
devTriggersHintPlugin(root, {
|
|
5220
5838
|
framework: true,
|
|
5221
5839
|
devTriggerToken
|
|
@@ -5228,6 +5846,9 @@ function voidPlugin(options) {
|
|
|
5228
5846
|
}
|
|
5229
5847
|
const remoteMode = resolveRemoteMode(config.remote);
|
|
5230
5848
|
const workerConfig = {};
|
|
5849
|
+
const jobs = scanJobsSync(root, paths.cronsDir);
|
|
5850
|
+
if (jobs.length > 0) workerConfig.triggers = { crons: [...new Set(jobs.flatMap((job) => job.crons))] };
|
|
5851
|
+
let envSchemaFacts;
|
|
5231
5852
|
let assetRouting;
|
|
5232
5853
|
if (config.worker?.vars) workerConfig.vars = { ...config.worker.vars };
|
|
5233
5854
|
let viteCommand = "build";
|
|
@@ -5245,6 +5866,23 @@ function voidPlugin(options) {
|
|
|
5245
5866
|
function mergeBindings(resolved) {
|
|
5246
5867
|
const environmentWebsocketRoutes = websocketRoutes.filter((route) => isRouteEnabledForEnvironment(route, routeEnvironment));
|
|
5247
5868
|
const result = { ...workerConfig };
|
|
5869
|
+
result.compatibility_flags = [.../* @__PURE__ */ new Set([...result.compatibility_flags ?? [], ...resolved.compatibility_flags ?? []])];
|
|
5870
|
+
resolved.compatibility_flags = [];
|
|
5871
|
+
if (envSchemaFacts || authEnabled && process.env["VOID_CLOUDFLARE_DEPLOY_BUILD"] === "1") {
|
|
5872
|
+
const plaintextVars = {
|
|
5873
|
+
...resolved.vars ?? {},
|
|
5874
|
+
...result.vars ?? {}
|
|
5875
|
+
};
|
|
5876
|
+
const plaintextServerKeys = (envSchemaFacts?.serverKeys ?? []).filter((key) => key in plaintextVars);
|
|
5877
|
+
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.`);
|
|
5878
|
+
const configuredRequired = resolved.secrets?.required ?? [];
|
|
5879
|
+
const required = [.../* @__PURE__ */ new Set([
|
|
5880
|
+
...configuredRequired,
|
|
5881
|
+
...envSchemaFacts?.requiredServerKeys ?? [],
|
|
5882
|
+
...authEnabled && process.env["VOID_CLOUDFLARE_DEPLOY_BUILD"] === "1" ? ["BETTER_AUTH_SECRET"] : []
|
|
5883
|
+
])];
|
|
5884
|
+
if (required.length > 0) result.secrets = { required };
|
|
5885
|
+
}
|
|
5248
5886
|
if (workerConfig.assets && resolved.assets) {
|
|
5249
5887
|
delete resolved.assets.not_found_handling;
|
|
5250
5888
|
delete resolved.assets.run_worker_first;
|
|
@@ -5269,10 +5907,41 @@ function voidPlugin(options) {
|
|
|
5269
5907
|
binding: r2Name,
|
|
5270
5908
|
bucket_name: "default"
|
|
5271
5909
|
}];
|
|
5272
|
-
|
|
5273
|
-
|
|
5910
|
+
const resolvedAi = resolved.ai;
|
|
5911
|
+
const resultAi = result.ai;
|
|
5912
|
+
const aiBindingName = resolveWorkersAiBindingName(resolvedAi, bindingNames?.ai);
|
|
5913
|
+
if (viteCommand === "serve" && bindings.needsAI && directCloudflareDestination && !resultAi && typeof resolvedAi === "object" && resolvedAi !== null && "binding" in resolvedAi && typeof resolvedAi.binding === "string") result.ai = {
|
|
5914
|
+
...resolvedAi,
|
|
5915
|
+
remote: true
|
|
5916
|
+
};
|
|
5917
|
+
else if (shouldBindWorkersAi(viteCommand, bindings.needsAI, resolvedAi, resultAi, directCloudflareDestination)) result.ai = {
|
|
5918
|
+
binding: aiBindingName,
|
|
5919
|
+
...viteCommand === "serve" && { remote: true }
|
|
5920
|
+
};
|
|
5921
|
+
if (aiBindingName !== "AI" || config.ai?.gateway) {
|
|
5922
|
+
const vars = result.vars ?? {};
|
|
5923
|
+
if (aiBindingName !== "AI") vars.__VOID_AI_BINDING = aiBindingName;
|
|
5924
|
+
if (config.ai?.gateway) vars.__VOID_AI_GATEWAY = config.ai.gateway;
|
|
5925
|
+
result.vars = vars;
|
|
5926
|
+
}
|
|
5927
|
+
const emailDevInboxBinding = workerConfig.assets?.binding ?? resolved.assets?.binding;
|
|
5928
|
+
if (shouldInjectEmailDevInboxVar(routeEnvironment, bindings.needsEmail, emailDevInboxBinding)) {
|
|
5929
|
+
const vars = result.vars ?? {};
|
|
5930
|
+
vars[DEV_INBOX_ENV_VAR] = emailDevInboxBinding;
|
|
5931
|
+
vars[DEV_INBOX_TOKEN_ENV_VAR] = devTriggerToken;
|
|
5932
|
+
result.vars = vars;
|
|
5933
|
+
}
|
|
5934
|
+
if (viteCommand === "serve" && bindings.needsEmail) {
|
|
5935
|
+
const sendEmail = resolved.send_email;
|
|
5936
|
+
if (Array.isArray(sendEmail)) {
|
|
5937
|
+
const kept = sendEmail.filter((entry) => entry?.name !== SEND_EMAIL_BINDING);
|
|
5938
|
+
if (kept.length > 0) resolved.send_email = kept;
|
|
5939
|
+
else delete resolved.send_email;
|
|
5940
|
+
}
|
|
5941
|
+
}
|
|
5942
|
+
if (viteCommand === "serve" && config.email?.from) {
|
|
5274
5943
|
const vars = result.vars ?? {};
|
|
5275
|
-
vars.
|
|
5944
|
+
vars.__VOID_EMAIL_FROM = config.email.from;
|
|
5276
5945
|
result.vars = vars;
|
|
5277
5946
|
}
|
|
5278
5947
|
if (queues.length > 0) result.queues = {
|
|
@@ -5290,15 +5959,38 @@ function voidPlugin(options) {
|
|
|
5290
5959
|
};
|
|
5291
5960
|
if (environmentWebsocketRoutes.length > 0) {
|
|
5292
5961
|
const existingDurableObjectBindings = resolved.durable_objects?.bindings ?? [];
|
|
5962
|
+
for (const route of environmentWebsocketRoutes) {
|
|
5963
|
+
const conflict = existingDurableObjectBindings.find((binding) => binding.name === route.bindingName && binding.class_name !== route.className);
|
|
5964
|
+
if (conflict) throw new Error(`websocket: binding '${route.bindingName}' is already configured for class '${conflict.class_name}', but '${route.filePath}' requires '${route.className}'.`);
|
|
5965
|
+
}
|
|
5293
5966
|
const missingDurableObjectBindings = environmentWebsocketRoutes.filter((route) => !existingDurableObjectBindings.some((binding) => binding.name === route.bindingName)).map((route) => ({
|
|
5294
5967
|
name: route.bindingName,
|
|
5295
5968
|
class_name: route.className
|
|
5296
5969
|
}));
|
|
5297
5970
|
if (missingDurableObjectBindings.length > 0) result.durable_objects = { bindings: [...existingDurableObjectBindings, ...missingDurableObjectBindings] };
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5971
|
+
const currentMigrations = resolved.migrations;
|
|
5972
|
+
const planned = appendSqliteClassMigration(Array.isArray(currentMigrations) ? currentMigrations : [], environmentWebsocketRoutes.map((route) => route.className), "void-ws-v1", existingDurableObjectBindings.map((binding) => binding.class_name));
|
|
5973
|
+
if (planned.added) result.migrations = planned.migrations;
|
|
5974
|
+
}
|
|
5975
|
+
if (durableObjects.length > 0) {
|
|
5976
|
+
const existingBindings = (result.durable_objects ?? resolved.durable_objects)?.bindings ?? [];
|
|
5977
|
+
for (const module of durableObjects) {
|
|
5978
|
+
const conflict = existingBindings.find((binding) => binding.name === module.bindingName && binding.class_name !== module.className);
|
|
5979
|
+
if (conflict) throw new Error(`durable: binding '${module.bindingName}' is already configured for class '${conflict.class_name}', but durable-objects/ requires '${module.className}'.`);
|
|
5980
|
+
}
|
|
5981
|
+
const additions = durableObjects.filter((module) => !existingBindings.some((binding) => binding.name === module.bindingName)).map((module) => ({
|
|
5982
|
+
name: module.bindingName,
|
|
5983
|
+
class_name: module.className
|
|
5984
|
+
}));
|
|
5985
|
+
if (additions.length > 0) result.durable_objects = { bindings: [...existingBindings, ...additions] };
|
|
5986
|
+
const currentMigrations = result.migrations ?? resolved.migrations;
|
|
5987
|
+
const existingMigrations = Array.isArray(currentMigrations) ? currentMigrations : [];
|
|
5988
|
+
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.`);
|
|
5989
|
+
const migrationAdditions = durableObjects.filter((module) => !existingMigrations.some((migration) => migration.tag === module.migrationTag || migration.new_sqlite_classes?.includes(module.className))).map((module) => ({
|
|
5990
|
+
tag: module.migrationTag,
|
|
5991
|
+
new_sqlite_classes: [module.className]
|
|
5992
|
+
}));
|
|
5993
|
+
if (migrationAdditions.length > 0) result.migrations = [...existingMigrations, ...migrationAdditions];
|
|
5302
5994
|
}
|
|
5303
5995
|
if (bindings.needsSandbox && sandboxConfig) {
|
|
5304
5996
|
const existingDurableObjectBindings = (result.durable_objects ?? resolved.durable_objects)?.bindings ?? [];
|
|
@@ -5335,12 +6027,13 @@ function voidPlugin(options) {
|
|
|
5335
6027
|
new_sqlite_classes: [liveConfig.className]
|
|
5336
6028
|
}];
|
|
5337
6029
|
}
|
|
5338
|
-
if (viteCommand === "serve" && bindings.needsAI) {
|
|
6030
|
+
if (viteCommand === "serve" && bindings.needsAI && !directCloudflareDestination) {
|
|
5339
6031
|
const credentials = readVoidDevCredentials(root);
|
|
5340
6032
|
if (credentials.status === "ok") {
|
|
5341
6033
|
const vars = result.vars ?? {};
|
|
5342
6034
|
vars.__VOID_TOKEN = credentials.token;
|
|
5343
6035
|
vars.__VOID_PROJECT_ID = credentials.projectId;
|
|
6036
|
+
vars.__VOID_PROXY_URL = credentials.proxyUrl;
|
|
5344
6037
|
if (credentials.staging) vars.__VOID_STAGING = "1";
|
|
5345
6038
|
result.vars = vars;
|
|
5346
6039
|
}
|
|
@@ -5349,7 +6042,7 @@ function voidPlugin(options) {
|
|
|
5349
6042
|
const credentials = readVoidDevCredentials(root);
|
|
5350
6043
|
if (credentials.status === "ok") {
|
|
5351
6044
|
const vars = result.vars ?? {};
|
|
5352
|
-
vars.__VOID_PROXY_URL = credentials.
|
|
6045
|
+
vars.__VOID_PROXY_URL = credentials.proxyUrl;
|
|
5353
6046
|
vars.__VOID_TOKEN = credentials.token;
|
|
5354
6047
|
vars.__VOID_PROJECT_ID = credentials.projectId;
|
|
5355
6048
|
vars.__VOID_REMOTE = "1";
|
|
@@ -5358,34 +6051,32 @@ function voidPlugin(options) {
|
|
|
5358
6051
|
}
|
|
5359
6052
|
return result;
|
|
5360
6053
|
}
|
|
5361
|
-
function
|
|
5362
|
-
|
|
5363
|
-
for (const [key, value] of Object.entries(defaults)) if (vars[key] === void 0) vars[key] = value;
|
|
5364
|
-
workerConfig.vars = vars;
|
|
6054
|
+
function applyEnvSchema(facts) {
|
|
6055
|
+
envSchemaFacts = facts;
|
|
5365
6056
|
}
|
|
5366
|
-
let voidDeployBuildConfig;
|
|
5367
6057
|
const envPlugin = {
|
|
5368
6058
|
name: "void:env",
|
|
5369
|
-
|
|
5370
|
-
config(userConfig, { mode, command, isPreview }) {
|
|
6059
|
+
config(userConfig, { command, isPreview }) {
|
|
5371
6060
|
viteCommand = command;
|
|
5372
6061
|
routeEnvironment = command === "serve" && !isPreview ? "dev" : "prod";
|
|
6062
|
+
if (command === "serve" && directCloudflareDestination && bindings.needsAI) process.env.CLOUDFLARE_AUTH_USE_KEYRING = "true";
|
|
5373
6063
|
if (!framework && !isNodeTarget(config.target)) {
|
|
6064
|
+
managedCloudflareBuild = command === "build" && Boolean(process.env.VOID_DEPLOY_PROJECT_ID);
|
|
6065
|
+
assetRoutingPublicDir = userConfig.publicDir === false ? null : typeof userConfig.publicDir === "string" ? resolve(root, userConfig.publicDir) : join(root, "public");
|
|
5374
6066
|
assetRouting = resolveConfiguredAssetRoutingPolicy();
|
|
5375
6067
|
applyAssetRoutingPolicy(assetRouting);
|
|
5376
6068
|
}
|
|
5377
6069
|
const ignored = ["**/.void/**"];
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
};
|
|
6070
|
+
if (command === "serve") {
|
|
6071
|
+
const local = loadLocalEnv(root, { onWarn: (message) => voidWarn(message) });
|
|
6072
|
+
const { sanitized: env, stripped } = stripInternalEnvKeys(local);
|
|
6073
|
+
if (stripped.length > 0) voidWarn(`Ignoring internal env keys from .env: ${stripped.join(", ")}. These are reserved for Void runtime use.`);
|
|
6074
|
+
workerConfig.vars = {
|
|
6075
|
+
...workerConfig.vars,
|
|
6076
|
+
...env
|
|
6077
|
+
};
|
|
6078
|
+
if (isPreview) for (const [key, value] of Object.entries(env)) process.env[key] ??= value;
|
|
6079
|
+
}
|
|
5389
6080
|
const assets = workerConfig.assets;
|
|
5390
6081
|
if (command === "serve" && !isPreview && assets?.run_worker_first?.includes("/**")) assets.run_worker_first = [...DEV_ASSET_ROUTING_EXCLUSIONS, "/**"];
|
|
5391
6082
|
const watchConfig = { server: { watch: { ignored } } };
|
|
@@ -5425,20 +6116,22 @@ function voidPlugin(options) {
|
|
|
5425
6116
|
voidWarn("Falling back to local bindings.");
|
|
5426
6117
|
});
|
|
5427
6118
|
}
|
|
5428
|
-
if (bindings.needsAI) {
|
|
6119
|
+
if (bindings.needsAI && !directCloudflareDestination) {
|
|
5429
6120
|
const credentials = readVoidDevCredentials(root);
|
|
5430
6121
|
if (credentials.status === "no-token") afterReady(() => {
|
|
5431
6122
|
console.log();
|
|
5432
6123
|
voidWarn("AI requires authentication. Run `void auth login`, then restart the dev server.");
|
|
5433
6124
|
});
|
|
5434
|
-
else if (credentials.status === "no-project")
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
6125
|
+
else if (credentials.status === "no-project") {
|
|
6126
|
+
if (process.stdin.isTTY) afterReady(() => {
|
|
6127
|
+
console.log();
|
|
6128
|
+
runAiSetupPrompt(root, credentials.token, credentials.apiUrl, server);
|
|
6129
|
+
});
|
|
6130
|
+
else afterReady(() => {
|
|
6131
|
+
console.log();
|
|
6132
|
+
voidWarn("AI requires a linked project. Run `void project link` to set one up.");
|
|
6133
|
+
});
|
|
6134
|
+
}
|
|
5442
6135
|
}
|
|
5443
6136
|
}
|
|
5444
6137
|
};
|
|
@@ -5455,7 +6148,8 @@ function voidPlugin(options) {
|
|
|
5455
6148
|
if (hintShown) return;
|
|
5456
6149
|
if (!watchDirs.some((d) => path.startsWith(d))) return;
|
|
5457
6150
|
try {
|
|
5458
|
-
const
|
|
6151
|
+
const code = readFileSync(path, "utf-8");
|
|
6152
|
+
const fileBindings = inferBindingsFromSource(code, path.split("/").pop());
|
|
5459
6153
|
const newBindings = [];
|
|
5460
6154
|
if (autoDetectBindings) {
|
|
5461
6155
|
if (fileBindings.needsD1 && !bindings.needsD1) newBindings.push("D1 (void/db)");
|
|
@@ -5463,6 +6157,7 @@ function voidPlugin(options) {
|
|
|
5463
6157
|
if (fileBindings.needsR2 && !bindings.needsR2) newBindings.push("R2 (void/storage)");
|
|
5464
6158
|
if (fileBindings.needsAI && !bindings.needsAI) newBindings.push("AI (void/ai)");
|
|
5465
6159
|
if (fileBindings.needsSandbox && !bindings.needsSandbox) newBindings.push("Sandbox (void/sandbox)");
|
|
6160
|
+
if (fileBindings.needsEmail && !bindings.needsEmail) newBindings.push("Email (void/email)");
|
|
5466
6161
|
}
|
|
5467
6162
|
if (autoDetectAuth && fileBindings.needsAuth) newBindings.push("Auth (void/auth)");
|
|
5468
6163
|
if (newBindings.length > 0) {
|
|
@@ -5496,7 +6191,7 @@ function voidPlugin(options) {
|
|
|
5496
6191
|
if (resolved.command !== "build") return;
|
|
5497
6192
|
if (config.routing?.notFound !== void 0 && !process.env.VOID_DEPLOY_BUILD && !notFoundIgnoredWarned) {
|
|
5498
6193
|
notFoundIgnoredWarned = true;
|
|
5499
|
-
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.
|
|
6194
|
+
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.`);
|
|
5500
6195
|
}
|
|
5501
6196
|
generateClassATriggerWrapper(root, framework, getOriginalFrameworkEntry(framework, root), true, resolved.build.assetsDir, config.routing?.notFound);
|
|
5502
6197
|
}
|
|
@@ -5525,19 +6220,22 @@ function voidPlugin(options) {
|
|
|
5525
6220
|
createWranglerCompatPersistPlugin(root, config),
|
|
5526
6221
|
restartPlugin(),
|
|
5527
6222
|
bindingWatchPlugin,
|
|
6223
|
+
...bindings.needsEmail ? [emailDevInboxPlugin({ devTriggerToken })] : [],
|
|
5528
6224
|
envPlugin,
|
|
5529
|
-
envSchemaPlugin(root, {
|
|
6225
|
+
envSchemaPlugin(root, { onSchema: applyEnvSchema }),
|
|
5530
6226
|
envClientGuardPlugin(root),
|
|
5531
6227
|
envClientFoldPlugin(),
|
|
5532
6228
|
clientStubsPlugin,
|
|
6229
|
+
serverRuntimeOptimizerPlugin,
|
|
5533
6230
|
bindingRuntimePlugin(bindingNames),
|
|
5534
6231
|
drizzlePlugin(root, false, getDatabaseDialect(config), {
|
|
5535
6232
|
d1BindingName: bindingNames?.d1,
|
|
5536
6233
|
forceVirtualDb: authEnabled || bindingNames?.d1 !== void 0,
|
|
5537
|
-
|
|
6234
|
+
localD1DatabaseId: localD1.databaseId,
|
|
6235
|
+
localD1PersistRoot: localD1.persistRoot,
|
|
5538
6236
|
redirectDbTypePaths
|
|
5539
6237
|
}),
|
|
5540
|
-
migrationPlugin(root, getDatabaseDialect(config)),
|
|
6238
|
+
migrationPlugin(root, getDatabaseDialect(config), localD1.databaseId, localD1.persistRoot),
|
|
5541
6239
|
...vinextCompat ? [vinextCompat] : [],
|
|
5542
6240
|
frameworkBuildWrapperPlugin,
|
|
5543
6241
|
frameworkTriggersPlugin(root, { devTriggerToken }),
|
|
@@ -5547,7 +6245,7 @@ function voidPlugin(options) {
|
|
|
5547
6245
|
}),
|
|
5548
6246
|
...cloudflare({
|
|
5549
6247
|
...inspectorPortOption,
|
|
5550
|
-
persistState: { path:
|
|
6248
|
+
persistState: { path: localD1.persistRoot },
|
|
5551
6249
|
auxiliaryWorkers: options?.auxiliaryWorkers,
|
|
5552
6250
|
viteEnvironment,
|
|
5553
6251
|
config: mergeBindings
|
|
@@ -5561,10 +6259,13 @@ function voidPlugin(options) {
|
|
|
5561
6259
|
if (config.remote) voidWarn("\"remote\" in void.json is ignored with target: \"" + config.target + "\"");
|
|
5562
6260
|
if (bindings.needsSandbox) throw new Error(`sandbox: Cloudflare Sandboxes require target: "cloudflare". They are not available with target: '${config.target}'.`);
|
|
5563
6261
|
if (bindings.needsLive) throw new Error(`live: void/live requires target: "cloudflare". It is not available with target: '${config.target}'.`);
|
|
6262
|
+
if (durableObjects.length > 0) throw new Error(`durable: durable-objects/ requires target: "cloudflare". It is not available with target: '${config.target}'.`);
|
|
6263
|
+
if (hasInboundEmail) throw new Error(`email: inbound email handlers (email/) require target: "cloudflare". They are not available with target: '${config.target}'.`);
|
|
5564
6264
|
if (config.routing?.revalidate) voidWarn("\"routing.revalidate\" in void.json is ignored with target: \"" + config.target + "\" (edge caching is CF-only)");
|
|
5565
6265
|
return [
|
|
5566
6266
|
restartPlugin(),
|
|
5567
6267
|
envPlugin,
|
|
6268
|
+
serverRuntimeOptimizerPlugin,
|
|
5568
6269
|
envSchemaPlugin(root),
|
|
5569
6270
|
...pagesDevCssAssetsPlugin(root, devTriggerToken),
|
|
5570
6271
|
routingPlugin(root, {
|
|
@@ -5582,16 +6283,18 @@ function voidPlugin(options) {
|
|
|
5582
6283
|
];
|
|
5583
6284
|
}
|
|
5584
6285
|
const existingFlags = workerConfig.compatibility_flags ?? [];
|
|
5585
|
-
const
|
|
6286
|
+
const needsNodejsCompat = authEnabled || dialect !== "sqlite" || bindings.needsSandbox;
|
|
6287
|
+
const normalizedFlags = normalizeWranglerCompatibilityFlags(existingFlags, { needsNodejsCompat });
|
|
5586
6288
|
if (normalizedFlags && normalizedFlags !== existingFlags) workerConfig.compatibility_flags = normalizedFlags;
|
|
5587
|
-
const jobs = scanJobsSync(root, paths.cronsDir);
|
|
5588
6289
|
const ssrEntry = validateSsrEntry(root, paths);
|
|
5589
6290
|
const hasPages = existsSync(paths.pagesDir);
|
|
5590
6291
|
const hasMiddleware = scanMiddlewareSync(root, paths).length > 0;
|
|
6292
|
+
let assetRoutingPublicDir = join(root, "public");
|
|
6293
|
+
let managedCloudflareBuild = false;
|
|
5591
6294
|
function resolveConfiguredAssetRoutingPolicy() {
|
|
5592
6295
|
const routePatterns = scanRoutePatternsSync(root, paths, routeEnvironment);
|
|
5593
6296
|
const environmentWebsocketRoutes = websocketRoutes.filter((route) => isRouteEnabledForEnvironment(route, routeEnvironment));
|
|
5594
|
-
|
|
6297
|
+
const policy = resolveAssetRoutingPolicy({
|
|
5595
6298
|
isSsr: Boolean(ssrEntry),
|
|
5596
6299
|
hasPages,
|
|
5597
6300
|
hasApiRoutes: hasApiRoutes(routePatterns) || hasApiRoutes(environmentWebsocketRoutes) || authEnabled,
|
|
@@ -5602,10 +6305,21 @@ function voidPlugin(options) {
|
|
|
5602
6305
|
liveEnabled: liveConfig !== void 0,
|
|
5603
6306
|
notFound: config.routing?.notFound
|
|
5604
6307
|
});
|
|
6308
|
+
const rules = mergeRoutingRules({
|
|
6309
|
+
dir: assetRoutingPublicDir,
|
|
6310
|
+
routing: config.routing
|
|
6311
|
+
});
|
|
6312
|
+
if (!managedCloudflareBuild && (rules.headerRules.length > 0 || rules.redirectRules.length > 0 || (rules.fallbackRules?.length ?? 0) > 0)) {
|
|
6313
|
+
policy.assetConfig.run_worker_first = ["/**"];
|
|
6314
|
+
if (rules.fallbackRules?.length && policy.assetConfig.not_found_handling === "single-page-application") {
|
|
6315
|
+
policy.assetConfig.not_found_handling = "none";
|
|
6316
|
+
policy.workerSpaFallback = true;
|
|
6317
|
+
}
|
|
6318
|
+
}
|
|
6319
|
+
return policy;
|
|
5605
6320
|
}
|
|
5606
6321
|
assetRouting = resolveConfiguredAssetRoutingPolicy();
|
|
5607
6322
|
workerConfig.main = join(root, ".void", "entry.ts");
|
|
5608
|
-
if (jobs.length > 0) workerConfig.triggers = { crons: jobs.flatMap((job) => job.crons) };
|
|
5609
6323
|
function applyAssetRoutingPolicy(policy) {
|
|
5610
6324
|
workerConfig.assets = {
|
|
5611
6325
|
binding: "ASSETS",
|
|
@@ -5627,11 +6341,13 @@ function voidPlugin(options) {
|
|
|
5627
6341
|
createWranglerCompatPersistPlugin(root, config),
|
|
5628
6342
|
restartPlugin(),
|
|
5629
6343
|
bindingWatchPlugin,
|
|
6344
|
+
...bindings.needsEmail ? [emailDevInboxPlugin({ devTriggerToken })] : [],
|
|
5630
6345
|
envPlugin,
|
|
5631
|
-
envSchemaPlugin(root, {
|
|
6346
|
+
envSchemaPlugin(root, { onSchema: applyEnvSchema }),
|
|
5632
6347
|
envClientGuardPlugin(root),
|
|
5633
6348
|
envClientFoldPlugin(),
|
|
5634
6349
|
clientStubsPlugin,
|
|
6350
|
+
serverRuntimeOptimizerPlugin,
|
|
5635
6351
|
bindingRuntimePlugin(bindingNames),
|
|
5636
6352
|
...bindings.needsSandbox ? [createSandboxSdkResolvePlugin()] : [],
|
|
5637
6353
|
...pagesDevCssAssetsPlugin(root, devTriggerToken),
|
|
@@ -5648,14 +6364,17 @@ function voidPlugin(options) {
|
|
|
5648
6364
|
sandboxBindingName: sandboxConfig?.binding,
|
|
5649
6365
|
sandboxClassName: sandboxConfig?.className,
|
|
5650
6366
|
live: liveConfig,
|
|
6367
|
+
durableObjects,
|
|
6368
|
+
websocketTombstones,
|
|
5651
6369
|
onDevAssetRoutingPolicyChange: updateDevAssetRoutingPolicy
|
|
5652
6370
|
}),
|
|
5653
6371
|
drizzlePlugin(root, true, dialect, {
|
|
5654
6372
|
d1BindingName: bindingNames?.d1,
|
|
5655
6373
|
forceVirtualDb: authEnabled || bindingNames?.d1 !== void 0,
|
|
5656
|
-
|
|
6374
|
+
localD1DatabaseId: localD1.databaseId,
|
|
6375
|
+
localD1PersistRoot: localD1.persistRoot
|
|
5657
6376
|
}),
|
|
5658
|
-
migrationPlugin(root, dialect,
|
|
6377
|
+
migrationPlugin(root, dialect, localD1.databaseId, localD1.persistRoot, {
|
|
5659
6378
|
enabled: authEnabled,
|
|
5660
6379
|
configPath: authConfigPath
|
|
5661
6380
|
}),
|
|
@@ -5666,7 +6385,7 @@ function voidPlugin(options) {
|
|
|
5666
6385
|
}),
|
|
5667
6386
|
...cloudflare({
|
|
5668
6387
|
...inspectorPortOption,
|
|
5669
|
-
persistState: { path:
|
|
6388
|
+
persistState: { path: localD1.persistRoot },
|
|
5670
6389
|
auxiliaryWorkers: options?.auxiliaryWorkers,
|
|
5671
6390
|
viteEnvironment: { name: DEFAULT_WORKER_ENVIRONMENT_NAME },
|
|
5672
6391
|
config: mergeBindings
|
|
@@ -5674,4 +6393,4 @@ function voidPlugin(options) {
|
|
|
5674
6393
|
];
|
|
5675
6394
|
}
|
|
5676
6395
|
//#endregion
|
|
5677
|
-
export { VoidAssetRewriteError, basicAuth, defer, defineHandler, defineHead, defineMiddleware, defineQueue, defineRender, defineScheduled, shouldBindWorkersAi, voidPlugin };
|
|
6396
|
+
export { VoidAssetRewriteError, basicAuth, defer, defineHandler, defineHead, defineMiddleware, defineQueue, defineRender, defineScheduled, resolveWorkersAiBindingName, shouldBindWorkersAi, shouldInjectEmailDevInboxVar, voidPlugin };
|