From eb373046ed9f11f71df8acf3ddc2b8671faee95a Mon Sep 17 00:00:00 2001 From: Ben Durrant Date: Sat, 25 Jan 2025 19:52:36 +0000 Subject: [PATCH] Add Valibot presets, and move Zod presets to new entry point (#310) Co-authored-by: juliusmarminge --- .changeset/quick-elephants-confess.md | 13 + .vscode/settings.json | 16 +- bun.lock | 6 + docs/src/app/docs/customization/page.mdx | 2 +- examples/nextjs/app/env.ts | 2 +- packages/core/package.json | 16 +- packages/core/src/presets-valibot.ts | 198 +++++++++++++++ packages/core/src/presets-zod.ts | 198 +++++++++++++++ packages/core/src/presets.ts | 291 +++++++++-------------- packages/core/src/standard.ts | 9 + packages/nextjs/package.json | 16 +- packages/nextjs/src/presets-valibot.ts | 1 + packages/nextjs/src/presets-zod.ts | 1 + packages/nextjs/src/presets.ts | 1 - packages/nuxt/package.json | 16 +- packages/nuxt/src/presets-valibot.ts | 1 + packages/nuxt/src/presets-zod.ts | 1 + packages/nuxt/src/presets.ts | 1 - 18 files changed, 592 insertions(+), 197 deletions(-) create mode 100644 .changeset/quick-elephants-confess.md create mode 100644 packages/core/src/presets-valibot.ts create mode 100644 packages/core/src/presets-zod.ts create mode 100644 packages/nextjs/src/presets-valibot.ts create mode 100644 packages/nextjs/src/presets-zod.ts delete mode 100644 packages/nextjs/src/presets.ts create mode 100644 packages/nuxt/src/presets-valibot.ts create mode 100644 packages/nuxt/src/presets-zod.ts delete mode 100644 packages/nuxt/src/presets.ts diff --git a/.changeset/quick-elephants-confess.md b/.changeset/quick-elephants-confess.md new file mode 100644 index 00000000..e16ec7d4 --- /dev/null +++ b/.changeset/quick-elephants-confess.md @@ -0,0 +1,13 @@ +--- +"@t3-oss/env-nextjs": minor +"@t3-oss/env-core": minor +"@t3-oss/env-nuxt": minor +--- + +feat!: add valibot presets + +Presets using Valibot are now available using the `/presets-valibot` entrypoint. + +This feature comes with some breaking changes: + +- Zod presets have now been moved to `/presets-zod`. diff --git a/.vscode/settings.json b/.vscode/settings.json index 092cd91e..fc0255fa 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,11 +5,25 @@ }, "editor.formatOnSave": true, "editor.defaultFormatter": "biomejs.biome", + "[json]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[jsonc]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[javascript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[typescript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[typescriptreact]": { + "editor.defaultFormatter": "biomejs.biome" + }, "tailwindCSS.experimental.configFile": "./docs/tailwind.config.ts", "tailwindCSS.experimental.classRegex": [ ["clsx\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"] ], - "mdx.experimentalLanguageServer": true, "typescript.tsdk": "node_modules/typescript/lib", "typescript.enablePromptUseWorkspaceTsdk": true } diff --git a/bun.lock b/bun.lock index d40e4dae..0a2e2ca6 100644 --- a/bun.lock +++ b/bun.lock @@ -109,10 +109,12 @@ }, "peerDependencies": { "typescript": ">=5.0.0", + "valibot": "^1.0.0-beta.7 || ^1.0.0", "zod": "^3.24.0", }, "optionalPeers": [ "typescript", + "valibot", "zod", ], }, @@ -129,10 +131,12 @@ }, "peerDependencies": { "typescript": ">=5.0.0", + "valibot": "^1.0.0-beta.7 || ^1.0.0", "zod": "^3.24.0", }, "optionalPeers": [ "typescript", + "valibot", "zod", ], }, @@ -149,10 +153,12 @@ }, "peerDependencies": { "typescript": ">=5.0.0", + "valibot": "^1.0.0-beta.7 || ^1.0.0", "zod": "^3.24.0", }, "optionalPeers": [ "typescript", + "valibot", "zod", ], }, diff --git a/docs/src/app/docs/customization/page.mdx b/docs/src/app/docs/customization/page.mdx index a76a7b7c..b3316a8d 100644 --- a/docs/src/app/docs/customization/page.mdx +++ b/docs/src/app/docs/customization/page.mdx @@ -83,7 +83,7 @@ Your env object may extend other presets by using the `extends` property. This c ```ts title="src/env.ts" import { createEnv } from "@t3-oss/env-core"; -import { vercel } from "@t3-oss/env-core/presets"; +import { vercel } from "@t3-oss/env-core/presets-zod"; export const env = createEnv({ // ... diff --git a/examples/nextjs/app/env.ts b/examples/nextjs/app/env.ts index ec089fe9..1c03df47 100644 --- a/examples/nextjs/app/env.ts +++ b/examples/nextjs/app/env.ts @@ -1,5 +1,5 @@ import { createEnv } from "@t3-oss/env-nextjs"; -import { vercel } from "@t3-oss/env-nextjs/presets"; +import { vercel } from "@t3-oss/env-nextjs/presets-zod"; import { z } from "zod"; export const env = createEnv({ diff --git a/packages/core/package.json b/packages/core/package.json index 5e7c6167..04847223 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -16,9 +16,13 @@ "types": "./dist/index.d.ts", "default": "./dist/index.js" }, - "./presets": { - "types": "./dist/presets.d.ts", - "default": "./dist/presets.js" + "./presets-zod": { + "types": "./dist/presets-zod.d.ts", + "default": "./dist/presets-zod.js" + }, + "./presets-valibot": { + "types": "./dist/presets-valibot.d.ts", + "default": "./dist/presets-valibot.js" } }, "files": ["dist", "package.json", "LICENSE", "README.md"], @@ -29,7 +33,8 @@ }, "peerDependencies": { "typescript": ">=5.0.0", - "zod": "^3.24.0" + "zod": "^3.24.0", + "valibot": "^1.0.0-beta.7 || ^1.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -37,6 +42,9 @@ }, "zod": { "optional": true + }, + "valibot": { + "optional": true } }, "devDependencies": { diff --git a/packages/core/src/presets-valibot.ts b/packages/core/src/presets-valibot.ts new file mode 100644 index 00000000..cbb40e3c --- /dev/null +++ b/packages/core/src/presets-valibot.ts @@ -0,0 +1,198 @@ +import { url, optional, picklist, pipe, string } from "valibot"; +import type { StandardSchemaDictionary } from "."; +import { createEnv } from "."; +import type { + FlyEnv, + NeonVercelEnv, + NetlifyEnv, + RailwayEnv, + RenderEnv, + UploadThingEnv, + UploadThingV6Env, + VercelEnv, +} from "./presets"; + +/** + * Vercel System Environment Variables + * @see https://vercel.com/docs/projects/environment-variables/system-environment-variables#system-environment-variables + */ +export const vercel = () => + createEnv({ + server: { + VERCEL: optional(string()), + CI: optional(string()), + VERCEL_ENV: optional(picklist(["development", "preview", "production"])), + VERCEL_URL: optional(string()), + VERCEL_PROJECT_PRODUCTION_URL: optional(string()), + VERCEL_BRANCH_URL: optional(string()), + VERCEL_REGION: optional(string()), + VERCEL_DEPLOYMENT_ID: optional(string()), + VERCEL_SKEW_PROTECTION_ENABLED: optional(string()), + VERCEL_AUTOMATION_BYPASS_SECRET: optional(string()), + VERCEL_GIT_PROVIDER: optional(string()), + VERCEL_GIT_REPO_SLUG: optional(string()), + VERCEL_GIT_REPO_OWNER: optional(string()), + VERCEL_GIT_REPO_ID: optional(string()), + VERCEL_GIT_COMMIT_REF: optional(string()), + VERCEL_GIT_COMMIT_SHA: optional(string()), + VERCEL_GIT_COMMIT_MESSAGE: optional(string()), + VERCEL_GIT_COMMIT_AUTHOR_LOGIN: optional(string()), + VERCEL_GIT_COMMIT_AUTHOR_NAME: optional(string()), + VERCEL_GIT_PREVIOUS_SHA: optional(string()), + VERCEL_GIT_PULL_REQUEST_ID: optional(string()), + } satisfies StandardSchemaDictionary.Matching, + runtimeEnv: process.env, + }); + +/** + * Neon for Vercel Environment Variables + * @see https://neon.tech/docs/guides/vercel-native-integration#environment-variables-set-by-the-integration + */ +export const neonVercel = () => + createEnv({ + server: { + DATABASE_URL: string(), + DATABASE_URL_UNPOOLED: optional(string()), + PGHOST: optional(string()), + PGHOST_UNPOOLED: optional(string()), + PGUSER: optional(string()), + PGDATABASE: optional(string()), + PGPASSWORD: optional(string()), + POSTGRES_URL: optional(pipe(string(), url())), + POSTGRES_URL_NON_POOLING: optional(pipe(string(), url())), + POSTGRES_USER: optional(string()), + POSTGRES_HOST: optional(string()), + POSTGRES_PASSWORD: optional(string()), + POSTGRES_DATABASE: optional(string()), + POSTGRES_URL_NO_SSL: optional(pipe(string(), url())), + POSTGRES_PRISMA_URL: optional(pipe(string(), url())), + } satisfies StandardSchemaDictionary.Matching, + runtimeEnv: process.env, + }); + +/** + * @see https://v6.docs.uploadthing.com/getting-started/nuxt#add-env-variables + */ +export const uploadthingV6 = () => + createEnv({ + server: { + UPLOADTHING_TOKEN: string(), + } satisfies StandardSchemaDictionary.Matching, + runtimeEnv: process.env, + }); + +/** + * @see https://docs.uploadthing.com/getting-started/appdir#add-env-variables + */ +export const uploadthing = () => + createEnv({ + server: { + UPLOADTHING_TOKEN: string(), + } satisfies StandardSchemaDictionary.Matching, + runtimeEnv: process.env, + }); + +/** + * Render System Environment Variables + * @see https://docs.render.com/environment-variables#all-runtimes + */ +export const render = () => + createEnv({ + server: { + IS_PULL_REQUEST: optional(string()), + RENDER_DISCOVERY_SERVICE: optional(string()), + RENDER_EXTERNAL_HOSTNAME: optional(string()), + RENDER_EXTERNAL_URL: optional(pipe(string(), url())), + RENDER_GIT_BRANCH: optional(string()), + RENDER_GIT_COMMIT: optional(string()), + RENDER_GIT_REPO_SLUG: optional(string()), + RENDER_INSTANCE_ID: optional(string()), + RENDER_SERVICE_ID: optional(string()), + RENDER_SERVICE_NAME: optional(string()), + RENDER_SERVICE_TYPE: optional( + picklist(["web", "pserv", "cron", "worker", "static"]), + ), + RENDER: optional(string()), + } satisfies StandardSchemaDictionary.Matching, + runtimeEnv: process.env, + }); + +/** + * Railway Environment Variables + * @see https://docs.railway.app/reference/variables#railway-provided-variables + */ +export const railway = () => + createEnv({ + server: { + RAILWAY_PUBLIC_DOMAIN: optional(string()), + RAILWAY_PRIVATE_DOMAIN: optional(string()), + RAILWAY_TCP_PROXY_DOMAIN: optional(string()), + RAILWAY_TCP_PROXY_PORT: optional(string()), + RAILWAY_TCP_APPLICATION_PORT: optional(string()), + RAILWAY_PROJECT_NAME: optional(string()), + RAILWAY_PROJECT_ID: optional(string()), + RAILWAY_ENVIRONMENT_NAME: optional(string()), + RAILWAY_ENVIRONMENT_ID: optional(string()), + RAILWAY_SERVICE_NAME: optional(string()), + RAILWAY_SERVICE_ID: optional(string()), + RAILWAY_REPLICA_ID: optional(string()), + RAILWAY_DEPLOYMENT_ID: optional(string()), + RAILWAY_SNAPSHOT_ID: optional(string()), + RAILWAY_VOLUME_NAME: optional(string()), + RAILWAY_VOLUME_MOUNT_PATH: optional(string()), + RAILWAY_RUN_UID: optional(string()), + RAILWAY_GIT_COMMIT_SHA: optional(string()), + RAILWAY_GIT_AUTHOR_EMAIL: optional(string()), + RAILWAY_GIT_BRANCH: optional(string()), + RAILWAY_GIT_REPO_NAME: optional(string()), + RAILWAY_GIT_REPO_OWNER: optional(string()), + RAILWAY_GIT_COMMIT_MESSAGE: optional(string()), + } satisfies StandardSchemaDictionary.Matching, + runtimeEnv: process.env, + }); + +/** + * Fly.io Environment Variables + * @see https://fly.io/docs/machines/runtime-environment/#environment-variables + */ +export const fly = () => + createEnv({ + server: { + FLY_APP_NAME: optional(string()), + FLY_MACHINE_ID: optional(string()), + FLY_ALLOC_ID: optional(string()), + FLY_REGION: optional(string()), + FLY_PUBLIC_IP: optional(string()), + FLY_IMAGE_REF: optional(string()), + FLY_MACHINE_VERSION: optional(string()), + FLY_PRIVATE_IP: optional(string()), + FLY_PROCESS_GROUP: optional(string()), + FLY_VM_MEMORY_MB: optional(string()), + PRIMARY_REGION: optional(string()), + } satisfies StandardSchemaDictionary.Matching, + runtimeEnv: process.env, + }); + +/** + * Netlify Environment Variables + * @see https://docs.netlify.com/configure-builds/environment-variables + */ +export const netlify = () => + createEnv({ + server: { + NETLIFY: optional(string()), + BUILD_ID: optional(string()), + CONTEXT: optional( + picklist(["production", "deploy-preview", "branch-deploy", "dev"]), + ), + REPOSITORY_URL: optional(string()), + BRANCH: optional(string()), + URL: optional(string()), + DEPLOY_URL: optional(string()), + DEPLOY_PRIME_URL: optional(string()), + DEPLOY_ID: optional(string()), + SITE_NAME: optional(string()), + SITE_ID: optional(string()), + } satisfies StandardSchemaDictionary.Matching, + runtimeEnv: process.env, + }); diff --git a/packages/core/src/presets-zod.ts b/packages/core/src/presets-zod.ts new file mode 100644 index 00000000..62a6ea83 --- /dev/null +++ b/packages/core/src/presets-zod.ts @@ -0,0 +1,198 @@ +import { z } from "zod"; +import type { StandardSchemaDictionary } from "."; +import { createEnv } from "."; +import type { + FlyEnv, + NeonVercelEnv, + NetlifyEnv, + RailwayEnv, + RenderEnv, + UploadThingEnv, + UploadThingV6Env, + VercelEnv, +} from "./presets"; + +/** + * Vercel System Environment Variables + * @see https://vercel.com/docs/projects/environment-variables/system-environment-variables#system-environment-variables + */ +export const vercel = () => + createEnv({ + server: { + VERCEL: z.string().optional(), + CI: z.string().optional(), + VERCEL_ENV: z.enum(["development", "preview", "production"]).optional(), + VERCEL_URL: z.string().optional(), + VERCEL_PROJECT_PRODUCTION_URL: z.string().optional(), + VERCEL_BRANCH_URL: z.string().optional(), + VERCEL_REGION: z.string().optional(), + VERCEL_DEPLOYMENT_ID: z.string().optional(), + VERCEL_SKEW_PROTECTION_ENABLED: z.string().optional(), + VERCEL_AUTOMATION_BYPASS_SECRET: z.string().optional(), + VERCEL_GIT_PROVIDER: z.string().optional(), + VERCEL_GIT_REPO_SLUG: z.string().optional(), + VERCEL_GIT_REPO_OWNER: z.string().optional(), + VERCEL_GIT_REPO_ID: z.string().optional(), + VERCEL_GIT_COMMIT_REF: z.string().optional(), + VERCEL_GIT_COMMIT_SHA: z.string().optional(), + VERCEL_GIT_COMMIT_MESSAGE: z.string().optional(), + VERCEL_GIT_COMMIT_AUTHOR_LOGIN: z.string().optional(), + VERCEL_GIT_COMMIT_AUTHOR_NAME: z.string().optional(), + VERCEL_GIT_PREVIOUS_SHA: z.string().optional(), + VERCEL_GIT_PULL_REQUEST_ID: z.string().optional(), + } satisfies StandardSchemaDictionary.Matching, + runtimeEnv: process.env, + }); + +/** + * Neon for Vercel Environment Variables + * @see https://neon.tech/docs/guides/vercel-native-integration#environment-variables-set-by-the-integration + */ +export const neonVercel = () => + createEnv({ + server: { + DATABASE_URL: z.string(), + DATABASE_URL_UNPOOLED: z.string().optional(), + PGHOST: z.string().optional(), + PGHOST_UNPOOLED: z.string().optional(), + PGUSER: z.string().optional(), + PGDATABASE: z.string().optional(), + PGPASSWORD: z.string().optional(), + POSTGRES_URL: z.string().url().optional(), + POSTGRES_URL_NON_POOLING: z.string().url().optional(), + POSTGRES_USER: z.string().optional(), + POSTGRES_HOST: z.string().optional(), + POSTGRES_PASSWORD: z.string().optional(), + POSTGRES_DATABASE: z.string().optional(), + POSTGRES_URL_NO_SSL: z.string().url().optional(), + POSTGRES_PRISMA_URL: z.string().url().optional(), + } satisfies StandardSchemaDictionary.Matching, + runtimeEnv: process.env, + }); + +/** + * @see https://v6.docs.uploadthing.com/getting-started/nuxt#add-env-variables + */ +export const uploadthingV6 = () => + createEnv({ + server: { + UPLOADTHING_TOKEN: z.string(), + } satisfies StandardSchemaDictionary.Matching, + runtimeEnv: process.env, + }); + +/** + * @see https://docs.uploadthing.com/getting-started/appdir#add-env-variables + */ +export const uploadthing = () => + createEnv({ + server: { + UPLOADTHING_TOKEN: z.string(), + } satisfies StandardSchemaDictionary.Matching, + runtimeEnv: process.env, + }); + +/** + * Render System Environment Variables + * @see https://docs.render.com/environment-variables#all-runtimes + */ +export const render = () => + createEnv({ + server: { + IS_PULL_REQUEST: z.string().optional(), + RENDER_DISCOVERY_SERVICE: z.string().optional(), + RENDER_EXTERNAL_HOSTNAME: z.string().optional(), + RENDER_EXTERNAL_URL: z.string().url().optional(), + RENDER_GIT_BRANCH: z.string().optional(), + RENDER_GIT_COMMIT: z.string().optional(), + RENDER_GIT_REPO_SLUG: z.string().optional(), + RENDER_INSTANCE_ID: z.string().optional(), + RENDER_SERVICE_ID: z.string().optional(), + RENDER_SERVICE_NAME: z.string().optional(), + RENDER_SERVICE_TYPE: z + .enum(["web", "pserv", "cron", "worker", "static"]) + .optional(), + RENDER: z.string().optional(), + } satisfies StandardSchemaDictionary.Matching, + runtimeEnv: process.env, + }); + +/** + * Railway Environment Variables + * @see https://docs.railway.app/reference/variables#railway-provided-variables + */ +export const railway = () => + createEnv({ + server: { + RAILWAY_PUBLIC_DOMAIN: z.string().optional(), + RAILWAY_PRIVATE_DOMAIN: z.string().optional(), + RAILWAY_TCP_PROXY_DOMAIN: z.string().optional(), + RAILWAY_TCP_PROXY_PORT: z.string().optional(), + RAILWAY_TCP_APPLICATION_PORT: z.string().optional(), + RAILWAY_PROJECT_NAME: z.string().optional(), + RAILWAY_PROJECT_ID: z.string().optional(), + RAILWAY_ENVIRONMENT_NAME: z.string().optional(), + RAILWAY_ENVIRONMENT_ID: z.string().optional(), + RAILWAY_SERVICE_NAME: z.string().optional(), + RAILWAY_SERVICE_ID: z.string().optional(), + RAILWAY_REPLICA_ID: z.string().optional(), + RAILWAY_DEPLOYMENT_ID: z.string().optional(), + RAILWAY_SNAPSHOT_ID: z.string().optional(), + RAILWAY_VOLUME_NAME: z.string().optional(), + RAILWAY_VOLUME_MOUNT_PATH: z.string().optional(), + RAILWAY_RUN_UID: z.string().optional(), + RAILWAY_GIT_COMMIT_SHA: z.string().optional(), + RAILWAY_GIT_AUTHOR_EMAIL: z.string().optional(), + RAILWAY_GIT_BRANCH: z.string().optional(), + RAILWAY_GIT_REPO_NAME: z.string().optional(), + RAILWAY_GIT_REPO_OWNER: z.string().optional(), + RAILWAY_GIT_COMMIT_MESSAGE: z.string().optional(), + } satisfies StandardSchemaDictionary.Matching, + runtimeEnv: process.env, + }); + +/** + * Fly.io Environment Variables + * @see https://fly.io/docs/machines/runtime-environment/#environment-variables + */ +export const fly = () => + createEnv({ + server: { + FLY_APP_NAME: z.string().optional(), + FLY_MACHINE_ID: z.string().optional(), + FLY_ALLOC_ID: z.string().optional(), + FLY_REGION: z.string().optional(), + FLY_PUBLIC_IP: z.string().optional(), + FLY_IMAGE_REF: z.string().optional(), + FLY_MACHINE_VERSION: z.string().optional(), + FLY_PRIVATE_IP: z.string().optional(), + FLY_PROCESS_GROUP: z.string().optional(), + FLY_VM_MEMORY_MB: z.string().optional(), + PRIMARY_REGION: z.string().optional(), + } satisfies StandardSchemaDictionary.Matching, + runtimeEnv: process.env, + }); + +/** + * Netlify Environment Variables + * @see https://docs.netlify.com/configure-builds/environment-variables + */ +export const netlify = () => + createEnv({ + server: { + NETLIFY: z.string().optional(), + BUILD_ID: z.string().optional(), + CONTEXT: z + .enum(["production", "deploy-preview", "branch-deploy", "dev"]) + .optional(), + REPOSITORY_URL: z.string().optional(), + BRANCH: z.string().optional(), + URL: z.string().optional(), + DEPLOY_URL: z.string().optional(), + DEPLOY_PRIME_URL: z.string().optional(), + DEPLOY_ID: z.string().optional(), + SITE_NAME: z.string().optional(), + SITE_ID: z.string().optional(), + } satisfies StandardSchemaDictionary.Matching, + runtimeEnv: process.env, + }); diff --git a/packages/core/src/presets.ts b/packages/core/src/presets.ts index 6f4d5a0e..c4473fbc 100644 --- a/packages/core/src/presets.ts +++ b/packages/core/src/presets.ts @@ -1,187 +1,118 @@ -import { z } from "zod"; -import { createEnv } from "."; +export interface VercelEnv { + VERCEL?: string; + CI?: string; + VERCEL_ENV?: "development" | "preview" | "production"; + VERCEL_URL?: string; + VERCEL_PROJECT_PRODUCTION_URL?: string; + VERCEL_BRANCH_URL?: string; + VERCEL_REGION?: string; + VERCEL_DEPLOYMENT_ID?: string; + VERCEL_SKEW_PROTECTION_ENABLED?: string; + VERCEL_AUTOMATION_BYPASS_SECRET?: string; + VERCEL_GIT_PROVIDER?: string; + VERCEL_GIT_REPO_SLUG?: string; + VERCEL_GIT_REPO_OWNER?: string; + VERCEL_GIT_REPO_ID?: string; + VERCEL_GIT_COMMIT_REF?: string; + VERCEL_GIT_COMMIT_SHA?: string; + VERCEL_GIT_COMMIT_MESSAGE?: string; + VERCEL_GIT_COMMIT_AUTHOR_LOGIN?: string; + VERCEL_GIT_COMMIT_AUTHOR_NAME?: string; + VERCEL_GIT_PREVIOUS_SHA?: string; + VERCEL_GIT_PULL_REQUEST_ID?: string; +} -/** - * Vercel System Environment Variables - * @see https://vercel.com/docs/projects/environment-variables/system-environment-variables#system-environment-variables - */ -export const vercel = () => - createEnv({ - server: { - VERCEL: z.string().optional(), - CI: z.string().optional(), - VERCEL_ENV: z.enum(["development", "preview", "production"]).optional(), - VERCEL_URL: z.string().optional(), - VERCEL_PROJECT_PRODUCTION_URL: z.string().optional(), - VERCEL_BRANCH_URL: z.string().optional(), - VERCEL_REGION: z.string().optional(), - VERCEL_DEPLOYMENT_ID: z.string().optional(), - VERCEL_SKEW_PROTECTION_ENABLED: z.string().optional(), - VERCEL_AUTOMATION_BYPASS_SECRET: z.string().optional(), - VERCEL_GIT_PROVIDER: z.string().optional(), - VERCEL_GIT_REPO_SLUG: z.string().optional(), - VERCEL_GIT_REPO_OWNER: z.string().optional(), - VERCEL_GIT_REPO_ID: z.string().optional(), - VERCEL_GIT_COMMIT_REF: z.string().optional(), - VERCEL_GIT_COMMIT_SHA: z.string().optional(), - VERCEL_GIT_COMMIT_MESSAGE: z.string().optional(), - VERCEL_GIT_COMMIT_AUTHOR_LOGIN: z.string().optional(), - VERCEL_GIT_COMMIT_AUTHOR_NAME: z.string().optional(), - VERCEL_GIT_PREVIOUS_SHA: z.string().optional(), - VERCEL_GIT_PULL_REQUEST_ID: z.string().optional(), - }, - runtimeEnv: process.env, - }); +export interface NeonVercelEnv { + DATABASE_URL: string; + DATABASE_URL_UNPOOLED?: string; + PGHOST?: string; + PGHOST_UNPOOLED?: string; + PGUSER?: string; + PGDATABASE?: string; + PGPASSWORD?: string; + POSTGRES_URL?: string; + POSTGRES_URL_NON_POOLING?: string; + POSTGRES_USER?: string; + POSTGRES_HOST?: string; + POSTGRES_PASSWORD?: string; + POSTGRES_DATABASE?: string; + POSTGRES_URL_NO_SSL?: string; + POSTGRES_PRISMA_URL?: string; +} -/** - * Neon for Vercel Environment Variables - * @see https://neon.tech/docs/guides/vercel-native-integration#environment-variables-set-by-the-integration - */ -export const neonVercel = () => - createEnv({ - server: { - DATABASE_URL: z.string(), - DATABASE_URL_UNPOOLED: z.string().optional(), - PGHOST: z.string().optional(), - PGHOST_UNPOOLED: z.string().optional(), - PGUSER: z.string().optional(), - PGDATABASE: z.string().optional(), - PGPASSWORD: z.string().optional(), - POSTGRES_URL: z.string().url().optional(), - POSTGRES_URL_NON_POOLING: z.string().url().optional(), - POSTGRES_USER: z.string().optional(), - POSTGRES_HOST: z.string().optional(), - POSTGRES_PASSWORD: z.string().optional(), - POSTGRES_DATABASE: z.string().optional(), - POSTGRES_URL_NO_SSL: z.string().url().optional(), - POSTGRES_PRISMA_URL: z.string().url().optional(), - }, - runtimeEnv: process.env, - }); +export interface UploadThingV6Env { + UPLOADTHING_TOKEN: string; +} -/** - * @see https://v6.docs.uploadthing.com/getting-started/nuxt#add-env-variables - */ -export const uploadthingV6 = () => - createEnv({ - server: { - UPLOADTHING_TOKEN: z.string(), - }, - runtimeEnv: process.env, - }); +export interface UploadThingEnv { + UPLOADTHING_TOKEN: string; +} -/** - * @see https://docs.uploadthing.com/getting-started/appdir#add-env-variables - */ -export const uploadthing = () => - createEnv({ - server: { - UPLOADTHING_TOKEN: z.string(), - }, - runtimeEnv: process.env, - }); +export interface RenderEnv { + IS_PULL_REQUEST?: string; + RENDER_DISCOVERY_SERVICE?: string; + RENDER_EXTERNAL_HOSTNAME?: string; + RENDER_EXTERNAL_URL?: string; + RENDER_GIT_BRANCH?: string; + RENDER_GIT_COMMIT?: string; + RENDER_GIT_REPO_SLUG?: string; + RENDER_INSTANCE_ID?: string; + RENDER_SERVICE_ID?: string; + RENDER_SERVICE_NAME?: string; + RENDER_SERVICE_TYPE?: "web" | "pserv" | "cron" | "worker" | "static"; + RENDER?: string; +} -/** - * Render System Environment Variables - * @see https://docs.render.com/environment-variables#all-runtimes - */ -export const render = () => - createEnv({ - server: { - IS_PULL_REQUEST: z.string().optional(), - RENDER_DISCOVERY_SERVICE: z.string().optional(), - RENDER_EXTERNAL_HOSTNAME: z.string().optional(), - RENDER_EXTERNAL_URL: z.string().url().optional(), - RENDER_GIT_BRANCH: z.string().optional(), - RENDER_GIT_COMMIT: z.string().optional(), - RENDER_GIT_REPO_SLUG: z.string().optional(), - RENDER_INSTANCE_ID: z.string().optional(), - RENDER_SERVICE_ID: z.string().optional(), - RENDER_SERVICE_NAME: z.string().optional(), - RENDER_SERVICE_TYPE: z - .enum(["web", "pserv", "cron", "worker", "static"]) - .optional(), - RENDER: z.string().optional(), - }, - runtimeEnv: process.env, - }); +export interface RailwayEnv { + RAILWAY_PUBLIC_DOMAIN?: string; + RAILWAY_PRIVATE_DOMAIN?: string; + RAILWAY_TCP_PROXY_DOMAIN?: string; + RAILWAY_TCP_PROXY_PORT?: string; + RAILWAY_TCP_APPLICATION_PORT?: string; + RAILWAY_PROJECT_NAME?: string; + RAILWAY_PROJECT_ID?: string; + RAILWAY_ENVIRONMENT_NAME?: string; + RAILWAY_ENVIRONMENT_ID?: string; + RAILWAY_SERVICE_NAME?: string; + RAILWAY_SERVICE_ID?: string; + RAILWAY_REPLICA_ID?: string; + RAILWAY_DEPLOYMENT_ID?: string; + RAILWAY_SNAPSHOT_ID?: string; + RAILWAY_VOLUME_NAME?: string; + RAILWAY_VOLUME_MOUNT_PATH?: string; + RAILWAY_RUN_UID?: string; + RAILWAY_GIT_COMMIT_SHA?: string; + RAILWAY_GIT_AUTHOR_EMAIL?: string; + RAILWAY_GIT_BRANCH?: string; + RAILWAY_GIT_REPO_NAME?: string; + RAILWAY_GIT_REPO_OWNER?: string; + RAILWAY_GIT_COMMIT_MESSAGE?: string; +} -/** - * Railway Environment Variables - * @see https://docs.railway.app/reference/variables#railway-provided-variables - */ -export const railway = () => - createEnv({ - server: { - RAILWAY_PUBLIC_DOMAIN: z.string().optional(), - RAILWAY_PRIVATE_DOMAIN: z.string().optional(), - RAILWAY_TCP_PROXY_DOMAIN: z.string().optional(), - RAILWAY_TCP_PROXY_PORT: z.string().optional(), - RAILWAY_TCP_APPLICATION_PORT: z.string().optional(), - RAILWAY_PROJECT_NAME: z.string().optional(), - RAILWAY_PROJECT_ID: z.string().optional(), - RAILWAY_ENVIRONMENT_NAME: z.string().optional(), - RAILWAY_ENVIRONMENT_ID: z.string().optional(), - RAILWAY_SERVICE_NAME: z.string().optional(), - RAILWAY_SERVICE_ID: z.string().optional(), - RAILWAY_REPLICA_ID: z.string().optional(), - RAILWAY_DEPLOYMENT_ID: z.string().optional(), - RAILWAY_SNAPSHOT_ID: z.string().optional(), - RAILWAY_VOLUME_NAME: z.string().optional(), - RAILWAY_VOLUME_MOUNT_PATH: z.string().optional(), - RAILWAY_RUN_UID: z.string().optional(), - RAILWAY_GIT_COMMIT_SHA: z.string().optional(), - RAILWAY_GIT_AUTHOR_EMAIL: z.string().optional(), - RAILWAY_GIT_BRANCH: z.string().optional(), - RAILWAY_GIT_REPO_NAME: z.string().optional(), - RAILWAY_GIT_REPO_OWNER: z.string().optional(), - RAILWAY_GIT_COMMIT_MESSAGE: z.string().optional(), - }, - runtimeEnv: process.env, - }); +export interface FlyEnv { + FLY_APP_NAME?: string; + FLY_MACHINE_ID?: string; + FLY_ALLOC_ID?: string; + FLY_REGION?: string; + FLY_PUBLIC_IP?: string; + FLY_IMAGE_REF?: string; + FLY_MACHINE_VERSION?: string; + FLY_PRIVATE_IP?: string; + FLY_PROCESS_GROUP?: string; + FLY_VM_MEMORY_MB?: string; + PRIMARY_REGION?: string; +} -/** - * Fly.io Environment Variables - * @see https://fly.io/docs/machines/runtime-environment/#environment-variables - */ -export const fly = () => - createEnv({ - server: { - FLY_APP_NAME: z.string().optional(), - FLY_MACHINE_ID: z.string().optional(), - FLY_ALLOC_ID: z.string().optional(), - FLY_REGION: z.string().optional(), - FLY_PUBLIC_IP: z.string().optional(), - FLY_IMAGE_REF: z.string().optional(), - FLY_MACHINE_VERSION: z.string().optional(), - FLY_PRIVATE_IP: z.string().optional(), - FLY_PROCESS_GROUP: z.string().optional(), - FLY_VM_MEMORY_MB: z.string().optional(), - PRIMARY_REGION: z.string().optional(), - }, - runtimeEnv: process.env, - }); - -/** - * Netlify Environment Variables - * @see https://docs.netlify.com/configure-builds/environment-variables - */ -export const netlify = () => - createEnv({ - server: { - NETLIFY: z.string().optional(), - BUILD_ID: z.string().optional(), - CONTEXT: z - .enum(["production", "deploy-preview", "branch-deploy", "dev"]) - .optional(), - REPOSITORY_URL: z.string().optional(), - BRANCH: z.string().optional(), - URL: z.string().optional(), - DEPLOY_URL: z.string().optional(), - DEPLOY_PRIME_URL: z.string().optional(), - DEPLOY_ID: z.string().optional(), - SITE_NAME: z.string().optional(), - SITE_ID: z.string().optional(), - }, - runtimeEnv: process.env, - }); +export interface NetlifyEnv { + NETLIFY?: string; + BUILD_ID?: string; + CONTEXT?: "production" | "deploy-preview" | "branch-deploy" | "dev"; + REPOSITORY_URL?: string; + BRANCH?: string; + URL?: string; + DEPLOY_URL?: string; + DEPLOY_PRIME_URL?: string; + DEPLOY_ID?: string; + SITE_NAME?: string; + SITE_ID?: string; +} diff --git a/packages/core/src/standard.ts b/packages/core/src/standard.ts index 8202f213..9cccb66b 100644 --- a/packages/core/src/standard.ts +++ b/packages/core/src/standard.ts @@ -71,6 +71,15 @@ export declare namespace StandardSchemaV1 { export type StandardSchemaDictionary = Record; export namespace StandardSchemaDictionary { + /** + * A dictionary of Standard Schemas that match the input and output types. + */ + export type Matching< + Input, + Output extends Record = Input, + > = { + [K in keyof Input]-?: StandardSchemaV1; + }; export type InferInput = { [K in keyof T]: StandardSchemaV1.InferInput; }; diff --git a/packages/nextjs/package.json b/packages/nextjs/package.json index e0284915..2ee42ce1 100644 --- a/packages/nextjs/package.json +++ b/packages/nextjs/package.json @@ -16,9 +16,13 @@ "types": "./dist/index.d.ts", "default": "./dist/index.js" }, - "./presets": { - "types": "./dist/presets.d.ts", - "default": "./dist/presets.js" + "./presets-zod": { + "types": "./dist/presets-zod.d.ts", + "default": "./dist/presets-zod.js" + }, + "./presets-valibot": { + "types": "./dist/presets-valibot.d.ts", + "default": "./dist/presets-valibot.js" } }, "files": ["dist", "package.json", "LICENSE", "README.md"], @@ -33,7 +37,8 @@ }, "peerDependencies": { "typescript": ">=5.0.0", - "zod": "^3.24.0" + "zod": "^3.24.0", + "valibot": "^1.0.0-beta.7 || ^1.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -41,6 +46,9 @@ }, "zod": { "optional": true + }, + "valibot": { + "optional": true } }, "devDependencies": { diff --git a/packages/nextjs/src/presets-valibot.ts b/packages/nextjs/src/presets-valibot.ts new file mode 100644 index 00000000..59b457de --- /dev/null +++ b/packages/nextjs/src/presets-valibot.ts @@ -0,0 +1 @@ +export * from "@t3-oss/env-core/presets-valibot"; diff --git a/packages/nextjs/src/presets-zod.ts b/packages/nextjs/src/presets-zod.ts new file mode 100644 index 00000000..00aded79 --- /dev/null +++ b/packages/nextjs/src/presets-zod.ts @@ -0,0 +1 @@ +export * from "@t3-oss/env-core/presets-zod"; diff --git a/packages/nextjs/src/presets.ts b/packages/nextjs/src/presets.ts deleted file mode 100644 index 4d04514e..00000000 --- a/packages/nextjs/src/presets.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "@t3-oss/env-core/presets"; diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index 059707fa..da3c857b 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -16,9 +16,13 @@ "types": "./dist/index.d.ts", "default": "./dist/index.js" }, - "./presets": { - "types": "./dist/presets.d.ts", - "default": "./dist/presets.js" + "./presets-zod": { + "types": "./dist/presets-zod.d.ts", + "default": "./dist/presets-zod.js" + }, + "./presets-valibot": { + "types": "./dist/presets-valibot.d.ts", + "default": "./dist/presets-valibot.js" } }, "files": ["dist", "package.json", "LICENSE", "README.md"], @@ -33,7 +37,8 @@ }, "peerDependencies": { "typescript": ">=5.0.0", - "zod": "^3.24.0" + "zod": "^3.24.0", + "valibot": "^1.0.0-beta.7 || ^1.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -41,6 +46,9 @@ }, "zod": { "optional": true + }, + "valibot": { + "optional": true } }, "devDependencies": { diff --git a/packages/nuxt/src/presets-valibot.ts b/packages/nuxt/src/presets-valibot.ts new file mode 100644 index 00000000..59b457de --- /dev/null +++ b/packages/nuxt/src/presets-valibot.ts @@ -0,0 +1 @@ +export * from "@t3-oss/env-core/presets-valibot"; diff --git a/packages/nuxt/src/presets-zod.ts b/packages/nuxt/src/presets-zod.ts new file mode 100644 index 00000000..00aded79 --- /dev/null +++ b/packages/nuxt/src/presets-zod.ts @@ -0,0 +1 @@ +export * from "@t3-oss/env-core/presets-zod"; diff --git a/packages/nuxt/src/presets.ts b/packages/nuxt/src/presets.ts deleted file mode 100644 index 4d04514e..00000000 --- a/packages/nuxt/src/presets.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "@t3-oss/env-core/presets";