void 0.1.6 → 0.7.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/AGENT_PROMPT.md +15 -0
- package/README.md +62 -123
- package/dist/auth-BdsJ0Aff.d.mts +43 -0
- package/dist/auth-cmd-DVKi6dzh.mjs +43 -0
- package/dist/auth-migrations-BAtAck2g.mjs +117 -0
- package/dist/better-auth-shared-C9_GHSkR.d.mts +71 -0
- package/dist/better-auth-shared-CdYmQGry.mjs +163 -0
- package/dist/cache-B0BgSTZi.mjs +47 -0
- package/dist/cancel-deploy-D9OFt5gA.mjs +59 -0
- package/dist/cf-access-Dee5cXxL.mjs +22 -0
- package/dist/chunk-DJd-R1mw.mjs +34 -0
- package/dist/cli/cli.d.mts +1 -0
- package/dist/cli/cli.mjs +1814 -0
- package/dist/client-BUdfE3QJ.mjs +622 -0
- package/dist/collect-CjeZgz5D.mjs +55 -0
- package/dist/config-BIa9HwVX.mjs +573 -0
- package/dist/config-BzM9Dy7T.mjs +37 -0
- package/dist/config-CvHtTM0q.mjs +30 -0
- package/dist/create-project-CN1pF-OQ.mjs +90 -0
- package/dist/db-BIP2kuEt.mjs +895 -0
- package/dist/defer-DcxEsVH1.mjs +49 -0
- package/dist/delete-DJTvwbr-.mjs +64 -0
- package/dist/deploy-BqXz1ycW.mjs +2723 -0
- package/dist/discover-B7FkXBLB.mjs +40 -0
- package/dist/dist-DUyXJLkq.mjs +2667 -0
- package/dist/dist-Dayj3gCK.mjs +1287 -0
- package/dist/domain-B-fIU3VE.mjs +79 -0
- package/dist/dotenv-DwO4ti0Z.mjs +173 -0
- package/dist/drizzle-NnudE_UN.mjs +232 -0
- package/dist/env-BwbZJd2x.mjs +301 -0
- package/dist/env-helpers-Dr9Y7RnE.d.mts +52 -0
- package/dist/env-raw-BDL4TvdN.mjs +32 -0
- package/dist/env-types-DknSA4SO.mjs +64 -0
- package/dist/env-validation-DJKjR_8q.mjs +163 -0
- package/dist/fetch-error-BQ8sZ5Nd.mjs +266 -0
- package/dist/fetch-error-CVZ5CGA-.d.mts +20 -0
- package/dist/gen-U0Ktr4Zd.mjs +761 -0
- package/dist/handler-B0ds0OHJ.d.mts +269 -0
- package/dist/head-P-egrtFE.d.mts +45 -0
- package/dist/headers-DCXc7mDs.mjs +279 -0
- package/dist/index.d.mts +32 -0
- package/dist/index.mjs +4695 -0
- package/dist/init-Bb_Qsdq6.mjs +2625 -0
- package/dist/link-D4d26PCm.mjs +49 -0
- package/dist/list-bQc1eQCZ.mjs +113 -0
- package/dist/log-DXdqnmhF.mjs +26 -0
- package/dist/login-RWUDCfdx.mjs +72 -0
- package/dist/logs-DrkTklop.mjs +98 -0
- package/dist/magic-string.es-D6g9UnIy.mjs +1011 -0
- package/dist/mcp-kZ4zg13a.mjs +373 -0
- package/dist/node-DDfXj10V.mjs +54 -0
- package/dist/output-BwlcIYSR.mjs +139 -0
- package/dist/pages/client.d.mts +198 -0
- package/dist/pages/client.mjs +980 -0
- package/dist/pages/head-client.d.mts +15 -0
- package/dist/pages/head-client.mjs +90 -0
- package/dist/pages/head.d.mts +2 -0
- package/dist/pages/head.mjs +112 -0
- package/dist/pages/index.d.mts +38 -0
- package/dist/pages/index.mjs +76 -0
- package/dist/pages/islands-plugin.d.mts +50 -0
- package/dist/pages/islands-plugin.mjs +195 -0
- package/dist/pages/prefetch.d.mts +31 -0
- package/dist/pages/prefetch.mjs +90 -0
- package/dist/pages/protocol.d.mts +3 -0
- package/dist/pages/protocol.mjs +193 -0
- package/dist/pages/serialize.d.mts +10 -0
- package/dist/pages/serialize.mjs +14 -0
- package/dist/pathe.M-eThtNZ-D-kmWkCS.mjs +150 -0
- package/dist/plugin-inference-oZ6Ybu2_.mjs +2447 -0
- package/dist/prepare-BAtWufvm.mjs +99 -0
- package/dist/preset-D4I73kT4.mjs +221 -0
- package/dist/project-TqORyHn8.mjs +72 -0
- package/dist/project-cmd-ATFi3kRm.mjs +67 -0
- package/dist/project-slug-CKam8lF9.mjs +11 -0
- package/dist/project-tsconfig-DfkESbDL.mjs +63 -0
- package/dist/protocol-BWzXs2A2.d.mts +34 -0
- package/dist/providers-B3aMxWzP.mjs +67 -0
- package/dist/resolve-project-Br5BR03U.mjs +29 -0
- package/dist/rollback-BSyita3C.mjs +92 -0
- package/dist/route-types-DReF1gUY.mjs +255 -0
- package/dist/routes-stub.d.mts +55 -0
- package/dist/routes-stub.mjs +1 -0
- package/dist/runner-6Ep3fNQu.mjs +123 -0
- package/dist/runner-pg-D0wWHYnr.mjs +57 -0
- package/dist/runtime/ai.d.mts +127 -0
- package/dist/runtime/ai.mjs +348 -0
- package/dist/runtime/auth-client-react.d.mts +8 -0
- package/dist/runtime/auth-client-react.mjs +6 -0
- package/dist/runtime/auth-client-solid.d.mts +8 -0
- package/dist/runtime/auth-client-solid.mjs +6 -0
- package/dist/runtime/auth-client-svelte.d.mts +8 -0
- package/dist/runtime/auth-client-svelte.mjs +6 -0
- package/dist/runtime/auth-client-vue.d.mts +8 -0
- package/dist/runtime/auth-client-vue.mjs +6 -0
- package/dist/runtime/auth-client.d.mts +8 -0
- package/dist/runtime/auth-client.mjs +6 -0
- package/dist/runtime/auth.d.mts +2 -0
- package/dist/runtime/auth.mjs +22 -0
- package/dist/runtime/better-auth-pg.d.mts +11 -0
- package/dist/runtime/better-auth-pg.mjs +51 -0
- package/dist/runtime/better-auth.d.mts +11 -0
- package/dist/runtime/better-auth.mjs +33 -0
- package/dist/runtime/client.d.mts +6 -0
- package/dist/runtime/client.mjs +5 -0
- package/dist/runtime/db-pg.d.mts +2 -0
- package/dist/runtime/db-pg.mjs +1 -0
- package/dist/runtime/db.d.mts +17 -0
- package/dist/runtime/db.mjs +30 -0
- package/dist/runtime/drizzle-arktype.d.mts +1 -0
- package/dist/runtime/drizzle-arktype.mjs +2 -0
- package/dist/runtime/drizzle-valibot.d.mts +1 -0
- package/dist/runtime/drizzle-valibot.mjs +2 -0
- package/dist/runtime/drizzle-zod.d.mts +1 -0
- package/dist/runtime/drizzle-zod.mjs +2 -0
- package/dist/runtime/env-helpers.d.mts +2 -0
- package/dist/runtime/env-helpers.mjs +173 -0
- package/dist/runtime/env-public-client.d.mts +22 -0
- package/dist/runtime/env-public-client.mjs +54 -0
- package/dist/runtime/env-public.d.mts +143 -0
- package/dist/runtime/env-public.mjs +366 -0
- package/dist/runtime/env.d.mts +13 -0
- package/dist/runtime/env.mjs +51 -0
- package/dist/runtime/fetch-stream.d.mts +51 -0
- package/dist/runtime/fetch-stream.mjs +81 -0
- package/dist/runtime/fetch.d.mts +59 -0
- package/dist/runtime/fetch.mjs +18 -0
- package/dist/runtime/handler.d.mts +3 -0
- package/dist/runtime/handler.mjs +85 -0
- package/dist/runtime/isr.d.mts +26 -0
- package/dist/runtime/isr.mjs +43 -0
- package/dist/runtime/kv.d.mts +48 -0
- package/dist/runtime/kv.mjs +106 -0
- package/dist/runtime/log.d.mts +24 -0
- package/dist/runtime/log.mjs +31 -0
- package/dist/runtime/migration-handler-pg.d.mts +6 -0
- package/dist/runtime/migration-handler-pg.mjs +85 -0
- package/dist/runtime/migration-handler.d.mts +19 -0
- package/dist/runtime/migration-handler.mjs +92 -0
- package/dist/runtime/queues.d.mts +7 -0
- package/dist/runtime/queues.mjs +8 -0
- package/dist/runtime/remote/binding-handler.d.mts +15 -0
- package/dist/runtime/remote/binding-handler.mjs +208 -0
- package/dist/runtime/remote/index.d.mts +8 -0
- package/dist/runtime/remote/index.mjs +461 -0
- package/dist/runtime/response.d.mts +14 -0
- package/dist/runtime/response.mjs +30 -0
- package/dist/runtime/sandbox.d.mts +17 -0
- package/dist/runtime/sandbox.mjs +19 -0
- package/dist/runtime/schema-d1.d.mts +1 -0
- package/dist/runtime/schema-d1.mjs +2 -0
- package/dist/runtime/schema-pg.d.mts +1 -0
- package/dist/runtime/schema-pg.mjs +2 -0
- package/dist/runtime/seed.d.mts +30 -0
- package/dist/runtime/seed.mjs +6 -0
- package/dist/runtime/storage.d.mts +7 -0
- package/dist/runtime/storage.mjs +14 -0
- package/dist/runtime/validator.d.mts +2 -0
- package/dist/runtime/validator.mjs +72 -0
- package/dist/runtime/ws-server.d.mts +26 -0
- package/dist/runtime/ws-server.mjs +296 -0
- package/dist/runtime/ws.d.mts +123 -0
- package/dist/runtime/ws.mjs +103 -0
- package/dist/scan-Ba4hFwlH.mjs +324 -0
- package/dist/scan-C6HMEIdW.mjs +318 -0
- package/dist/secret-DmjBDxB1.mjs +109 -0
- package/dist/skills-ipldjlKE.mjs +62 -0
- package/dist/standard-schema-9CRjx-uR.d.mts +42 -0
- package/dist/subcommand-prompt-BKjuNAPb.mjs +349 -0
- package/dist/sveltekit.d.mts +20 -0
- package/dist/sveltekit.mjs +61 -0
- package/dist/types-mHOEwpW4.d.mts +57 -0
- package/dist/validate-CaMavMxu.mjs +146 -0
- package/dist/yarn-pnp-BFqMV_bl.mjs +196 -0
- package/getting-started-prompt.txt +26 -0
- package/package.json +322 -30
- package/schema.json +364 -0
- package/skills/migrate-vite-cloudflare-to-void/SKILL.md +175 -0
- package/skills/void/SKILL.md +75 -0
- package/skills/void/command/void.md +7 -0
- package/skills/void/docs/guide/ai.md +235 -0
- package/skills/void/docs/guide/app-types.md +103 -0
- package/skills/void/docs/guide/auth.md +257 -0
- package/skills/void/docs/guide/database/d1.md +106 -0
- package/skills/void/docs/guide/database/postgresql.md +106 -0
- package/skills/void/docs/guide/database.md +418 -0
- package/skills/void/docs/guide/deployment.md +98 -0
- package/skills/void/docs/guide/edge/headers.md +79 -0
- package/skills/void/docs/guide/edge/prerendering.md +83 -0
- package/skills/void/docs/guide/edge/redirects.md +116 -0
- package/skills/void/docs/guide/edge/revalidation.md +131 -0
- package/skills/void/docs/guide/edge/rewrites.md +354 -0
- package/skills/void/docs/guide/edge/static-assets.md +72 -0
- package/skills/void/docs/guide/env-vars.md +298 -0
- package/skills/void/docs/guide/index.md +80 -0
- package/skills/void/docs/guide/jobs.md +91 -0
- package/skills/void/docs/guide/kv.md +107 -0
- package/skills/void/docs/guide/pages-routing/actions-and-forms.md +419 -0
- package/skills/void/docs/guide/pages-routing/head.md +130 -0
- package/skills/void/docs/guide/pages-routing/islands.md +405 -0
- package/skills/void/docs/guide/pages-routing/layouts.md +362 -0
- package/skills/void/docs/guide/pages-routing/loaders.md +267 -0
- package/skills/void/docs/guide/pages-routing/markdown.md +625 -0
- package/skills/void/docs/guide/pages-routing/overview.md +236 -0
- package/skills/void/docs/guide/pages-routing/view-transitions.md +140 -0
- package/skills/void/docs/guide/queues.md +140 -0
- package/skills/void/docs/guide/quickstart.md +233 -0
- package/skills/void/docs/guide/remote-dev.md +67 -0
- package/skills/void/docs/guide/sandboxes.md +82 -0
- package/skills/void/docs/guide/server-routing.md +246 -0
- package/skills/void/docs/guide/ssg.md +74 -0
- package/skills/void/docs/guide/ssr.md +105 -0
- package/skills/void/docs/guide/storage.md +67 -0
- package/skills/void/docs/guide/type-safety.md +179 -0
- package/skills/void/docs/guide/typed-fetch.md +113 -0
- package/skills/void/docs/guide/websockets.md +190 -0
- package/skills/void/docs/index.md +48 -0
- package/skills/void/docs/integrations/agents.md +84 -0
- package/skills/void/docs/integrations/cloudflare.md +284 -0
- package/skills/void/docs/integrations/frameworks/analog.md +182 -0
- package/skills/void/docs/integrations/frameworks/astro.md +197 -0
- package/skills/void/docs/integrations/frameworks/nuxt.md +164 -0
- package/skills/void/docs/integrations/frameworks/overview.md +136 -0
- package/skills/void/docs/integrations/frameworks/react-router.md +137 -0
- package/skills/void/docs/integrations/frameworks/sveltekit.md +191 -0
- package/skills/void/docs/integrations/frameworks/tanstack-start.md +140 -0
- package/skills/void/docs/integrations/hono.md +97 -0
- package/skills/void/docs/integrations/nodejs-bun-deno.md +210 -0
- package/skills/void/docs/node_modules/@iconify/vue/README.md +408 -0
- package/skills/void/docs/node_modules/@iconify/vue/offline/readme.md +5 -0
- package/skills/void/docs/node_modules/@voidzero-dev/vitepress-theme/README.md +103 -0
- package/skills/void/docs/node_modules/oxc-minify/README.md +78 -0
- package/skills/void/docs/node_modules/reka-ui/README.md +80 -0
- package/skills/void/docs/node_modules/vitepress/README.md +28 -0
- package/skills/void/docs/node_modules/vitepress/template/api-examples.md +49 -0
- package/skills/void/docs/node_modules/vitepress/template/index.md +28 -0
- package/skills/void/docs/node_modules/vitepress/template/markdown-examples.md +85 -0
- package/skills/void/docs/node_modules/vitepress-plugin-group-icons/README.md +101 -0
- package/skills/void/docs/node_modules/void/AGENTS.md +204 -0
- package/skills/void/docs/node_modules/void/AGENT_PROMPT.md +15 -0
- package/skills/void/docs/node_modules/void/README.md +89 -0
- package/skills/void/docs/node_modules/void/node_modules/@clack/prompts/CHANGELOG.md +591 -0
- package/skills/void/docs/node_modules/void/node_modules/@clack/prompts/README.md +375 -0
- package/skills/void/docs/node_modules/void/node_modules/@cloudflare/sandbox/README.md +174 -0
- package/skills/void/docs/node_modules/void/node_modules/@cloudflare/vite-plugin/README.md +37 -0
- package/skills/void/docs/node_modules/void/node_modules/@cloudflare/workers-types/README.md +135 -0
- package/skills/void/docs/node_modules/void/node_modules/@electric-sql/pglite/README.md +189 -0
- package/skills/void/docs/node_modules/void/node_modules/@hono/oauth-providers/CHANGELOG.md +143 -0
- package/skills/void/docs/node_modules/void/node_modules/@hono/oauth-providers/README.md +1272 -0
- package/skills/void/docs/node_modules/void/node_modules/@napi-rs/keyring/README.md +19 -0
- package/skills/void/docs/node_modules/void/node_modules/@types/better-sqlite3/README.md +15 -0
- package/skills/void/docs/node_modules/void/node_modules/@types/node/README.md +15 -0
- package/skills/void/docs/node_modules/void/node_modules/@types/pg/README.md +15 -0
- package/skills/void/docs/node_modules/void/node_modules/@typescript/native-preview/README.md +22 -0
- package/skills/void/docs/node_modules/void/node_modules/@typescript/native-preview/vendor/vscode-jsonrpc/README.md +69 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/README.md +152 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/@shikijs/engine-javascript/README.md +9 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/@shikijs/transformers/README.md +9 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/@types/node/README.md +15 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/gray-matter/CHANGELOG.md +24 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/gray-matter/README.md +565 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/markdown-exit/README.md +124 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/markdown-it-anchor/README.md +600 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/markdown-it-attrs/README.md +386 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/markdown-it-container/README.md +95 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/markdown-it-emoji/README.md +101 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/pathe/README.md +73 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/shiki/README.md +15 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/tinyglobby/README.md +25 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/tsdown/README.md +55 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite/LICENSE.md +2230 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vite/README.md +20 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/vue/README.md +58 -0
- package/skills/void/docs/node_modules/void/node_modules/arktype/README.md +165 -0
- package/skills/void/docs/node_modules/void/node_modules/better-auth/LICENSE.md +20 -0
- package/skills/void/docs/node_modules/void/node_modules/better-auth/README.md +32 -0
- package/skills/void/docs/node_modules/void/node_modules/better-sqlite3/README.md +99 -0
- package/skills/void/docs/node_modules/void/node_modules/blake3-jit/README.md +108 -0
- package/skills/void/docs/node_modules/void/node_modules/drizzle-arktype/README.md +51 -0
- package/skills/void/docs/node_modules/void/node_modules/drizzle-kit/README.md +79 -0
- package/skills/void/docs/node_modules/void/node_modules/drizzle-orm/README.md +44 -0
- package/skills/void/docs/node_modules/void/node_modules/drizzle-valibot/README.md +51 -0
- package/skills/void/docs/node_modules/void/node_modules/drizzle-zod/README.md +65 -0
- package/skills/void/docs/node_modules/void/node_modules/es-module-lexer/README.md +390 -0
- package/skills/void/docs/node_modules/void/node_modules/estree-walker/README.md +48 -0
- package/skills/void/docs/node_modules/void/node_modules/hono/README.md +85 -0
- package/skills/void/docs/node_modules/void/node_modules/ignore/README.md +452 -0
- package/skills/void/docs/node_modules/void/node_modules/jsonc-parser/CHANGELOG.md +76 -0
- package/{LICENSE → skills/void/docs/node_modules/void/node_modules/jsonc-parser/LICENSE.md} +21 -21
- package/skills/void/docs/node_modules/void/node_modules/jsonc-parser/README.md +364 -0
- package/skills/void/docs/node_modules/void/node_modules/jsonc-parser/SECURITY.md +41 -0
- package/skills/void/docs/node_modules/void/node_modules/magic-string/README.md +325 -0
- package/skills/void/docs/node_modules/void/node_modules/ofetch/README.md +398 -0
- package/skills/void/docs/node_modules/void/node_modules/pathe/README.md +73 -0
- package/skills/void/docs/node_modules/void/node_modules/pg/README.md +95 -0
- package/skills/void/docs/node_modules/void/node_modules/pglite-server/LICENSE.md +21 -0
- package/skills/void/docs/node_modules/void/node_modules/pglite-server/README.md +135 -0
- package/skills/void/docs/node_modules/void/node_modules/picocolors/README.md +21 -0
- package/skills/void/docs/node_modules/void/node_modules/tinyglobby/README.md +25 -0
- package/skills/void/docs/node_modules/void/node_modules/tsdown/README.md +55 -0
- package/skills/void/docs/node_modules/void/node_modules/valibot/LICENSE.md +9 -0
- package/skills/void/docs/node_modules/void/node_modules/valibot/README.md +94 -0
- package/skills/void/docs/node_modules/void/node_modules/vite/LICENSE.md +2230 -0
- package/skills/void/docs/node_modules/void/node_modules/vite/README.md +20 -0
- package/skills/void/docs/node_modules/void/node_modules/wrangler/README.md +63 -0
- package/skills/void/docs/node_modules/void/node_modules/zod/README.md +191 -0
- package/skills/void/docs/node_modules/void/skills/migrate-vite-cloudflare-to-void/SKILL.md +175 -0
- package/skills/void/docs/node_modules/void/skills/void/SKILL.md +75 -0
- package/skills/void/docs/node_modules/void/skills/void/command/void.md +7 -0
- package/skills/void/docs/reference/api.md +917 -0
- package/skills/void/docs/reference/cli.md +564 -0
- package/skills/void/docs/reference/config.md +408 -0
- package/skills/void/docs/reference/resource-inference.md +149 -0
- package/skills/void/docs/reference/structure.md +176 -0
- package/.npmignore +0 -29
- package/.travis.yml +0 -9
- package/favicon.ico +0 -0
- package/index.js +0 -14
- package/lib/Job.js +0 -150
- package/lib/Void.js +0 -99
- package/lib/scan.js +0 -19
- package/test/credentials.js +0 -20
- package/test/job.js +0 -64
- package/test/static/dir1/test6.html +0 -0
- package/test/static/dir2/test7.html +0 -0
- package/test/static/dir2/test8.html +0 -0
- package/test/static/dir2/test9.html +0 -0
- package/test/static/test1.html +0 -0
- package/test/static/test2.html +0 -0
- package/test/static/test3.html +0 -0
- package/test/void.js +0 -31
- /package/{test/static/dir1/test4.html → skills/void/docs/integrations/auth-providers.md} +0 -0
- /package/{test/static/dir1/test5.html → skills/void/docs/integrations/payment-processors.md} +0 -0
|
@@ -0,0 +1,573 @@
|
|
|
1
|
+
import { n as __exportAll } from "./chunk-DJd-R1mw.mjs";
|
|
2
|
+
import { a as join } from "./pathe.M-eThtNZ-D-kmWkCS.mjs";
|
|
3
|
+
import { i as isVoidAuthProvider, t as VOID_AUTH_PROVIDERS } from "./providers-B3aMxWzP.mjs";
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
5
|
+
//#region src/config.ts
|
|
6
|
+
var config_exports = /* @__PURE__ */ __exportAll({
|
|
7
|
+
VALID_REDIRECT_STATUSES: () => VALID_REDIRECT_STATUSES,
|
|
8
|
+
assertSingleSplat: () => assertSingleSplat,
|
|
9
|
+
assertUniqueCaptureNames: () => assertUniqueCaptureNames,
|
|
10
|
+
convertFallbacksConfig: () => convertFallbacksConfig,
|
|
11
|
+
convertHeadersConfig: () => convertHeadersConfig,
|
|
12
|
+
convertRedirectsConfig: () => convertRedirectsConfig,
|
|
13
|
+
convertRewritesConfig: () => convertRewritesConfig,
|
|
14
|
+
countSplats: () => countSplats,
|
|
15
|
+
getDatabaseDialect: () => getDatabaseDialect,
|
|
16
|
+
isNodeTarget: () => isNodeTarget,
|
|
17
|
+
isProtocolRelative: () => isProtocolRelative,
|
|
18
|
+
parseHostPrefixedSource: () => parseHostPrefixedSource,
|
|
19
|
+
readConfig: () => readConfig,
|
|
20
|
+
resolveBindingNames: () => resolveBindingNames
|
|
21
|
+
});
|
|
22
|
+
const CONFIG_FILE = "void.json";
|
|
23
|
+
const VALID_TARGETS = new Set([
|
|
24
|
+
"cloudflare",
|
|
25
|
+
"node",
|
|
26
|
+
"bun",
|
|
27
|
+
"deno"
|
|
28
|
+
]);
|
|
29
|
+
const VALID_APP_TYPES = new Set([
|
|
30
|
+
"spa",
|
|
31
|
+
"static",
|
|
32
|
+
"void",
|
|
33
|
+
"framework"
|
|
34
|
+
]);
|
|
35
|
+
const VALID_OUTPUTS = new Set(["server", "static"]);
|
|
36
|
+
/**
|
|
37
|
+
* Allowed 3xx redirect statuses. Source of truth for the framework, the
|
|
38
|
+
* `_redirects` parser (`cli/headers.ts`), and the schema.json enum. 303 is
|
|
39
|
+
* included for POST→GET after-submit patterns; 304/305/306 aren't
|
|
40
|
+
* cacheable-safe / are deprecated.
|
|
41
|
+
*/
|
|
42
|
+
const VALID_REDIRECT_STATUSES = new Set([
|
|
43
|
+
301,
|
|
44
|
+
302,
|
|
45
|
+
303,
|
|
46
|
+
307,
|
|
47
|
+
308
|
|
48
|
+
]);
|
|
49
|
+
const VALID_DATABASE_VALUES = new Set(["pg"]);
|
|
50
|
+
const VALID_SANDBOX_INSTANCE_TYPES = new Set([
|
|
51
|
+
"dev",
|
|
52
|
+
"lite",
|
|
53
|
+
"basic",
|
|
54
|
+
"standard",
|
|
55
|
+
"standard-1",
|
|
56
|
+
"standard-2",
|
|
57
|
+
"standard-3",
|
|
58
|
+
"standard-4"
|
|
59
|
+
]);
|
|
60
|
+
/**
|
|
61
|
+
* Count anonymous `*` wildcards in a pattern, ignoring the `*` that
|
|
62
|
+
* terminates a `:name*` multi-segment named capture.
|
|
63
|
+
*
|
|
64
|
+
* Both the framework's emitted `__compilePattern` (router/compile.ts) and
|
|
65
|
+
* dispatch's `compilePattern` (packages/dispatch/src/pattern.ts) emit a
|
|
66
|
+
* distinct `(?<name>.*)` group for `:name*` and a `(?<splat>.*)` group for
|
|
67
|
+
* the first bare `*` — those don't clash, so a pattern with both a named
|
|
68
|
+
* multi-segment capture and a bare splat is legitimate and must validate.
|
|
69
|
+
* Walking raw chars would over-count and cause `assertSingleSplat` to
|
|
70
|
+
* reject such patterns.
|
|
71
|
+
*
|
|
72
|
+
* The identifier character class matches `[A-Za-z0-9_]+` from both compilers.
|
|
73
|
+
*/
|
|
74
|
+
function countSplats(source) {
|
|
75
|
+
return source.replace(/:[A-Za-z0-9_]+\*/g, "").match(/\*/g)?.length ?? 0;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Reject a rule source containing more than one `*` wildcard. The dispatch
|
|
79
|
+
* worker compiles each `*` into a `(?<splat>...)` named capture group; having
|
|
80
|
+
* two of them in one pattern means `new RegExp()` throws at startup with a
|
|
81
|
+
* cryptic "duplicate group name" error. Fail at config-read time with a
|
|
82
|
+
* clear message instead. `kind` is a capitalised noun (e.g. "Redirect",
|
|
83
|
+
* "Rewrite") used in the error text.
|
|
84
|
+
*/
|
|
85
|
+
function assertSingleSplat(source, kind) {
|
|
86
|
+
const count = countSplats(source);
|
|
87
|
+
if (count > 1) throw new Error(`${kind} source "${source}" in ${CONFIG_FILE} must contain at most one "*" wildcard (got ${count}); the matched portion is captured once as :splat`);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Reject patterns whose compilation would produce duplicate named-capture
|
|
91
|
+
* groups, which makes `new RegExp()` throw `SyntaxError: Duplicate capture
|
|
92
|
+
* group name` at request time. Two cases:
|
|
93
|
+
*
|
|
94
|
+
* 1. Two `:name` (or `:name` + trailing `*`) tokens with the same
|
|
95
|
+
* identifier — e.g. `/:id/:id`, or two named-multi-segment captures
|
|
96
|
+
* sharing a name.
|
|
97
|
+
* 2. A `:splat` (named) token alongside a bare `*` — both compile to a
|
|
98
|
+
* `(?<splat>...)` group.
|
|
99
|
+
*
|
|
100
|
+
* `assertSingleSplat` already prevents two bare `*`s clashing on the
|
|
101
|
+
* implicit `splat` name. This complements it. The runtime emitter has a
|
|
102
|
+
* try/catch defense-in-depth in `emitApplyRoutingRules`, but failing at
|
|
103
|
+
* config-read with a precise message is friendlier than a CLI-log warn.
|
|
104
|
+
*/
|
|
105
|
+
function assertUniqueCaptureNames(source, kind) {
|
|
106
|
+
const seen = /* @__PURE__ */ new Set();
|
|
107
|
+
const dups = /* @__PURE__ */ new Set();
|
|
108
|
+
const re = /:([A-Za-z0-9_]+)\*?/g;
|
|
109
|
+
let m;
|
|
110
|
+
while ((m = re.exec(source)) !== null) {
|
|
111
|
+
const name = m[1];
|
|
112
|
+
if (seen.has(name)) dups.add(name);
|
|
113
|
+
seen.add(name);
|
|
114
|
+
}
|
|
115
|
+
if (countSplats(source) >= 1 && seen.has("splat")) dups.add("splat");
|
|
116
|
+
if (dups.size > 0) {
|
|
117
|
+
const names = [...dups].map((n) => `:${n}`).join(", ");
|
|
118
|
+
throw new Error(`${kind} source "${source}" in ${CONFIG_FILE} has duplicate capture group name(s) (${names}); each :name token must be unique within a pattern, and :splat collides with a bare "*"`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Predicate for the "protocol-relative" shape: a leading `//` parses as
|
|
123
|
+
* `//host/path` → `https://host/path`, which silently turns an intended
|
|
124
|
+
* in-worker rewrite/redirect into a cross-origin proxy.
|
|
125
|
+
*
|
|
126
|
+
* Shared by the `void.json` validators below and the `_redirects` parser
|
|
127
|
+
* (`cli/headers.ts`). The `c.rewrite()` codegen in `router/compile.ts`
|
|
128
|
+
* inlines an equivalent check in emitted worker code — it validates
|
|
129
|
+
* runtime user input rather than config, so it can't call through here.
|
|
130
|
+
*/
|
|
131
|
+
function isProtocolRelative(dest) {
|
|
132
|
+
return dest.startsWith("//");
|
|
133
|
+
}
|
|
134
|
+
function assertNotProtocolRelative(dest, source, kind) {
|
|
135
|
+
if (!isProtocolRelative(dest)) return;
|
|
136
|
+
throw new Error(`${kind} destination for "${source}" in ${CONFIG_FILE} must not start with "//" (protocol-relative URLs parse as cross-origin; ${kind === "Redirect" ? "use a single-slash path for internal redirects or an explicit \"https://...\" URL for external" : "only internal paths are supported"})`);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Strict literal-hostname regex used by `parseHostPrefixedSource` to validate
|
|
140
|
+
* the host portion of an `https://host/path` rule source. Mirrors
|
|
141
|
+
* `LITERAL_HOSTNAME_REGEX` in `packages/api/src/routes/deploy.ts` and the
|
|
142
|
+
* regex in `packages/api/src/routes/domains.ts`. Rejects scheme prefixes,
|
|
143
|
+
* ports, paths, whitespace, control chars, wildcards, single-label hosts,
|
|
144
|
+
* IPv4 literals, and userinfo. The host is lowercased before testing so the
|
|
145
|
+
* same byte-exact form reaches dispatch (which compares against the
|
|
146
|
+
* lowercase `url.hostname`).
|
|
147
|
+
*/
|
|
148
|
+
const LITERAL_HOSTNAME_REGEX = /^([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z]{2,}$/;
|
|
149
|
+
/**
|
|
150
|
+
* Split an optional `https://host/path` prefix from a rule source.
|
|
151
|
+
*
|
|
152
|
+
* Path-only sources (no scheme) are returned as `{ host: undefined, path }`.
|
|
153
|
+
* Sources starting with `https://` have the host portion extracted and
|
|
154
|
+
* lowercase-normalized; the remaining path becomes `path` (including the
|
|
155
|
+
* leading `/`, which the caller may further validate).
|
|
156
|
+
*
|
|
157
|
+
* Rejected (returns `{ error }`):
|
|
158
|
+
* - `http://...` — TLS terminates upstream of the dispatch worker; only
|
|
159
|
+
* `https://` requests ever reach the runtime, so an `http://`-scoped rule
|
|
160
|
+
* physically cannot fire.
|
|
161
|
+
* - `//host/path` — protocol-relative; ambiguous and rejected by the same
|
|
162
|
+
* reasoning.
|
|
163
|
+
* - `https://` with a wildcarded, ported, or otherwise non-literal host
|
|
164
|
+
* (v1 only supports literal hosts).
|
|
165
|
+
* - `https://` with no path (`https://host`) — accepted and normalized to
|
|
166
|
+
* `https://host/` so the path is always non-empty.
|
|
167
|
+
*/
|
|
168
|
+
function parseHostPrefixedSource(raw) {
|
|
169
|
+
if (raw.startsWith("//")) return { error: `must not start with "//" (protocol-relative URLs are ambiguous; use "/path" for path-only or "https://host/path")` };
|
|
170
|
+
if (raw.startsWith("http://")) return { error: `must not start with "http://" (TLS terminates upstream of the worker; only "https://" requests reach the runtime — use "https://host/path" instead)` };
|
|
171
|
+
if (!raw.startsWith("https://")) return {
|
|
172
|
+
host: void 0,
|
|
173
|
+
path: raw
|
|
174
|
+
};
|
|
175
|
+
const afterScheme = raw.slice(8);
|
|
176
|
+
const slashIdx = afterScheme.indexOf("/");
|
|
177
|
+
const rawHost = slashIdx === -1 ? afterScheme : afterScheme.slice(0, slashIdx);
|
|
178
|
+
const path = slashIdx === -1 ? "/" : afterScheme.slice(slashIdx);
|
|
179
|
+
const host = rawHost.toLowerCase();
|
|
180
|
+
if (!LITERAL_HOSTNAME_REGEX.test(host)) return { error: `host must be a literal hostname (e.g. "https://www.example.com/path"; no port, wildcards, or userinfo): ${JSON.stringify(rawHost)}` };
|
|
181
|
+
return {
|
|
182
|
+
host,
|
|
183
|
+
path
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Shared guard for rewrite/fallback destinations: they preserve the incoming
|
|
188
|
+
* request's query string, so embedding one in the destination would silently
|
|
189
|
+
* override (or merge confusingly with) the request query.
|
|
190
|
+
*/
|
|
191
|
+
function assertNoQueryString(dest, source, kind) {
|
|
192
|
+
if (!dest.includes("?")) return;
|
|
193
|
+
throw new Error(`${kind} destination for "${source}" in ${CONFIG_FILE} must not contain "?" (query strings are not supported in ${kind.toLowerCase()} destinations; the incoming request's query is preserved automatically)`);
|
|
194
|
+
}
|
|
195
|
+
/** Old flat keys that have moved into namespaces. */
|
|
196
|
+
const MIGRATION_ERRORS = {
|
|
197
|
+
bindings: "\"bindings\" has moved to \"inference.bindings\"",
|
|
198
|
+
build: "\"build\" has moved to \"inference.build\"",
|
|
199
|
+
scanDirs: "\"scanDirs\" has moved to \"inference.scanDirs\"",
|
|
200
|
+
appType: "\"appType\" has moved to \"inference.appType\"",
|
|
201
|
+
outputDir: "\"outputDir\" has moved to \"inference.outputDir\"",
|
|
202
|
+
headers: "\"headers\" has moved to \"routing.headers\"",
|
|
203
|
+
redirects: "\"redirects\" has moved to \"routing.redirects\"",
|
|
204
|
+
cache: "\"cache\" has been replaced by \"routing\" — use \"routing.revalidate\" and \"routing.prerender\"",
|
|
205
|
+
wrangler: "\"wrangler\" has been renamed to \"worker\"",
|
|
206
|
+
mode: "\"mode\" has been renamed to \"inference.appType\"",
|
|
207
|
+
revalidate: "\"revalidate\" has moved to \"routing.revalidate\""
|
|
208
|
+
};
|
|
209
|
+
/**
|
|
210
|
+
* Read and validate the `void.json` config file from the project root.
|
|
211
|
+
* Returns an empty config object if no file exists.
|
|
212
|
+
*/
|
|
213
|
+
function readConfig(root) {
|
|
214
|
+
const filePath = join(root, CONFIG_FILE);
|
|
215
|
+
let raw;
|
|
216
|
+
try {
|
|
217
|
+
raw = readFileSync(filePath, "utf-8");
|
|
218
|
+
} catch {
|
|
219
|
+
return {};
|
|
220
|
+
}
|
|
221
|
+
let config;
|
|
222
|
+
try {
|
|
223
|
+
config = JSON.parse(raw);
|
|
224
|
+
} catch {
|
|
225
|
+
throw new Error(`config: Invalid JSON in ${CONFIG_FILE}.`);
|
|
226
|
+
}
|
|
227
|
+
if (typeof config !== "object" || config === null || Array.isArray(config)) throw new Error(`config: ${CONFIG_FILE} must be a JSON object.`);
|
|
228
|
+
const obj = config;
|
|
229
|
+
for (const [key, message] of Object.entries(MIGRATION_ERRORS)) if (obj[key] !== void 0) throw new Error(`config: ${message} in ${CONFIG_FILE}.`);
|
|
230
|
+
if (obj.target !== void 0) {
|
|
231
|
+
if (typeof obj.target !== "string" || !VALID_TARGETS.has(obj.target)) throw new Error(`config: "target" in ${CONFIG_FILE} must be one of: cloudflare, node, bun, deno.`);
|
|
232
|
+
}
|
|
233
|
+
if (obj.output !== void 0) {
|
|
234
|
+
if (typeof obj.output !== "string" || !VALID_OUTPUTS.has(obj.output)) throw new Error(`config: "output" in ${CONFIG_FILE} must be one of: server, static.`);
|
|
235
|
+
}
|
|
236
|
+
if (obj.auth !== void 0) {
|
|
237
|
+
if (typeof obj.auth !== "object" || obj.auth === null || Array.isArray(obj.auth)) throw new Error(`config: "auth" in ${CONFIG_FILE} must be an object.`);
|
|
238
|
+
const auth = obj.auth;
|
|
239
|
+
for (const key of Object.keys(auth)) if (key !== "providers") throw new Error(`config: Unknown key 'auth.${key}' in ${CONFIG_FILE}. Valid: providers.`);
|
|
240
|
+
if (auth.providers !== void 0) {
|
|
241
|
+
if (!Array.isArray(auth.providers)) throw new Error(`config: "auth.providers" in ${CONFIG_FILE} must be an array of strings.`);
|
|
242
|
+
if (auth.providers.length === 0) throw new Error(`config: "auth.providers" in ${CONFIG_FILE} must not be empty.`);
|
|
243
|
+
const seen = /* @__PURE__ */ new Set();
|
|
244
|
+
for (const provider of auth.providers) {
|
|
245
|
+
if (typeof provider !== "string") throw new Error(`config: "auth.providers" in ${CONFIG_FILE} must be an array of strings.`);
|
|
246
|
+
if (!isVoidAuthProvider(provider)) throw new Error(`config: "auth.providers" value '${provider}' in ${CONFIG_FILE} must be one of: ${VOID_AUTH_PROVIDERS.join(", ")}.`);
|
|
247
|
+
if (seen.has(provider)) throw new Error(`config: "auth.providers" in ${CONFIG_FILE} must not contain duplicates.`);
|
|
248
|
+
seen.add(provider);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (obj.head !== void 0) {
|
|
253
|
+
if (typeof obj.head !== "object" || obj.head === null || Array.isArray(obj.head)) throw new Error(`config: "head" in ${CONFIG_FILE} must be an object.`);
|
|
254
|
+
const h = obj.head;
|
|
255
|
+
if (h.title !== void 0 && typeof h.title !== "string") throw new Error(`config: "head.title" in ${CONFIG_FILE} must be a string.`);
|
|
256
|
+
if (h.titleTemplate !== void 0 && typeof h.titleTemplate !== "string") throw new Error(`config: "head.titleTemplate" in ${CONFIG_FILE} must be a string.`);
|
|
257
|
+
if (h.meta !== void 0) {
|
|
258
|
+
if (!Array.isArray(h.meta)) throw new Error(`config: "head.meta" in ${CONFIG_FILE} must be an array.`);
|
|
259
|
+
for (const entry of h.meta) if (typeof entry !== "object" || entry === null || Array.isArray(entry)) throw new Error(`config: "head.meta" entries in ${CONFIG_FILE} must be objects.`);
|
|
260
|
+
}
|
|
261
|
+
if (h.link !== void 0) {
|
|
262
|
+
if (!Array.isArray(h.link)) throw new Error(`config: "head.link" in ${CONFIG_FILE} must be an array.`);
|
|
263
|
+
}
|
|
264
|
+
if (h.script !== void 0) {
|
|
265
|
+
if (!Array.isArray(h.script)) throw new Error(`config: "head.script" in ${CONFIG_FILE} must be an array.`);
|
|
266
|
+
}
|
|
267
|
+
if (h.htmlAttrs !== void 0) {
|
|
268
|
+
if (typeof h.htmlAttrs !== "object" || h.htmlAttrs === null || Array.isArray(h.htmlAttrs)) throw new Error(`config: "head.htmlAttrs" in ${CONFIG_FILE} must be an object.`);
|
|
269
|
+
}
|
|
270
|
+
if (h.bodyAttrs !== void 0) {
|
|
271
|
+
if (typeof h.bodyAttrs !== "object" || h.bodyAttrs === null || Array.isArray(h.bodyAttrs)) throw new Error(`config: "head.bodyAttrs" in ${CONFIG_FILE} must be an object.`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (obj.routing !== void 0) {
|
|
275
|
+
if (typeof obj.routing !== "object" || obj.routing === null || Array.isArray(obj.routing)) throw new Error(`config: "routing" in ${CONFIG_FILE} must be an object.`);
|
|
276
|
+
const routing = obj.routing;
|
|
277
|
+
if (routing.revalidate !== void 0) if (typeof routing.revalidate === "number") {
|
|
278
|
+
if (!Number.isFinite(routing.revalidate) || routing.revalidate < 0) throw new Error(`config: "routing.revalidate" in ${CONFIG_FILE} must be a non-negative finite number.`);
|
|
279
|
+
} else if (typeof routing.revalidate === "object" && routing.revalidate !== null && !Array.isArray(routing.revalidate)) {
|
|
280
|
+
const r = routing.revalidate;
|
|
281
|
+
for (const [pattern, value] of Object.entries(r)) {
|
|
282
|
+
if (pattern !== "*" && !pattern.startsWith("/")) throw new Error(`config: "routing.revalidate" key '${pattern}' in ${CONFIG_FILE} must start with "/" or be "*".`);
|
|
283
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) throw new Error(`config: "routing.revalidate" value for '${pattern}' in ${CONFIG_FILE} must be a non-negative finite number.`);
|
|
284
|
+
}
|
|
285
|
+
} else throw new Error(`config: "routing.revalidate" in ${CONFIG_FILE} must be a number or an object of path patterns to numbers.`);
|
|
286
|
+
if (routing.prerender !== void 0) {
|
|
287
|
+
if (!Array.isArray(routing.prerender) || !routing.prerender.every((p) => typeof p === "string")) throw new Error(`config: "routing.prerender" in ${CONFIG_FILE} must be an array of strings.`);
|
|
288
|
+
for (const p of routing.prerender) if (!p.startsWith("/")) throw new Error(`config: "routing.prerender" path '${p}' in ${CONFIG_FILE} must start with "/".`);
|
|
289
|
+
}
|
|
290
|
+
if (routing.headers !== void 0) {
|
|
291
|
+
if (typeof routing.headers !== "object" || routing.headers === null || Array.isArray(routing.headers)) throw new Error(`config: "routing.headers" in ${CONFIG_FILE} must be an object.`);
|
|
292
|
+
const h = routing.headers;
|
|
293
|
+
for (const [pattern, values] of Object.entries(h)) {
|
|
294
|
+
if (!pattern.startsWith("/")) throw new Error(`config: Header pattern '${pattern}' in ${CONFIG_FILE} must start with "/".`);
|
|
295
|
+
assertSingleSplat(pattern, "Header");
|
|
296
|
+
if (!Array.isArray(values) || !values.every((v) => typeof v === "string")) throw new Error(`config: Headers for '${pattern}' in ${CONFIG_FILE} must be an array of strings.`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (routing.redirects !== void 0) {
|
|
300
|
+
if (typeof routing.redirects !== "object" || routing.redirects === null || Array.isArray(routing.redirects)) throw new Error(`config: "routing.redirects" in ${CONFIG_FILE} must be an object.`);
|
|
301
|
+
const r = routing.redirects;
|
|
302
|
+
for (const [source, dest] of Object.entries(r)) {
|
|
303
|
+
const parsed = parseHostPrefixedSource(source);
|
|
304
|
+
if ("error" in parsed) throw new Error(`config: Redirect source '${source}' in ${CONFIG_FILE}: ${parsed.error}.`);
|
|
305
|
+
if (!parsed.path.startsWith("/")) throw new Error(`config: Redirect source '${source}' in ${CONFIG_FILE} must start with "/" (or be "https://host/path" with a path-absolute path).`);
|
|
306
|
+
assertSingleSplat(parsed.path, "Redirect");
|
|
307
|
+
assertUniqueCaptureNames(parsed.path, "Redirect");
|
|
308
|
+
if (typeof dest === "string") {
|
|
309
|
+
if (dest.startsWith("/")) assertNotProtocolRelative(dest, source, "Redirect");
|
|
310
|
+
} else if (typeof dest === "object" && dest !== null && !Array.isArray(dest)) {
|
|
311
|
+
const d = dest;
|
|
312
|
+
if (typeof d.to !== "string") throw new Error(`config: Redirect for '${source}' in ${CONFIG_FILE} must have a "to" string.`);
|
|
313
|
+
if (d.to.startsWith("/")) assertNotProtocolRelative(d.to, source, "Redirect");
|
|
314
|
+
if (d.status !== void 0 && !VALID_REDIRECT_STATUSES.has(d.status)) throw new Error(`config: Redirect status for '${source}' in ${CONFIG_FILE} must be 301, 302, 303, 307, or 308.`);
|
|
315
|
+
} else throw new Error(`config: Redirect for '${source}' in ${CONFIG_FILE} must be a string or an object with "to" and optional "status".`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
if (routing.revalidateQueryAllowlist !== void 0) {
|
|
319
|
+
if (typeof routing.revalidateQueryAllowlist !== "object" || routing.revalidateQueryAllowlist === null || Array.isArray(routing.revalidateQueryAllowlist)) throw new Error(`"routing.revalidateQueryAllowlist" in ${CONFIG_FILE} must be an object`);
|
|
320
|
+
for (const [pattern, params] of Object.entries(routing.revalidateQueryAllowlist)) {
|
|
321
|
+
if (pattern !== "*" && !pattern.startsWith("/")) throw new Error(`config: revalidateQueryAllowlist pattern '${pattern}' in ${CONFIG_FILE} must start with "/" or be "*".`);
|
|
322
|
+
if (pattern !== "*") assertSingleSplat(pattern, "revalidateQueryAllowlist");
|
|
323
|
+
if (!Array.isArray(params) || !params.every((v) => typeof v === "string")) throw new Error(`config: revalidateQueryAllowlist for '${pattern}' in ${CONFIG_FILE} must be an array of strings.`);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
if (routing.rewrites !== void 0) {
|
|
327
|
+
if (typeof routing.rewrites !== "object" || routing.rewrites === null || Array.isArray(routing.rewrites)) throw new Error(`"routing.rewrites" in ${CONFIG_FILE} must be an object`);
|
|
328
|
+
const rw = routing.rewrites;
|
|
329
|
+
for (const [source, dest] of Object.entries(rw)) {
|
|
330
|
+
const parsed = parseHostPrefixedSource(source);
|
|
331
|
+
if ("error" in parsed) throw new Error(`Rewrite source "${source}" in ${CONFIG_FILE}: ${parsed.error}`);
|
|
332
|
+
if (!parsed.path.startsWith("/")) throw new Error(`Rewrite source "${source}" in ${CONFIG_FILE} must start with "/" (or be "https://host/path" with a path-absolute path)`);
|
|
333
|
+
assertSingleSplat(parsed.path, "Rewrite");
|
|
334
|
+
assertUniqueCaptureNames(parsed.path, "Rewrite");
|
|
335
|
+
if (typeof dest !== "string") throw new Error(`Rewrite destination for "${source}" in ${CONFIG_FILE} must be a string`);
|
|
336
|
+
if (!dest.startsWith("/")) throw new Error(`Rewrite destination for "${source}" in ${CONFIG_FILE} must start with "/" (only internal paths are supported)`);
|
|
337
|
+
assertNotProtocolRelative(dest, source, "Rewrite");
|
|
338
|
+
assertNoQueryString(dest, source, "Rewrite");
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
if (routing.fallbacks !== void 0) {
|
|
342
|
+
if (typeof routing.fallbacks !== "object" || routing.fallbacks === null || Array.isArray(routing.fallbacks)) throw new Error(`"routing.fallbacks" in ${CONFIG_FILE} must be an object`);
|
|
343
|
+
const fb = routing.fallbacks;
|
|
344
|
+
for (const [source, dest] of Object.entries(fb)) {
|
|
345
|
+
const parsed = parseHostPrefixedSource(source);
|
|
346
|
+
if ("error" in parsed) throw new Error(`Fallback source "${source}" in ${CONFIG_FILE}: ${parsed.error}`);
|
|
347
|
+
if (!parsed.path.startsWith("/")) throw new Error(`Fallback source "${source}" in ${CONFIG_FILE} must start with "/" (or be "https://host/path" with a path-absolute path)`);
|
|
348
|
+
assertSingleSplat(parsed.path, "Fallback");
|
|
349
|
+
assertUniqueCaptureNames(parsed.path, "Fallback");
|
|
350
|
+
if (typeof dest !== "string") throw new Error(`Fallback destination for "${source}" in ${CONFIG_FILE} must be a string`);
|
|
351
|
+
if (!dest.startsWith("/")) throw new Error(`Fallback destination for "${source}" in ${CONFIG_FILE} must start with "/" (only internal paths are supported)`);
|
|
352
|
+
assertNotProtocolRelative(dest, source, "Fallback");
|
|
353
|
+
assertNoQueryString(dest, source, "Fallback");
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
if (obj.inference !== void 0) {
|
|
358
|
+
if (typeof obj.inference !== "object" || obj.inference === null || Array.isArray(obj.inference)) throw new Error(`config: "inference" in ${CONFIG_FILE} must be an object.`);
|
|
359
|
+
const inf = obj.inference;
|
|
360
|
+
if (inf.auth !== void 0) throw new Error(`config: "inference.auth" in ${CONFIG_FILE} is no longer supported. Use auth.ts or import from "void/auth"/"void/client" instead.`);
|
|
361
|
+
if (inf.bindings !== void 0) {
|
|
362
|
+
if (typeof inf.bindings !== "object" || inf.bindings === null || Array.isArray(inf.bindings)) throw new Error(`config: "inference.bindings" in ${CONFIG_FILE} must be an object.`);
|
|
363
|
+
const b = inf.bindings;
|
|
364
|
+
for (const key of Object.keys(b)) {
|
|
365
|
+
if (![
|
|
366
|
+
"db",
|
|
367
|
+
"kv",
|
|
368
|
+
"storage",
|
|
369
|
+
"ai"
|
|
370
|
+
].includes(key)) throw new Error(`config: Unknown binding '${key}' in ${CONFIG_FILE}. Valid: db, kv, storage, ai.`);
|
|
371
|
+
if (key === "ai") {
|
|
372
|
+
if (typeof b[key] !== "boolean") throw new Error(`config: "inference.bindings.${key}" in ${CONFIG_FILE} must be a boolean.`);
|
|
373
|
+
} else if (typeof b[key] !== "boolean" && typeof b[key] !== "string") throw new Error(`config: "inference.bindings.${key}" in ${CONFIG_FILE} must be a boolean or a string custom binding name.`);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
if (inf.build !== void 0 && typeof inf.build !== "string") throw new Error(`config: "inference.build" in ${CONFIG_FILE} must be a string.`);
|
|
377
|
+
if (inf.scanDirs !== void 0) {
|
|
378
|
+
if (!Array.isArray(inf.scanDirs) || !inf.scanDirs.every((d) => typeof d === "string")) throw new Error(`config: "inference.scanDirs" in ${CONFIG_FILE} must be an array of strings.`);
|
|
379
|
+
for (const d of inf.scanDirs) if (d.startsWith("/") || d.startsWith("..")) throw new Error(`config: "inference.scanDirs" path '${d}' in ${CONFIG_FILE} must be a relative directory.`);
|
|
380
|
+
}
|
|
381
|
+
if (inf.appType !== void 0) {
|
|
382
|
+
if (typeof inf.appType !== "string" || !VALID_APP_TYPES.has(inf.appType)) throw new Error(`config: "inference.appType" in ${CONFIG_FILE} must be one of: spa, static, void, framework.`);
|
|
383
|
+
}
|
|
384
|
+
if (inf.outputDir !== void 0 && typeof inf.outputDir !== "string") throw new Error(`config: "inference.outputDir" in ${CONFIG_FILE} must be a string.`);
|
|
385
|
+
}
|
|
386
|
+
if (obj.remote !== void 0 && typeof obj.remote !== "boolean") throw new Error(`config: "remote" in ${CONFIG_FILE} must be a boolean.`);
|
|
387
|
+
if (obj.sandbox !== void 0) if (typeof obj.sandbox === "boolean") {} else if (typeof obj.sandbox === "object" && obj.sandbox !== null && !Array.isArray(obj.sandbox)) {
|
|
388
|
+
const sandbox = obj.sandbox;
|
|
389
|
+
for (const key of Object.keys(sandbox)) if (![
|
|
390
|
+
"binding",
|
|
391
|
+
"className",
|
|
392
|
+
"containerName",
|
|
393
|
+
"image",
|
|
394
|
+
"imageBuildContext",
|
|
395
|
+
"platformImage",
|
|
396
|
+
"instanceType",
|
|
397
|
+
"maxInstances"
|
|
398
|
+
].includes(key)) throw new Error(`config: Unknown key 'sandbox.${key}' in ${CONFIG_FILE}. Valid: binding, className, containerName, image, imageBuildContext, platformImage, instanceType, maxInstances.`);
|
|
399
|
+
for (const key of [
|
|
400
|
+
"binding",
|
|
401
|
+
"className",
|
|
402
|
+
"containerName",
|
|
403
|
+
"image",
|
|
404
|
+
"imageBuildContext",
|
|
405
|
+
"platformImage"
|
|
406
|
+
]) if (sandbox[key] !== void 0 && typeof sandbox[key] !== "string") throw new Error(`config: "sandbox.${key}" in ${CONFIG_FILE} must be a string.`);
|
|
407
|
+
if (sandbox.instanceType !== void 0 && (typeof sandbox.instanceType !== "string" || !VALID_SANDBOX_INSTANCE_TYPES.has(sandbox.instanceType))) throw new Error(`config: "sandbox.instanceType" in ${CONFIG_FILE} must be one of: ${[...VALID_SANDBOX_INSTANCE_TYPES].join(", ")}.`);
|
|
408
|
+
if (sandbox.maxInstances !== void 0 && (typeof sandbox.maxInstances !== "number" || !Number.isInteger(sandbox.maxInstances) || sandbox.maxInstances < 1)) throw new Error(`config: "sandbox.maxInstances" in ${CONFIG_FILE} must be a positive integer.`);
|
|
409
|
+
} else throw new Error(`config: "sandbox" in ${CONFIG_FILE} must be a boolean or an object.`);
|
|
410
|
+
if (obj.worker !== void 0) {
|
|
411
|
+
if (typeof obj.worker !== "object" || obj.worker === null || Array.isArray(obj.worker)) throw new Error(`config: "worker" in ${CONFIG_FILE} must be an object.`);
|
|
412
|
+
const w = obj.worker;
|
|
413
|
+
if (w.compatibility_date !== void 0) {
|
|
414
|
+
if (typeof w.compatibility_date !== "string") throw new Error(`config: "worker.compatibility_date" in ${CONFIG_FILE} must be a string.`);
|
|
415
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(w.compatibility_date)) throw new Error(`config: "worker.compatibility_date" in ${CONFIG_FILE} must use YYYY-MM-DD format.`);
|
|
416
|
+
}
|
|
417
|
+
if (w.compatibility_flags !== void 0) {
|
|
418
|
+
if (!Array.isArray(w.compatibility_flags) || !w.compatibility_flags.every((f) => typeof f === "string")) throw new Error(`config: "worker.compatibility_flags" in ${CONFIG_FILE} must be an array of strings.`);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
if (obj.database !== void 0) {
|
|
422
|
+
if (typeof obj.database !== "string" || !VALID_DATABASE_VALUES.has(obj.database)) throw new Error(`config: "database" in ${CONFIG_FILE} must be "pg".`);
|
|
423
|
+
}
|
|
424
|
+
return obj;
|
|
425
|
+
}
|
|
426
|
+
/** Returns true if the target is a non-Cloudflare runtime (Node.js, Bun, Deno). */
|
|
427
|
+
function isNodeTarget(target) {
|
|
428
|
+
return target === "node" || target === "bun" || target === "deno";
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Extract custom binding names from config. Returns only entries where
|
|
432
|
+
* a string name was explicitly provided (not `true`).
|
|
433
|
+
*/
|
|
434
|
+
function resolveBindingNames(bindings) {
|
|
435
|
+
if (!bindings) return;
|
|
436
|
+
const names = {};
|
|
437
|
+
let hasCustom = false;
|
|
438
|
+
if (typeof bindings.db === "string") {
|
|
439
|
+
names.d1 = bindings.db;
|
|
440
|
+
hasCustom = true;
|
|
441
|
+
}
|
|
442
|
+
if (typeof bindings.kv === "string") {
|
|
443
|
+
names.kv = bindings.kv;
|
|
444
|
+
hasCustom = true;
|
|
445
|
+
}
|
|
446
|
+
if (typeof bindings.storage === "string") {
|
|
447
|
+
names.r2 = bindings.storage;
|
|
448
|
+
hasCustom = true;
|
|
449
|
+
}
|
|
450
|
+
return hasCustom ? names : void 0;
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Get the database dialect from config. Defaults to "sqlite".
|
|
454
|
+
*/
|
|
455
|
+
function getDatabaseDialect(config) {
|
|
456
|
+
return config.database === "pg" ? "postgresql" : "sqlite";
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Convert the `headers` config field into `HeaderRule[]` for the deploy manifest.
|
|
460
|
+
*
|
|
461
|
+
* Each key is a URL pattern (e.g. "/assets/*") and each value is an array of
|
|
462
|
+
* "Name: value" strings. Returns undefined if the input is empty or undefined.
|
|
463
|
+
*/
|
|
464
|
+
function convertHeadersConfig(headers) {
|
|
465
|
+
if (!headers) return;
|
|
466
|
+
const rules = [];
|
|
467
|
+
for (const [pattern, values] of Object.entries(headers)) {
|
|
468
|
+
const parsed = [];
|
|
469
|
+
for (const entry of values) {
|
|
470
|
+
const colonIdx = entry.indexOf(":");
|
|
471
|
+
if (colonIdx === -1) continue;
|
|
472
|
+
const name = entry.slice(0, colonIdx).trim();
|
|
473
|
+
const value = entry.slice(colonIdx + 1).trim();
|
|
474
|
+
if (name) parsed.push([name, value]);
|
|
475
|
+
}
|
|
476
|
+
if (parsed.length > 0) rules.push({
|
|
477
|
+
pattern,
|
|
478
|
+
headers: parsed
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
return rules.length > 0 ? rules : void 0;
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Convert the `redirects` config field into `DevRedirectRule[]` for the deploy manifest.
|
|
485
|
+
*
|
|
486
|
+
* Each key is a URL pattern (e.g. "/old") and each value is either a string
|
|
487
|
+
* destination (defaults to 302) or an object with `to` and optional `status`.
|
|
488
|
+
* Returns undefined if the input is empty or undefined.
|
|
489
|
+
*/
|
|
490
|
+
function convertRedirectsConfig(redirects) {
|
|
491
|
+
if (!redirects) return;
|
|
492
|
+
const origin = "void.json#routing.redirects";
|
|
493
|
+
const rules = [];
|
|
494
|
+
for (const [rawSource, dest] of Object.entries(redirects)) {
|
|
495
|
+
const parsed = parseHostPrefixedSource(rawSource);
|
|
496
|
+
if ("error" in parsed) throw new Error(`convertRedirectsConfig: source "${rawSource}": ${parsed.error}`);
|
|
497
|
+
const { host, path } = parsed;
|
|
498
|
+
const base = {
|
|
499
|
+
source: path,
|
|
500
|
+
status: 302,
|
|
501
|
+
origin,
|
|
502
|
+
...host && { host }
|
|
503
|
+
};
|
|
504
|
+
if (typeof dest === "string") rules.push({
|
|
505
|
+
...base,
|
|
506
|
+
destination: dest
|
|
507
|
+
});
|
|
508
|
+
else rules.push({
|
|
509
|
+
...base,
|
|
510
|
+
destination: dest.to,
|
|
511
|
+
status: dest.status ?? 302
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
return rules.length > 0 ? rules : void 0;
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Convert the `rewrites` config field into `DevRedirectRule[]` with status 200.
|
|
518
|
+
*
|
|
519
|
+
* Each key is a URL pattern (e.g. "/docs") and each value is a destination path.
|
|
520
|
+
* Rewrites serve content from the destination without changing the browser URL.
|
|
521
|
+
* Emits `force: true` so these rules fire unconditionally, overriding any
|
|
522
|
+
* matching static asset (Netlify-compat `200!` semantics). Returns undefined
|
|
523
|
+
* if the input is empty or undefined.
|
|
524
|
+
*/
|
|
525
|
+
function convertRewritesConfig(rewrites) {
|
|
526
|
+
if (!rewrites) return;
|
|
527
|
+
const origin = "void.json#routing.rewrites";
|
|
528
|
+
const rules = [];
|
|
529
|
+
for (const [rawSource, destination] of Object.entries(rewrites)) {
|
|
530
|
+
const parsed = parseHostPrefixedSource(rawSource);
|
|
531
|
+
if ("error" in parsed) throw new Error(`convertRewritesConfig: source "${rawSource}": ${parsed.error}`);
|
|
532
|
+
const { host, path } = parsed;
|
|
533
|
+
rules.push({
|
|
534
|
+
source: path,
|
|
535
|
+
destination,
|
|
536
|
+
status: 200,
|
|
537
|
+
force: true,
|
|
538
|
+
origin,
|
|
539
|
+
...host && { host }
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
return rules.length > 0 ? rules : void 0;
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Convert the `fallbacks` config field into `DevRedirectRule[]` with status 200.
|
|
546
|
+
*
|
|
547
|
+
* Fallbacks fire only when the static asset resolver would otherwise return
|
|
548
|
+
* 404. They share the rewrite shape (status 200, pathname-only destination)
|
|
549
|
+
* but are evaluated at a different pipeline phase — post-lookup instead of
|
|
550
|
+
* pre-lookup. Emits `force: false` (Netlify-compat plain `200` semantics).
|
|
551
|
+
* Returns undefined if the input is empty or undefined.
|
|
552
|
+
*/
|
|
553
|
+
function convertFallbacksConfig(fallbacks) {
|
|
554
|
+
if (!fallbacks) return;
|
|
555
|
+
const origin = "void.json#routing.fallbacks";
|
|
556
|
+
const rules = [];
|
|
557
|
+
for (const [rawSource, destination] of Object.entries(fallbacks)) {
|
|
558
|
+
const parsed = parseHostPrefixedSource(rawSource);
|
|
559
|
+
if ("error" in parsed) throw new Error(`convertFallbacksConfig: source "${rawSource}": ${parsed.error}`);
|
|
560
|
+
const { host, path } = parsed;
|
|
561
|
+
rules.push({
|
|
562
|
+
source: path,
|
|
563
|
+
destination,
|
|
564
|
+
status: 200,
|
|
565
|
+
force: false,
|
|
566
|
+
origin,
|
|
567
|
+
...host && { host }
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
return rules.length > 0 ? rules : void 0;
|
|
571
|
+
}
|
|
572
|
+
//#endregion
|
|
573
|
+
export { convertRedirectsConfig as a, getDatabaseDialect as c, parseHostPrefixedSource as d, readConfig as f, convertHeadersConfig as i, isNodeTarget as l, config_exports as n, convertRewritesConfig as o, resolveBindingNames as p, convertFallbacksConfig as r, countSplats as s, VALID_REDIRECT_STATUSES as t, isProtocolRelative as u };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { n as __exportAll } from "./chunk-DJd-R1mw.mjs";
|
|
2
|
+
import { a as join } from "./pathe.M-eThtNZ-D-kmWkCS.mjs";
|
|
3
|
+
import { r as schemaSpecifier, t as discoverSchema } from "./discover-B7FkXBLB.mjs";
|
|
4
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
5
|
+
//#region src/drizzle/config.ts
|
|
6
|
+
var config_exports = /* @__PURE__ */ __exportAll({ writeDrizzleConfig: () => writeDrizzleConfig });
|
|
7
|
+
/**
|
|
8
|
+
* Write a temporary drizzle-kit config to `.void/drizzle.config.json`.
|
|
9
|
+
* All paths are relative to the project root (drizzle-kit resolves
|
|
10
|
+
* relative to `--config` file location, so we use project-root-relative).
|
|
11
|
+
*
|
|
12
|
+
* @returns Absolute path to the written config file.
|
|
13
|
+
*/
|
|
14
|
+
function writeDrizzleConfig(root, dbPath, dialect = "sqlite") {
|
|
15
|
+
const schema = discoverSchema(root);
|
|
16
|
+
if (!schema) throw new Error("db: No Drizzle schema found. Create db/schema.ts or run `void gen model <name>`.");
|
|
17
|
+
const outDir = join(root, ".void");
|
|
18
|
+
mkdirSync(outDir, { recursive: true });
|
|
19
|
+
const config = dialect === "postgresql" ? {
|
|
20
|
+
dialect: "postgresql",
|
|
21
|
+
schema: schemaSpecifier(schema),
|
|
22
|
+
out: "./db/migrations",
|
|
23
|
+
migrations: { prefix: "timestamp" },
|
|
24
|
+
dbCredentials: { url: dbPath }
|
|
25
|
+
} : {
|
|
26
|
+
dialect: "sqlite",
|
|
27
|
+
schema: schemaSpecifier(schema),
|
|
28
|
+
out: "./db/migrations",
|
|
29
|
+
migrations: { prefix: "timestamp" },
|
|
30
|
+
dbCredentials: { url: dbPath }
|
|
31
|
+
};
|
|
32
|
+
const configPath = join(outDir, "drizzle.config.json");
|
|
33
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
34
|
+
return configPath;
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
export { writeDrizzleConfig as n, config_exports as t };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { a as join } from "./pathe.M-eThtNZ-D-kmWkCS.mjs";
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
4
|
+
//#region src/auth/config.ts
|
|
5
|
+
const AUTH_CONFIG_CANDIDATES = [
|
|
6
|
+
"auth.ts",
|
|
7
|
+
"auth.mts",
|
|
8
|
+
"auth.js",
|
|
9
|
+
"auth.mjs",
|
|
10
|
+
"auth.cts",
|
|
11
|
+
"auth.cjs"
|
|
12
|
+
];
|
|
13
|
+
function isVoidAuthConfigSource(code) {
|
|
14
|
+
return /\bfrom\s+["']void\/auth["']/.test(code);
|
|
15
|
+
}
|
|
16
|
+
function findVoidAuthConfig(root) {
|
|
17
|
+
for (const file of AUTH_CONFIG_CANDIDATES) {
|
|
18
|
+
const absPath = join(root, file);
|
|
19
|
+
if (!existsSync(absPath)) continue;
|
|
20
|
+
if (isVoidAuthConfigSource(readFileSync(absPath, "utf-8"))) return absPath;
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
async function loadVoidAuthConfig(configPath) {
|
|
25
|
+
if (!configPath) return;
|
|
26
|
+
const mod = await import(pathToFileURL(configPath).href);
|
|
27
|
+
return mod.default ?? mod.auth ?? mod.config;
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { loadVoidAuthConfig as n, findVoidAuthConfig as t };
|