From 6070c868c867b8d6d77a6253e66e7008e8eeb9a9 Mon Sep 17 00:00:00 2001
From: juliusmarminge
Date: Wed, 24 Jan 2024 19:46:57 +0100
Subject: [PATCH] tabwidth 2
---
.changeset/config.json | 26 +-
.github/canary-version.js | 52 +-
.vscode/settings.json | 1 -
biome.json | 74 +-
docs/mdx-components.tsx | 164 +--
docs/next.config.js | 66 +-
docs/postcss.config.cjs | 8 +-
docs/src/app/docs/layout.tsx | 28 +-
docs/src/app/layout.tsx | 136 ++-
docs/src/app/page.tsx | 112 +--
docs/src/app/site-config.ts | 106 +-
docs/src/components/icons.tsx | 238 ++---
docs/src/components/layout.tsx | 14 +-
docs/src/components/main-nav.tsx | 63 +-
docs/src/components/mdx/callout.tsx | 120 +--
docs/src/components/mdx/code-block.tsx | 122 ++-
docs/src/components/mobile-nav.tsx | 134 ++-
docs/src/components/sidebar.tsx | 107 +-
docs/src/components/site-header.tsx | 80 +-
docs/src/components/tailwind-indicator.tsx | 28 +-
docs/src/components/theme-provider.tsx | 2 +-
docs/src/components/theme-toggle.tsx | 24 +-
docs/src/components/ui/button.tsx | 73 +-
docs/src/components/ui/popover.tsx | 28 +-
docs/src/components/ui/scroll-area.tsx | 62 +-
docs/src/lib/cn.ts | 2 +-
docs/tailwind.config.ts | 212 ++--
examples/astro/astro.config.mjs | 2 +-
examples/astro/src/counter.tsx | 4 +-
examples/astro/src/t3-env.ts | 24 +-
examples/nextjs/app/api/edge/route.ts | 2 +-
examples/nextjs/app/api/node/route.ts | 2 +-
examples/nextjs/app/edge/page.tsx | 18 +-
examples/nextjs/app/env.js | 28 +-
examples/nextjs/app/layout.tsx | 20 +-
examples/nextjs/app/node/page.tsx | 18 +-
examples/nextjs/app/page.tsx | 2 +-
examples/nextjs/next.config.js | 6 +-
examples/nuxt/env.ts | 12 +-
examples/nuxt/nuxt.config.ts | 2 +-
examples/nuxt/server/api/hello.get.ts | 6 +-
packages/core/src/index.ts | 468 +++++----
packages/core/src/presets.ts | 40 +-
packages/core/test/smoke.test.ts | 1057 ++++++++++----------
packages/nextjs/src/index.ts | 136 ++-
packages/nextjs/test/smoke.test.ts | 550 +++++-----
packages/nuxt/src/index.ts | 50 +-
replace-workspace-protocol.ts | 8 +-
turbo.json | 46 +-
49 files changed, 2272 insertions(+), 2311 deletions(-)
diff --git a/.changeset/config.json b/.changeset/config.json
index 67b4a918..22b480f9 100644
--- a/.changeset/config.json
+++ b/.changeset/config.json
@@ -1,15 +1,15 @@
{
- "$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json",
- "changelog": ["@changesets/changelog-github", { "repo": "t3-oss/t3-env" }],
- "commit": false,
- "access": "public",
- "baseBranch": "main",
- "updateInternalDependencies": "patch",
- "fixed": [["@t3-oss/env-core", "@t3-oss/env-nextjs", "@t3-oss/env-nuxt"]],
- "ignore": [
- "@examples/astro",
- "@examples/nextjs",
- "@examples/nuxt",
- "@t3-env/docs"
- ]
+ "$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json",
+ "changelog": ["@changesets/changelog-github", { "repo": "t3-oss/t3-env" }],
+ "commit": false,
+ "access": "public",
+ "baseBranch": "main",
+ "updateInternalDependencies": "patch",
+ "fixed": [["@t3-oss/env-core", "@t3-oss/env-nextjs", "@t3-oss/env-nuxt"]],
+ "ignore": [
+ "@examples/astro",
+ "@examples/nextjs",
+ "@examples/nuxt",
+ "@t3-env/docs"
+ ]
}
diff --git a/.github/canary-version.js b/.github/canary-version.js
index 1bbebd5e..84c159b3 100644
--- a/.github/canary-version.js
+++ b/.github/canary-version.js
@@ -2,39 +2,37 @@ import { exec } from "child_process";
import fs from "fs";
const pkgJsonPaths = [
- "packages/core/package.json",
- "packages/nextjs/package.json",
- "packages/nuxt/package.json",
+ "packages/core/package.json",
+ "packages/nextjs/package.json",
+ "packages/nuxt/package.json",
];
try {
- exec("git rev-parse --short HEAD", (err, stdout) => {
- if (err) {
- console.log(err);
- process.exit(1);
- }
- const commitHash = stdout.trim();
+ exec("git rev-parse --short HEAD", (err, stdout) => {
+ if (err) {
+ console.log(err);
+ process.exit(1);
+ }
+ const commitHash = stdout.trim();
- for (const pkgJsonPath of pkgJsonPaths) {
- const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
- const oldVersion = pkg.version;
- const [major, minor, patch] = oldVersion.split(".").map(Number);
- const newVersion = `${major}.${minor}.${
- patch + 1
- }-canary.${commitHash}`;
+ for (const pkgJsonPath of pkgJsonPaths) {
+ const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
+ const oldVersion = pkg.version;
+ const [major, minor, patch] = oldVersion.split(".").map(Number);
+ const newVersion = `${major}.${minor}.${patch + 1}-canary.${commitHash}`;
- pkg.version = newVersion;
+ pkg.version = newVersion;
- const content = `${JSON.stringify(pkg, null, "\t")}\n`;
- const newContent = content.replace(
- new RegExp(`"@t3-oss/\\*": "${oldVersion}"`, "g"),
- `"@t3-oss/*": "${newVersion}"`,
- );
+ const content = `${JSON.stringify(pkg, null, "\t")}\n`;
+ const newContent = content.replace(
+ new RegExp(`"@t3-oss/\\*": "${oldVersion}"`, "g"),
+ `"@t3-oss/*": "${newVersion}"`,
+ );
- fs.writeFileSync(pkgJsonPath, newContent);
- }
- });
+ fs.writeFileSync(pkgJsonPath, newContent);
+ }
+ });
} catch (error) {
- console.error(error);
- process.exit(1);
+ console.error(error);
+ process.exit(1);
}
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 7dbc802e..092cd91e 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,5 +1,4 @@
{
- "biome.lspBin": "node_modules/.bin/biome",
"editor.codeActionsOnSave": {
"quickfix.biome": "explicit",
"source.organizeImports.biome": "explicit"
diff --git a/biome.json b/biome.json
index c714eb65..7cf22f20 100644
--- a/biome.json
+++ b/biome.json
@@ -1,42 +1,42 @@
{
- "$schema": "https://biomejs.dev/schemas/1.5.3/schema.json",
- "organizeImports": {
- "enabled": true
- },
- "formatter": {
- "enabled": true,
- "indentWidth": 4,
- "indentStyle": "space"
- },
- "linter": {
- "enabled": true,
+ "$schema": "https://biomejs.dev/schemas/1.5.3/schema.json",
+ "organizeImports": {
+ "enabled": true
+ },
+ "formatter": {
+ "enabled": true,
+ "indentWidth": 2,
+ "indentStyle": "space"
+ },
+ "linter": {
+ "enabled": true,
+ "rules": {
+ "recommended": true,
+ "a11y": {
+ "noSvgWithoutTitle": "off",
+ "useButtonType": "off",
+ "useAltText": "off"
+ },
+ "complexity": {
+ "noBannedTypes": "off"
+ }
+ }
+ },
+ "overrides": [
+ {
+ "include": ["**/*.test.ts"],
+ "linter": {
"rules": {
- "recommended": true,
- "a11y": {
- "noSvgWithoutTitle": "off",
- "useButtonType": "off",
- "useAltText": "off"
- },
- "complexity": {
- "noBannedTypes": "off"
- }
- }
- },
- "overrides": [
- {
- "include": ["**/*.test.ts"],
- "linter": {
- "rules": {
- "suspicious": {
- "noExplicitAny": "off"
- }
- }
- }
+ "suspicious": {
+ "noExplicitAny": "off"
+ }
}
- ],
- "vcs": {
- "enabled": true,
- "clientKind": "git",
- "useIgnoreFile": true
+ }
}
+ ],
+ "vcs": {
+ "enabled": true,
+ "clientKind": "git",
+ "useIgnoreFile": true
+ }
}
diff --git a/docs/mdx-components.tsx b/docs/mdx-components.tsx
index e64c06ae..bd09ddd9 100644
--- a/docs/mdx-components.tsx
+++ b/docs/mdx-components.tsx
@@ -8,92 +8,92 @@ import { Codeblock } from "@/components/mdx/code-block";
// This file is required to use MDX in `app` directory.
export function useMDXComponents(components: MDXComponents): MDXComponents {
- return {
- // Allows customizing built-in components, e.g. to add styling.
- h1: ({ children, ...props }) => (
-
- {children}
-
- ),
- h2: ({ children, ...props }) => (
-
- ),
- h3: ({ children, ...props }) => (
-
- ),
- h4: ({ children, ...props }) => (
-
- ),
- p: (props) => (
-
- ),
- a: ({ children, href }) => {
- const isExternal = href?.startsWith("http");
- const Component = isExternal ? "a" : Link;
- return (
-
- {children}
-
- );
- },
- ul: (props) => ,
- code: (props) => (
-
- ),
- pre: Codeblock,
+ return {
+ // Allows customizing built-in components, e.g. to add styling.
+ h1: ({ children, ...props }) => (
+
+ {children}
+
+ ),
+ h2: ({ children, ...props }) => (
+
+ ),
+ h3: ({ children, ...props }) => (
+
+ ),
+ h4: ({ children, ...props }) => (
+
+ ),
+ p: (props) => (
+
+ ),
+ a: ({ children, href }) => {
+ const isExternal = href?.startsWith("http");
+ const Component = isExternal ? "a" : Link;
+ return (
+
+ {children}
+
+ );
+ },
+ ul: (props) => ,
+ code: (props) => (
+
+ ),
+ pre: Codeblock,
- img: (props) =>
,
+ img: (props) =>
,
- // Add custom components.
- Callout,
- Steps: ({ ...props }) => (
-
- ),
+ // Add custom components.
+ Callout,
+ Steps: ({ ...props }) => (
+
+ ),
- // Pass through all other components.
- ...components,
- };
+ // Pass through all other components.
+ ...components,
+ };
}
function slugify(input: unknown) {
- if (typeof input !== "string") {
- return "";
- }
- return input.replaceAll(" ", "-").toLowerCase().trim();
+ if (typeof input !== "string") {
+ return "";
+ }
+ return input.replaceAll(" ", "-").toLowerCase().trim();
}
diff --git a/docs/next.config.js b/docs/next.config.js
index 74efc11b..003599b1 100644
--- a/docs/next.config.js
+++ b/docs/next.config.js
@@ -4,40 +4,40 @@ import { getHighlighter } from "shiki";
/** @type {import('next').NextConfig} */
const nextConfig = {
- pageExtensions: ["ts", "tsx", "mdx"],
- redirects: () => [
- { source: "/docs", destination: "/docs/introduction", permanent: true },
- ],
- eslint: {
- ignoreDuringBuilds: true,
- },
+ pageExtensions: ["ts", "tsx", "mdx"],
+ redirects: () => [
+ { source: "/docs", destination: "/docs/introduction", permanent: true },
+ ],
+ eslint: {
+ ignoreDuringBuilds: true,
+ },
};
export default withMdx({
- options: {
- rehypePlugins: [
- [
- rehypePrettyCode,
- /** @type {import("rehype-pretty-code").Options} */
- ({
- theme: { dark: "one-dark-pro", light: "min-light" },
- getHighlighter,
- onVisitLine(node) {
- // Prevent lines from collapsing in `display: grid` mode, and allow empty
- // lines to be copy/pasted
- if (node.children.length === 0) {
- node.children = [{ type: "text", value: " " }];
- }
- },
- onVisitHighlightedLine(node) {
- node.properties.className.push("line--highlighted");
- },
- onVisitHighlightedWord(node, id) {
- node.properties.className = ["word"];
- node.properties["data-word-id"] = id;
- },
- }),
- ],
- ],
- },
+ options: {
+ rehypePlugins: [
+ [
+ rehypePrettyCode,
+ /** @type {import("rehype-pretty-code").Options} */
+ ({
+ theme: { dark: "one-dark-pro", light: "min-light" },
+ getHighlighter,
+ onVisitLine(node) {
+ // Prevent lines from collapsing in `display: grid` mode, and allow empty
+ // lines to be copy/pasted
+ if (node.children.length === 0) {
+ node.children = [{ type: "text", value: " " }];
+ }
+ },
+ onVisitHighlightedLine(node) {
+ node.properties.className.push("line--highlighted");
+ },
+ onVisitHighlightedWord(node, id) {
+ node.properties.className = ["word"];
+ node.properties["data-word-id"] = id;
+ },
+ }),
+ ],
+ ],
+ },
})(nextConfig);
diff --git a/docs/postcss.config.cjs b/docs/postcss.config.cjs
index 67cdf1a5..12a703d9 100644
--- a/docs/postcss.config.cjs
+++ b/docs/postcss.config.cjs
@@ -1,6 +1,6 @@
module.exports = {
- plugins: {
- tailwindcss: {},
- autoprefixer: {},
- },
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
};
diff --git a/docs/src/app/docs/layout.tsx b/docs/src/app/docs/layout.tsx
index 4c59eaf1..2badb32c 100644
--- a/docs/src/app/docs/layout.tsx
+++ b/docs/src/app/docs/layout.tsx
@@ -5,21 +5,21 @@ import { Metadata } from "next";
import { ReactNode } from "react";
export const metadata: Metadata = {
- title: {
- default: "Docs ⋅ T3 Env",
- template: "%s ⋅ T3 Env",
- },
+ title: {
+ default: "Docs ⋅ T3 Env",
+ template: "%s ⋅ T3 Env",
+ },
};
export default function DocsLayout(props: { children: ReactNode }) {
- return (
-
- );
+ return (
+
+ );
}
diff --git a/docs/src/app/layout.tsx b/docs/src/app/layout.tsx
index c6ab9ff3..c78590fc 100644
--- a/docs/src/app/layout.tsx
+++ b/docs/src/app/layout.tsx
@@ -11,93 +11,89 @@ import { Inter, JetBrains_Mono } from "next/font/google";
import localFont from "next/font/local";
const fontSans = Inter({
- subsets: ["latin"],
- variable: "--font-sans",
+ subsets: ["latin"],
+ variable: "--font-sans",
});
const fontCal = localFont({
- src: "../styles/calsans.ttf",
- variable: "--font-cal",
- display: "swap",
+ src: "../styles/calsans.ttf",
+ variable: "--font-cal",
+ display: "swap",
});
const fontMono = JetBrains_Mono({
- subsets: ["latin"],
- variable: "--font-mono",
+ subsets: ["latin"],
+ variable: "--font-mono",
});
export const metadata: Metadata = {
- metadataBase: new URL("https://env.t3.gg"),
- title: {
- default: siteConfig.name,
- template: `%s - ${siteConfig.name}`,
- },
+ metadataBase: new URL("https://env.t3.gg"),
+ title: {
+ default: siteConfig.name,
+ template: `%s - ${siteConfig.name}`,
+ },
+ description: siteConfig.description,
+ icons: {
+ icon: "/favicon.ico",
+ shortcut: "/favicon-16x16.png",
+ apple: "/apple-touch-icon.png",
+ },
+ openGraph: {
+ type: "website",
+ locale: "en_US",
+ title: siteConfig.name,
description: siteConfig.description,
- icons: {
- icon: "/favicon.ico",
- shortcut: "/favicon-16x16.png",
- apple: "/apple-touch-icon.png",
- },
- openGraph: {
- type: "website",
- locale: "en_US",
- title: siteConfig.name,
- description: siteConfig.description,
- images: [
- {
- url: "/opengraph-image.png",
- width: 910,
- height: 455,
- alt: siteConfig.name,
- },
- ],
- },
- twitter: {
- card: "summary_large_image",
- title: siteConfig.name,
- description: siteConfig.description,
- images: [{ url: "/opengraph-image.png" }],
- },
+ images: [
+ {
+ url: "/opengraph-image.png",
+ width: 910,
+ height: 455,
+ alt: siteConfig.name,
+ },
+ ],
+ },
+ twitter: {
+ card: "summary_large_image",
+ title: siteConfig.name,
+ description: siteConfig.description,
+ images: [{ url: "/opengraph-image.png" }],
+ },
};
export const viewport: Viewport = {
- themeColor: [
- { media: "(prefers-color-scheme: light)", color: "white" },
- { media: "(prefers-color-scheme: dark)", color: "black" },
- ],
+ themeColor: [
+ { media: "(prefers-color-scheme: light)", color: "white" },
+ { media: "(prefers-color-scheme: dark)", color: "black" },
+ ],
};
interface RootLayoutProps {
- children: React.ReactNode;
+ children: React.ReactNode;
}
export default function RootLayout({ children }: RootLayoutProps) {
- return (
- <>
-
-
-
-
-
-
-
-
-
-
- >
- );
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+ >
+ );
}
diff --git a/docs/src/app/page.tsx b/docs/src/app/page.tsx
index 8d19d01c..e072adaa 100644
--- a/docs/src/app/page.tsx
+++ b/docs/src/app/page.tsx
@@ -6,60 +6,60 @@ import { Icons } from "@/components/icons";
import { buttonVariants } from "@/components/ui/button";
export default function IndexPage() {
- return (
-
-
-
-
- Framework agnostic validation for{" "}
-
- type-safe
- {" "}
- environment variables.
-
-
-
- {siteConfig.description}
-
-
-
- Documentation
-
-
-
- GitHub
-
-
-
-
- );
+ return (
+
+
+
+
+ Framework agnostic validation for{" "}
+
+ type-safe
+ {" "}
+ environment variables.
+
+
+
+ {siteConfig.description}
+
+
+
+ Documentation
+
+
+
+ GitHub
+
+
+
+
+ );
}
diff --git a/docs/src/app/site-config.ts b/docs/src/app/site-config.ts
index 070d1404..cad360c8 100644
--- a/docs/src/app/site-config.ts
+++ b/docs/src/app/site-config.ts
@@ -1,66 +1,66 @@
export type SiteConfig = typeof siteConfig;
export const siteConfig = {
- name: "Env",
- description:
- "Never build your apps with invalid environment variables again. Validate and transform your environment with the full power of Zod.",
- mainNav: [
+ name: "Env",
+ description:
+ "Never build your apps with invalid environment variables again. Validate and transform your environment with the full power of Zod.",
+ mainNav: [
+ {
+ title: "Documentation",
+ href: "/docs/introduction",
+ },
+ ],
+ sidebarNav: [
+ {
+ title: "Getting Started",
+ items: [
+ {
+ title: "Introduction",
+ href: "/docs/introduction",
+ items: [],
+ },
+ ],
+ },
+ {
+ title: "Framework Guides",
+ items: [
{
- title: "Documentation",
- href: "/docs/introduction",
+ title: "Agnostic Core",
+ href: "/docs/core",
+ items: [],
},
- ],
- sidebarNav: [
{
- title: "Getting Started",
- items: [
- {
- title: "Introduction",
- href: "/docs/introduction",
- items: [],
- },
- ],
+ title: "Next.js",
+ href: "/docs/nextjs",
+ items: [],
},
{
- title: "Framework Guides",
- items: [
- {
- title: "Agnostic Core",
- href: "/docs/core",
- items: [],
- },
- {
- title: "Next.js",
- href: "/docs/nextjs",
- items: [],
- },
- {
- title: "Nuxt",
- href: "/docs/nuxt",
- items: [],
- },
- ],
+ title: "Nuxt",
+ href: "/docs/nuxt",
+ items: [],
+ },
+ ],
+ },
+ {
+ title: "Further Reading",
+ items: [
+ {
+ title: "Recipes",
+ href: "/docs/recipes",
+ items: [],
},
{
- title: "Further Reading",
- items: [
- {
- title: "Recipes",
- href: "/docs/recipes",
- items: [],
- },
- {
- title: "Customization",
- href: "/docs/customization",
- label: "New",
- items: [],
- },
- ],
+ title: "Customization",
+ href: "/docs/customization",
+ label: "New",
+ items: [],
},
- ],
- links: {
- // twitter: "https://twitter.com/",
- github: "https://github.com/t3-oss/t3-env",
- docs: "/docs",
+ ],
},
+ ],
+ links: {
+ // twitter: "https://twitter.com/",
+ github: "https://github.com/t3-oss/t3-env",
+ docs: "/docs",
+ },
};
diff --git a/docs/src/components/icons.tsx b/docs/src/components/icons.tsx
index 9e84043f..c00d7d83 100644
--- a/docs/src/components/icons.tsx
+++ b/docs/src/components/icons.tsx
@@ -1,126 +1,126 @@
import {
- type Icon as LucideIcon,
- Link,
- LucideProps,
- Moon,
- SunMedium,
- TerminalSquare,
- Twitter,
+ type Icon as LucideIcon,
+ Link,
+ LucideProps,
+ Moon,
+ SunMedium,
+ TerminalSquare,
+ Twitter,
} from "lucide-react";
export type Icon = LucideIcon;
export const Icons = {
- sun: SunMedium,
- moon: Moon,
- twitter: Twitter,
- logo: (props: LucideProps) => (
-
- ),
- gitHub: (props: LucideProps) => (
-
- ),
- javascript: (props: LucideProps) => (
-
- ),
- typescript: (props: LucideProps) => (
-
- ),
- vue: (props: LucideProps) => (
-
- ),
- bash: TerminalSquare,
- menu: (props: LucideProps) => (
-
- ),
- link: Link,
+ sun: SunMedium,
+ moon: Moon,
+ twitter: Twitter,
+ logo: (props: LucideProps) => (
+
+ ),
+ gitHub: (props: LucideProps) => (
+
+ ),
+ javascript: (props: LucideProps) => (
+
+ ),
+ typescript: (props: LucideProps) => (
+
+ ),
+ vue: (props: LucideProps) => (
+
+ ),
+ bash: TerminalSquare,
+ menu: (props: LucideProps) => (
+
+ ),
+ link: Link,
};
diff --git a/docs/src/components/layout.tsx b/docs/src/components/layout.tsx
index 0be56cb1..bd911d51 100644
--- a/docs/src/components/layout.tsx
+++ b/docs/src/components/layout.tsx
@@ -1,14 +1,14 @@
import { SiteHeader } from "@/components/site-header";
interface LayoutProps {
- children: React.ReactNode;
+ children: React.ReactNode;
}
export function Layout({ children }: LayoutProps) {
- return (
- <>
-
- {children}
- >
- );
+ return (
+ <>
+
+ {children}
+ >
+ );
}
diff --git a/docs/src/components/main-nav.tsx b/docs/src/components/main-nav.tsx
index 1a892f10..4422ed96 100644
--- a/docs/src/components/main-nav.tsx
+++ b/docs/src/components/main-nav.tsx
@@ -8,41 +8,40 @@ import { cn } from "@/lib/cn";
import { useSelectedLayoutSegment } from "next/navigation";
export interface NavItem {
- title: string;
- href?: string;
- disabled?: boolean;
- external?: boolean;
- icon?: keyof typeof Icons;
- label?: string;
+ title: string;
+ href?: string;
+ disabled?: boolean;
+ external?: boolean;
+ icon?: keyof typeof Icons;
+ label?: string;
}
export function MainNav(props: { items: NavItem[] }) {
- const segment = useSelectedLayoutSegment();
+ const segment = useSelectedLayoutSegment();
- const isActive = (href: string) => {
- if (!segment) return false;
- return href.startsWith(`/${segment}`);
- };
+ const isActive = (href: string) => {
+ if (!segment) return false;
+ return href.startsWith(`/${segment}`);
+ };
- return (
-
- );
+ return (
+
+ );
}
diff --git a/docs/src/components/mdx/callout.tsx b/docs/src/components/mdx/callout.tsx
index 0eb7e397..5c44a18b 100644
--- a/docs/src/components/mdx/callout.tsx
+++ b/docs/src/components/mdx/callout.tsx
@@ -4,83 +4,83 @@
import clsx from "clsx";
import React, {
- type ComponentProps,
- type ReactElement,
- type ReactNode,
+ type ComponentProps,
+ type ReactElement,
+ type ReactNode,
} from "react";
export function InformationCircleIcon(
- props: ComponentProps<"svg">,
+ props: ComponentProps<"svg">,
): ReactElement {
- return (
-
- );
+ return (
+
+ );
}
const TypeToEmoji = {
- default: "💡",
- error: "🚫",
- info: ,
- warning: "⚠️",
+ default: "💡",
+ error: "🚫",
+ info: ,
+ warning: "⚠️",
};
type CalloutType = keyof typeof TypeToEmoji;
const classes: Record = {
- default: clsx(
- "border-orange-200 bg-orange-100 text-orange-800 dark:border-orange-400/30 dark:bg-orange-400/20 dark:text-orange-300",
- ),
- error: clsx(
- "border-red-200 bg-red-100 text-red-900 dark:border-red-200/30 dark:bg-red-900/30 dark:text-red-200",
- ),
- info: clsx(
- "border-blue-200 bg-blue-100 text-blue-900 dark:border-blue-200/30 dark:bg-blue-900/30 dark:text-blue-200",
- ),
- warning: clsx(
- "border-yellow-200 bg-yellow-100 text-yellow-900 dark:border-yellow-200/30 dark:bg-yellow-700/30 dark:text-yellow-200",
- ),
+ default: clsx(
+ "border-orange-200 bg-orange-100 text-orange-800 dark:border-orange-400/30 dark:bg-orange-400/20 dark:text-orange-300",
+ ),
+ error: clsx(
+ "border-red-200 bg-red-100 text-red-900 dark:border-red-200/30 dark:bg-red-900/30 dark:text-red-200",
+ ),
+ info: clsx(
+ "border-blue-200 bg-blue-100 text-blue-900 dark:border-blue-200/30 dark:bg-blue-900/30 dark:text-blue-200",
+ ),
+ warning: clsx(
+ "border-yellow-200 bg-yellow-100 text-yellow-900 dark:border-yellow-200/30 dark:bg-yellow-700/30 dark:text-yellow-200",
+ ),
};
interface CalloutProps {
- type?: CalloutType;
- emoji?: string | ReactElement;
- children: ReactNode;
+ type?: CalloutType;
+ emoji?: string | ReactElement;
+ children: ReactNode;
}
export function Callout(props: CalloutProps): ReactElement {
- const { children, type = "default", emoji = TypeToEmoji[type] } = props;
+ const { children, type = "default", emoji = TypeToEmoji[type] } = props;
- return (
-
-
- {emoji}
-
-
{children}
-
- );
+ return (
+
+
+ {emoji}
+
+
{children}
+
+ );
}
diff --git a/docs/src/components/mdx/code-block.tsx b/docs/src/components/mdx/code-block.tsx
index c8bf5a44..114d84d6 100644
--- a/docs/src/components/mdx/code-block.tsx
+++ b/docs/src/components/mdx/code-block.tsx
@@ -6,73 +6,71 @@ import { useRef, useState } from "react";
import { Icons } from "../icons";
export type CodeblockProps = React.DetailedHTMLProps<
- React.HTMLAttributes,
- HTMLPreElement
+ React.HTMLAttributes,
+ HTMLPreElement
> & {
- /** set by `rehype-pretty-code` */
- "data-language"?: string;
- /** set by `rehype-pretty-code` */
- "data-theme"?: string;
+ /** set by `rehype-pretty-code` */
+ "data-language"?: string;
+ /** set by `rehype-pretty-code` */
+ "data-theme"?: string;
};
export function Codeblock(props: CodeblockProps) {
- const { children, ...rest } = props;
- const language = props["data-language"] as string;
- const theme = props["data-theme"] as string;
- const Icon = {
- js: Icons.javascript,
- ts: Icons.typescript,
- vue: Icons.vue,
- bash: Icons.bash,
- }[language];
+ const { children, ...rest } = props;
+ const language = props["data-language"] as string;
+ const theme = props["data-theme"] as string;
+ const Icon = {
+ js: Icons.javascript,
+ ts: Icons.typescript,
+ vue: Icons.vue,
+ bash: Icons.bash,
+ }[language];
- const ref = useRef(null);
- const [copied, setCopied] = useState(false);
+ const ref = useRef(null);
+ const [copied, setCopied] = useState(false);
- return (
- <>
- {Icon && (
-
+ return (
+ <>
+ {Icon && (
+
+ )}
+
+
+ {children}
+
+ >
+ );
}
diff --git a/docs/src/components/mobile-nav.tsx b/docs/src/components/mobile-nav.tsx
index d75db071..56bf5ed9 100644
--- a/docs/src/components/mobile-nav.tsx
+++ b/docs/src/components/mobile-nav.tsx
@@ -16,80 +16,68 @@ import { NestedNavItem } from "./sidebar";
import { ThemeToggle } from "./theme-toggle";
export function MobileDropdown(props: {
- items: { main: NavItem[]; docs: NestedNavItem[] };
+ items: { main: NavItem[]; docs: NestedNavItem[] };
}) {
- const [isOpen, setIsOpen] = React.useState(false);
- const pathname = usePathname();
+ const [isOpen, setIsOpen] = React.useState(false);
+ const pathname = usePathname();
- React.useEffect(() => {
- if (isOpen) {
- document.body.classList.add("overflow-hidden");
- } else {
- document.body.classList.remove("overflow-hidden");
- }
- }, [isOpen]);
+ React.useEffect(() => {
+ if (isOpen) {
+ document.body.classList.add("overflow-hidden");
+ } else {
+ document.body.classList.remove("overflow-hidden");
+ }
+ }, [isOpen]);
- return (
-
-
-
-
-
-
- {props.items.docs.map((item) => (
-
-
{item.title}
- {item?.items?.length &&
- item.items.map((item) => (
-
- {item.href ? (
-
- {item.title}
- {item.label && (
-
- {item.label}
-
- )}
-
- ) : (
- item.title
- )}
-
- ))}
-
- ))}
-
-
-
-
-
-
- );
+ return (
+
+
+
+
+
+
+ {props.items.docs.map((item) => (
+
+
{item.title}
+ {item?.items?.length &&
+ item.items.map((item) => (
+
+ {item.href ? (
+
+ {item.title}
+ {item.label && (
+
+ {item.label}
+
+ )}
+
+ ) : (
+ item.title
+ )}
+
+ ))}
+
+ ))}
+
+
+
+
+
+
+ );
}
diff --git a/docs/src/components/sidebar.tsx b/docs/src/components/sidebar.tsx
index d8f5e3c7..d1359844 100644
--- a/docs/src/components/sidebar.tsx
+++ b/docs/src/components/sidebar.tsx
@@ -7,69 +7,66 @@ import { cn } from "@/lib/cn";
import { NavItem } from "./main-nav";
export interface NestedNavItem extends NavItem {
- items: NestedNavItem[];
+ items: NestedNavItem[];
}
export function DocsSidebarNav(props: { items: NestedNavItem[] }) {
- const pathname = usePathname();
+ const pathname = usePathname();
- return props.items.length ? (
-
- {props.items.map((item) => (
-
-
- {item.title}
-
- {item?.items?.length && (
-
- )}
-
- ))}
+ return props.items.length ? (
+
+ {props.items.map((item) => (
+
+
+ {item.title}
+
+ {item?.items?.length && (
+
+ )}
- ) : null;
+ ))}
+
+ ) : null;
}
export function DocsSidebarNavItems(props: {
- items: NestedNavItem[];
- pathname: string | null;
+ items: NestedNavItem[];
+ pathname: string | null;
}) {
- return props.items?.length ? (
-
- {props.items.map((item) =>
- item.href ? (
-
- {item.title}
- {item.label && (
-
- {item.label}
-
- )}
-
- ) : (
-
- {item.title}
-
- ),
+ return props.items?.length ? (
+
+ {props.items.map((item) =>
+ item.href ? (
+
- ) : null;
+ target={item.external ? "_blank" : ""}
+ rel={item.external ? "noreferrer" : ""}
+ >
+ {item.title}
+ {item.label && (
+
+ {item.label}
+
+ )}
+
+ ) : (
+
+ {item.title}
+
+ ),
+ )}
+
+ ) : null;
}
diff --git a/docs/src/components/site-header.tsx b/docs/src/components/site-header.tsx
index 88347929..1cb71447 100644
--- a/docs/src/components/site-header.tsx
+++ b/docs/src/components/site-header.tsx
@@ -8,35 +8,35 @@ import { ThemeToggle } from "@/components/theme-toggle";
import { buttonVariants } from "@/components/ui/button";
export function SiteHeader() {
- return (
-
+
+ );
}
diff --git a/docs/src/components/tailwind-indicator.tsx b/docs/src/components/tailwind-indicator.tsx
index ba0320ef..5644c1b0 100644
--- a/docs/src/components/tailwind-indicator.tsx
+++ b/docs/src/components/tailwind-indicator.tsx
@@ -1,18 +1,16 @@
export function TailwindIndicator() {
- if (process.env.NODE_ENV === "production") return null;
+ if (process.env.NODE_ENV === "production") return null;
- return (
-
-
xs
-
- sm
-
-
- md
-
-
lg
-
xl
-
2xl
-
- );
+ return (
+
+
xs
+
+ sm
+
+
md
+
lg
+
xl
+
2xl
+
+ );
}
diff --git a/docs/src/components/theme-provider.tsx b/docs/src/components/theme-provider.tsx
index 1e5373f1..93d93c0b 100644
--- a/docs/src/components/theme-provider.tsx
+++ b/docs/src/components/theme-provider.tsx
@@ -5,5 +5,5 @@ import { ThemeProviderProps } from "next-themes/dist/types";
import * as React from "react";
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
- return
{children};
+ return
{children};
}
diff --git a/docs/src/components/theme-toggle.tsx b/docs/src/components/theme-toggle.tsx
index 984edbd8..b85a19a3 100644
--- a/docs/src/components/theme-toggle.tsx
+++ b/docs/src/components/theme-toggle.tsx
@@ -7,17 +7,17 @@ import { Icons } from "@/components/icons";
import { Button } from "@/components/ui/button";
export function ThemeToggle() {
- const { setTheme, theme } = useTheme();
+ const { setTheme, theme } = useTheme();
- return (
-
- );
+ return (
+
+ );
}
diff --git a/docs/src/components/ui/button.tsx b/docs/src/components/ui/button.tsx
index c6c26c9e..1a4fdb6a 100644
--- a/docs/src/components/ui/button.tsx
+++ b/docs/src/components/ui/button.tsx
@@ -4,49 +4,48 @@ import * as React from "react";
import { cn } from "@/lib/cn";
const buttonVariants = cva(
- "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background",
- {
- variants: {
- variant: {
- default:
- "bg-primary text-primary-foreground hover:bg-primary/90",
- destructive:
- "bg-destructive text-destructive-foreground hover:bg-destructive/90",
- outline:
- "border border-input hover:bg-accent hover:text-accent-foreground",
- secondary:
- "bg-secondary text-secondary-foreground hover:bg-secondary/80",
- ghost: "hover:bg-accent hover:text-accent-foreground",
- link: "underline-offset-4 hover:underline text-primary",
- },
- size: {
- lg: "h-11 px-8 rounded-md",
- default: "h-10 py-2 px-4",
- sm: "h-9 px-3 rounded-md",
- icon: "h-9 w-9",
- },
- },
- defaultVariants: {
- variant: "default",
- size: "default",
- },
+ "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background",
+ {
+ variants: {
+ variant: {
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
+ destructive:
+ "bg-destructive text-destructive-foreground hover:bg-destructive/90",
+ outline:
+ "border border-input hover:bg-accent hover:text-accent-foreground",
+ secondary:
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80",
+ ghost: "hover:bg-accent hover:text-accent-foreground",
+ link: "underline-offset-4 hover:underline text-primary",
+ },
+ size: {
+ lg: "h-11 px-8 rounded-md",
+ default: "h-10 py-2 px-4",
+ sm: "h-9 px-3 rounded-md",
+ icon: "h-9 w-9",
+ },
},
+ defaultVariants: {
+ variant: "default",
+ size: "default",
+ },
+ },
);
export interface ButtonProps
- extends React.ButtonHTMLAttributes
,
- VariantProps {}
+ extends React.ButtonHTMLAttributes,
+ VariantProps {}
const Button = React.forwardRef(
- ({ className, variant, size, ...props }, ref) => {
- return (
-
- );
- },
+ ({ className, variant, size, ...props }, ref) => {
+ return (
+
+ );
+ },
);
Button.displayName = "Button";
diff --git a/docs/src/components/ui/popover.tsx b/docs/src/components/ui/popover.tsx
index 7d7137c6..3544c7a1 100644
--- a/docs/src/components/ui/popover.tsx
+++ b/docs/src/components/ui/popover.tsx
@@ -10,21 +10,21 @@ const PopoverTrigger = PopoverPrimitive.Trigger;
const PopoverClose = PopoverPrimitive.Close;
const PopoverContent = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
-
-
-
+
+
+
));
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
diff --git a/docs/src/components/ui/scroll-area.tsx b/docs/src/components/ui/scroll-area.tsx
index 43839fde..39abd225 100644
--- a/docs/src/components/ui/scroll-area.tsx
+++ b/docs/src/components/ui/scroll-area.tsx
@@ -6,44 +6,42 @@ import * as React from "react";
import { cn } from "@/lib/cn";
const ScrollArea = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
>(({ className, children, ...props }, ref) => (
-
-
- {children}
-
-
-
-
+
+
+ {children}
+
+
+
+
));
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
const ScrollBar = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef<
- typeof ScrollAreaPrimitive.ScrollAreaScrollbar
- >
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
>(({ className, orientation = "vertical", ...props }, ref) => (
-
-
-
+
+
+
));
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
diff --git a/docs/src/lib/cn.ts b/docs/src/lib/cn.ts
index e6447944..365058ce 100644
--- a/docs/src/lib/cn.ts
+++ b/docs/src/lib/cn.ts
@@ -2,5 +2,5 @@ import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
- return twMerge(clsx(inputs));
+ return twMerge(clsx(inputs));
}
diff --git a/docs/tailwind.config.ts b/docs/tailwind.config.ts
index 31395f5d..6fa7d39d 100644
--- a/docs/tailwind.config.ts
+++ b/docs/tailwind.config.ts
@@ -2,115 +2,111 @@ import type { Config } from "tailwindcss";
import { fontFamily } from "tailwindcss/defaultTheme";
export default {
- darkMode: ["class"],
- content: ["src/**/*.{ts,tsx,mdx}", "./mdx-components.tsx"],
- theme: {
- container: {
- center: true,
- padding: "2rem",
- screens: {
- "2xl": "1400px",
- },
+ darkMode: ["class"],
+ content: ["src/**/*.{ts,tsx,mdx}", "./mdx-components.tsx"],
+ theme: {
+ container: {
+ center: true,
+ padding: "2rem",
+ screens: {
+ "2xl": "1400px",
+ },
+ },
+ extend: {
+ borderColor: {
+ DEFAULT: "hsl(var(--border) / )",
+ },
+ colors: {
+ border: "hsl(var(--border) / )",
+ input: "hsl(var(--input) / )",
+ ring: "hsl(var(--ring) / )",
+ background: "hsl(var(--background) / )",
+ foreground: "hsl(var(--foreground) / )",
+ primary: {
+ DEFAULT: "hsl(var(--primary) / )",
+ foreground: "hsl(var(--primary-foreground) / )",
},
- extend: {
- borderColor: {
- DEFAULT: "hsl(var(--border) / )",
- },
- colors: {
- border: "hsl(var(--border) / )",
- input: "hsl(var(--input) / )",
- ring: "hsl(var(--ring) / )",
- background: "hsl(var(--background) / )",
- foreground: "hsl(var(--foreground) / )",
- primary: {
- DEFAULT: "hsl(var(--primary) / )",
- foreground:
- "hsl(var(--primary-foreground) / )",
- },
- secondary: {
- DEFAULT: "hsl(var(--secondary) / )",
- foreground:
- "hsl(var(--secondary-foreground) / )",
- },
- destructive: {
- DEFAULT: "hsl(var(--destructive) / )",
- foreground:
- "hsl(var(--destructive-foreground) / )",
- },
- muted: {
- DEFAULT: "hsl(var(--muted) / )",
- foreground: "hsl(var(--muted-foreground) / )",
- },
- accent: {
- DEFAULT: "hsl(var(--accent) / )",
- foreground: "hsl(var(--accent-foreground) / )",
- },
- popover: {
- DEFAULT: "hsl(var(--popover) / )",
- foreground:
- "hsl(var(--popover-foreground) / )",
- },
- card: {
- DEFAULT: "hsl(var(--card) / )",
- foreground: "hsl(var(--card-foreground) / )",
- },
- },
- borderRadius: {
- lg: "var(--radius)",
- md: "calc(var(--radius) - 2px)",
- sm: "calc(var(--radius) - 4px)",
- },
- fontFamily: {
- cal: ["var(--font-cal)", ...fontFamily.sans],
- sans: ["var(--font-sans)", ...fontFamily.sans],
- mono: ["var(--font-mono)", ...fontFamily.mono],
- },
- keyframes: {
- "fade-up": {
- "0%": {
- opacity: "0",
- transform: "translateY(10px)",
- },
- "80%": {
- opacity: "0.6",
- },
- "100%": {
- opacity: "1",
- transform: "translateY(0px)",
- },
- },
- "fade-down": {
- "0%": {
- opacity: "0",
- transform: "translateY(-10px)",
- },
- "80%": {
- opacity: "0.6",
- },
- "100%": {
- opacity: "1",
- transform: "translateY(0px)",
- },
- },
- "accordion-down": {
- from: { height: "0" },
- to: { height: "var(--radix-accordion-content-height)" },
- },
- "accordion-up": {
- from: { height: "var(--radix-accordion-content-height)" },
- to: { height: "0" },
- },
- },
- animation: {
- "fade-up": "fade-up 0.5s",
- "fade-down": "fade-down 0.5s",
- "accordion-down": "accordion-down 0.2s ease-out",
- "accordion-up": "accordion-up 0.2s ease-out",
- },
+ secondary: {
+ DEFAULT: "hsl(var(--secondary) / )",
+ foreground: "hsl(var(--secondary-foreground) / )",
},
+ destructive: {
+ DEFAULT: "hsl(var(--destructive) / )",
+ foreground: "hsl(var(--destructive-foreground) / )",
+ },
+ muted: {
+ DEFAULT: "hsl(var(--muted) / )",
+ foreground: "hsl(var(--muted-foreground) / )",
+ },
+ accent: {
+ DEFAULT: "hsl(var(--accent) / )",
+ foreground: "hsl(var(--accent-foreground) / )",
+ },
+ popover: {
+ DEFAULT: "hsl(var(--popover) / )",
+ foreground: "hsl(var(--popover-foreground) / )",
+ },
+ card: {
+ DEFAULT: "hsl(var(--card) / )",
+ foreground: "hsl(var(--card-foreground) / )",
+ },
+ },
+ borderRadius: {
+ lg: "var(--radius)",
+ md: "calc(var(--radius) - 2px)",
+ sm: "calc(var(--radius) - 4px)",
+ },
+ fontFamily: {
+ cal: ["var(--font-cal)", ...fontFamily.sans],
+ sans: ["var(--font-sans)", ...fontFamily.sans],
+ mono: ["var(--font-mono)", ...fontFamily.mono],
+ },
+ keyframes: {
+ "fade-up": {
+ "0%": {
+ opacity: "0",
+ transform: "translateY(10px)",
+ },
+ "80%": {
+ opacity: "0.6",
+ },
+ "100%": {
+ opacity: "1",
+ transform: "translateY(0px)",
+ },
+ },
+ "fade-down": {
+ "0%": {
+ opacity: "0",
+ transform: "translateY(-10px)",
+ },
+ "80%": {
+ opacity: "0.6",
+ },
+ "100%": {
+ opacity: "1",
+ transform: "translateY(0px)",
+ },
+ },
+ "accordion-down": {
+ from: { height: "0" },
+ to: { height: "var(--radix-accordion-content-height)" },
+ },
+ "accordion-up": {
+ from: { height: "var(--radix-accordion-content-height)" },
+ to: { height: "0" },
+ },
+ },
+ animation: {
+ "fade-up": "fade-up 0.5s",
+ "fade-down": "fade-down 0.5s",
+ "accordion-down": "accordion-down 0.2s ease-out",
+ "accordion-up": "accordion-up 0.2s ease-out",
+ },
},
- future: {
- hoverOnlyWhenSupported: true,
- },
- plugins: [require("tailwindcss-animate")],
+ },
+ future: {
+ hoverOnlyWhenSupported: true,
+ },
+ plugins: [require("tailwindcss-animate")],
} satisfies Config;
diff --git a/examples/astro/astro.config.mjs b/examples/astro/astro.config.mjs
index c11b2212..7486d953 100644
--- a/examples/astro/astro.config.mjs
+++ b/examples/astro/astro.config.mjs
@@ -4,5 +4,5 @@ import solidJs from "@astrojs/solid-js";
// https://astro.build/config
export default defineConfig({
- integrations: [solidJs()],
+ integrations: [solidJs()],
});
diff --git a/examples/astro/src/counter.tsx b/examples/astro/src/counter.tsx
index 986a54a9..049fdbe3 100644
--- a/examples/astro/src/counter.tsx
+++ b/examples/astro/src/counter.tsx
@@ -1,6 +1,6 @@
import { env } from "./t3-env";
export function ClientComponent() {
- // Try changing PUBLIC_API_URL to PORT - the component will throw
- return Client API Url:{env.PUBLIC_API_URL}
;
+ // Try changing PUBLIC_API_URL to PORT - the component will throw
+ return Client API Url:{env.PUBLIC_API_URL}
;
}
diff --git a/examples/astro/src/t3-env.ts b/examples/astro/src/t3-env.ts
index 5b7cf40f..868e3eee 100644
--- a/examples/astro/src/t3-env.ts
+++ b/examples/astro/src/t3-env.ts
@@ -2,16 +2,16 @@ import { createEnv } from "@t3-oss/env-core";
import { z } from "zod";
export const env = createEnv({
- server: {
- PORT: z.string(),
- },
- client: {
- PUBLIC_API_URL: z.string(),
- },
- // Astro bundles all environment variables so
- // we don't need to manually destructure them
- runtimeEnv: import.meta.env,
- // process is not available in Astro, so we must set this explicitly
- skipValidation: import.meta.env.SKIP_ENV_VALIDATION === "development",
- clientPrefix: "PUBLIC_",
+ server: {
+ PORT: z.string(),
+ },
+ client: {
+ PUBLIC_API_URL: z.string(),
+ },
+ // Astro bundles all environment variables so
+ // we don't need to manually destructure them
+ runtimeEnv: import.meta.env,
+ // process is not available in Astro, so we must set this explicitly
+ skipValidation: import.meta.env.SKIP_ENV_VALIDATION === "development",
+ clientPrefix: "PUBLIC_",
});
diff --git a/examples/nextjs/app/api/edge/route.ts b/examples/nextjs/app/api/edge/route.ts
index fc50b529..d0af53fd 100644
--- a/examples/nextjs/app/api/edge/route.ts
+++ b/examples/nextjs/app/api/edge/route.ts
@@ -4,5 +4,5 @@ import { env } from "~/env";
export const runtime = "edge";
export function GET() {
- return NextResponse.json({ env, processEnv: process.env });
+ return NextResponse.json({ env, processEnv: process.env });
}
diff --git a/examples/nextjs/app/api/node/route.ts b/examples/nextjs/app/api/node/route.ts
index 29e8f9a4..0d5e2e9d 100644
--- a/examples/nextjs/app/api/node/route.ts
+++ b/examples/nextjs/app/api/node/route.ts
@@ -2,5 +2,5 @@ import { NextResponse } from "next/server";
import { env } from "~/env";
export function GET(_request: Request) {
- return NextResponse.json({ env, processEnv: process.env });
+ return NextResponse.json({ env, processEnv: process.env });
}
diff --git a/examples/nextjs/app/edge/page.tsx b/examples/nextjs/app/edge/page.tsx
index a021a627..10384897 100644
--- a/examples/nextjs/app/edge/page.tsx
+++ b/examples/nextjs/app/edge/page.tsx
@@ -5,14 +5,14 @@ import { env } from "~/env";
export const runtime = "edge";
export default function Page() {
- return (
- <>
- Edge Runtime
- t3-env
- {JSON.stringify(env, null, 4)}
+ return (
+ <>
+ Edge Runtime
+ t3-env
+ {JSON.stringify(env, null, 4)}
- process.env
- {JSON.stringify(process.env, null, 4)}
- >
- );
+ process.env
+ {JSON.stringify(process.env, null, 4)}
+ >
+ );
}
diff --git a/examples/nextjs/app/env.js b/examples/nextjs/app/env.js
index 70d3f0ef..a4246980 100644
--- a/examples/nextjs/app/env.js
+++ b/examples/nextjs/app/env.js
@@ -3,18 +3,18 @@ import { vercel } from "@t3-oss/env-nextjs/presets";
import { z } from "zod";
export const env = createEnv({
- client: {
- NEXT_PUBLIC_GREETING: z.string(),
- },
- server: {
- SECRET: z.string(),
- },
- shared: {
- NODE_ENV: z.enum(["development", "production"]),
- },
- experimental__runtimeEnv: {
- NODE_ENV: process.env.NODE_ENV,
- NEXT_PUBLIC_GREETING: process.env.NEXT_PUBLIC_GREETING,
- },
- extends: [vercel],
+ client: {
+ NEXT_PUBLIC_GREETING: z.string(),
+ },
+ server: {
+ SECRET: z.string(),
+ },
+ shared: {
+ NODE_ENV: z.enum(["development", "production"]),
+ },
+ experimental__runtimeEnv: {
+ NODE_ENV: process.env.NODE_ENV,
+ NEXT_PUBLIC_GREETING: process.env.NEXT_PUBLIC_GREETING,
+ },
+ extends: [vercel],
});
diff --git a/examples/nextjs/app/layout.tsx b/examples/nextjs/app/layout.tsx
index 10880bbb..5ed4f58a 100644
--- a/examples/nextjs/app/layout.tsx
+++ b/examples/nextjs/app/layout.tsx
@@ -6,17 +6,17 @@ import "./globals.css";
const inter = Inter({ subsets: ["latin"] });
export const metadata = {
- title: "Create Next App",
- description: "Generated by create next app",
+ title: "Create Next App",
+ description: "Generated by create next app",
};
export default function RootLayout(props: { children: React.ReactNode }) {
- return (
-
-
- Server says {env.SECRET}!
- {props.children}
-
-
- );
+ return (
+
+
+ Server says {env.SECRET}!
+ {props.children}
+
+
+ );
}
diff --git a/examples/nextjs/app/node/page.tsx b/examples/nextjs/app/node/page.tsx
index 3b64bee6..e0d45d27 100644
--- a/examples/nextjs/app/node/page.tsx
+++ b/examples/nextjs/app/node/page.tsx
@@ -3,14 +3,14 @@
import { env } from "~/env";
export default function Page() {
- return (
- <>
- Node.js Runtime
- t3-env
- {JSON.stringify(env, null, 4)}
+ return (
+ <>
+ Node.js Runtime
+ t3-env
+ {JSON.stringify(env, null, 4)}
- process.env
- {JSON.stringify(process.env, null, 4)}
- >
- );
+ process.env
+ {JSON.stringify(process.env, null, 4)}
+ >
+ );
}
diff --git a/examples/nextjs/app/page.tsx b/examples/nextjs/app/page.tsx
index d4b4a8b0..728a1ebc 100644
--- a/examples/nextjs/app/page.tsx
+++ b/examples/nextjs/app/page.tsx
@@ -2,5 +2,5 @@
import { env } from "~/env";
export default function HomePage() {
- return Client says {env.NEXT_PUBLIC_GREETING}!
;
+ return Client says {env.NEXT_PUBLIC_GREETING}!
;
}
diff --git a/examples/nextjs/next.config.js b/examples/nextjs/next.config.js
index ae2f1d4f..267511ff 100644
--- a/examples/nextjs/next.config.js
+++ b/examples/nextjs/next.config.js
@@ -2,9 +2,9 @@ import "./app/env.js";
/** @type {import('next').NextConfig} */
const nextConfig = {
- eslint: {
- ignoreDuringBuilds: true,
- },
+ eslint: {
+ ignoreDuringBuilds: true,
+ },
};
export default nextConfig;
diff --git a/examples/nuxt/env.ts b/examples/nuxt/env.ts
index 7e463dff..ce3023f6 100644
--- a/examples/nuxt/env.ts
+++ b/examples/nuxt/env.ts
@@ -2,10 +2,10 @@ import { createEnv } from "@t3-oss/env-nuxt";
import { z } from "zod";
export const env = createEnv({
- server: {
- SECRET: z.string(),
- },
- client: {
- NUXT_PUBLIC_GREETING: z.string(),
- },
+ server: {
+ SECRET: z.string(),
+ },
+ client: {
+ NUXT_PUBLIC_GREETING: z.string(),
+ },
});
diff --git a/examples/nuxt/nuxt.config.ts b/examples/nuxt/nuxt.config.ts
index e898541f..0713f9ab 100644
--- a/examples/nuxt/nuxt.config.ts
+++ b/examples/nuxt/nuxt.config.ts
@@ -2,5 +2,5 @@ import "./env";
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
- // ...
+ // ...
});
diff --git a/examples/nuxt/server/api/hello.get.ts b/examples/nuxt/server/api/hello.get.ts
index a31a0def..df35b801 100644
--- a/examples/nuxt/server/api/hello.get.ts
+++ b/examples/nuxt/server/api/hello.get.ts
@@ -1,7 +1,7 @@
import { env } from "~~/env";
export default defineEventHandler(() => {
- return {
- secret: `Server says ${env.SECRET}`,
- };
+ return {
+ secret: `Server says ${env.SECRET}`,
+ };
});
diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts
index 964a7a9d..9da85d47 100644
--- a/packages/core/src/index.ts
+++ b/packages/core/src/index.ts
@@ -2,299 +2,297 @@ import { type ZodError, type ZodObject, type ZodType, z } from "zod";
export type ErrorMessage = T;
export type Simplify = {
- [P in keyof T]: T[P];
+ [P in keyof T]: T[P];
} & {};
// biome-ignore lint/suspicious/noExplicitAny:
type Impossible> = Partial<
- Record
+ Record
>;
type UnReadonlyObject = T extends Readonly ? U : T;
type Reduce<
- TArr extends Array>,
- TAcc = {},
+ TArr extends Array>,
+ TAcc = {},
> = TArr extends []
- ? TAcc
- : TArr extends [infer Head, ...infer Tail]
- ? Tail extends Array>
- ? Head & Reduce
- : never
- : never;
+ ? TAcc
+ : TArr extends [infer Head, ...infer Tail]
+ ? Tail extends Array>
+ ? Head & Reduce
+ : never
+ : never;
export interface BaseOptions<
- TShared extends Record,
- TExtends extends Array>,
+ TShared extends Record,
+ TExtends extends Array>,
> {
- /**
- * How to determine whether the app is running on the server or the client.
- * @default typeof window === "undefined"
- */
- isServer?: boolean;
+ /**
+ * How to determine whether the app is running on the server or the client.
+ * @default typeof window === "undefined"
+ */
+ isServer?: boolean;
- /**
- * Shared variables, often those that are provided by build tools and is available to both client and server,
- * but isn't prefixed and doesn't require to be manually supplied. For example `NODE_ENV`, `VERCEL_URL` etc.
- */
- shared?: TShared;
+ /**
+ * Shared variables, often those that are provided by build tools and is available to both client and server,
+ * but isn't prefixed and doesn't require to be manually supplied. For example `NODE_ENV`, `VERCEL_URL` etc.
+ */
+ shared?: TShared;
- /**
- * Extend presets
- */
- extends?: TExtends;
+ /**
+ * Extend presets
+ */
+ extends?: TExtends;
- /**
- * Called when validation fails. By default the error is logged,
- * and an error is thrown telling what environment variables are invalid.
- */
- onValidationError?: (error: ZodError) => never;
+ /**
+ * Called when validation fails. By default the error is logged,
+ * and an error is thrown telling what environment variables are invalid.
+ */
+ onValidationError?: (error: ZodError) => never;
- /**
- * Called when a server-side environment variable is accessed on the client.
- * By default an error is thrown.
- */
- onInvalidAccess?: (variable: string) => never;
+ /**
+ * Called when a server-side environment variable is accessed on the client.
+ * By default an error is thrown.
+ */
+ onInvalidAccess?: (variable: string) => never;
- /**
- * Whether to skip validation of environment variables.
- * @default false
- */
- skipValidation?: boolean;
+ /**
+ * Whether to skip validation of environment variables.
+ * @default false
+ */
+ skipValidation?: boolean;
- /**
- * By default, this library will feed the environment variables directly to
- * the Zod validator.
- *
- * This means that if you have an empty string for a value that is supposed
- * to be a number (e.g. `PORT=` in a ".env" file), Zod will incorrectly flag
- * it as a type mismatch violation. Additionally, if you have an empty string
- * for a value that is supposed to be a string with a default value (e.g.
- * `DOMAIN=` in an ".env" file), the default value will never be applied.
- *
- * In order to solve these issues, we recommend that all new projects
- * explicitly specify this option as true.
- */
- emptyStringAsUndefined?: boolean;
+ /**
+ * By default, this library will feed the environment variables directly to
+ * the Zod validator.
+ *
+ * This means that if you have an empty string for a value that is supposed
+ * to be a number (e.g. `PORT=` in a ".env" file), Zod will incorrectly flag
+ * it as a type mismatch violation. Additionally, if you have an empty string
+ * for a value that is supposed to be a string with a default value (e.g.
+ * `DOMAIN=` in an ".env" file), the default value will never be applied.
+ *
+ * In order to solve these issues, we recommend that all new projects
+ * explicitly specify this option as true.
+ */
+ emptyStringAsUndefined?: boolean;
}
export interface LooseOptions<
- TShared extends Record,
- TExtends extends Array>,
+ TShared extends Record,
+ TExtends extends Array>,
> extends BaseOptions {
- runtimeEnvStrict?: never;
+ runtimeEnvStrict?: never;
- /**
- * What object holds the environment variables at runtime. This is usually
- * `process.env` or `import.meta.env`.
- */
- // Unlike `runtimeEnvStrict`, this doesn't enforce that all environment variables are set.
- runtimeEnv: Record;
+ /**
+ * What object holds the environment variables at runtime. This is usually
+ * `process.env` or `import.meta.env`.
+ */
+ // Unlike `runtimeEnvStrict`, this doesn't enforce that all environment variables are set.
+ runtimeEnv: Record;
}
export interface StrictOptions<
- TPrefix extends string | undefined,
- TServer extends Record,
- TClient extends Record,
- TShared extends Record,
- TExtends extends Array>,
+ TPrefix extends string | undefined,
+ TServer extends Record,
+ TClient extends Record,
+ TShared extends Record,
+ TExtends extends Array>,
> extends BaseOptions {
- /**
- * Runtime Environment variables to use for validation - `process.env`, `import.meta.env` or similar.
- * Enforces all environment variables to be set. Required in for example Next.js Edge and Client runtimes.
- */
- runtimeEnvStrict: Record<
- | {
- [TKey in keyof TClient]: TPrefix extends undefined
- ? never
- : TKey extends `${TPrefix}${string}`
- ? TKey
- : never;
- }[keyof TClient]
- | {
- [TKey in keyof TServer]: TPrefix extends undefined
- ? TKey
- : TKey extends `${TPrefix}${string}`
- ? never
- : TKey;
- }[keyof TServer]
- | {
- [TKey in keyof TShared]: TKey extends string ? TKey : never;
- }[keyof TShared],
- string | boolean | number | undefined
- >;
- runtimeEnv?: never;
+ /**
+ * Runtime Environment variables to use for validation - `process.env`, `import.meta.env` or similar.
+ * Enforces all environment variables to be set. Required in for example Next.js Edge and Client runtimes.
+ */
+ runtimeEnvStrict: Record<
+ | {
+ [TKey in keyof TClient]: TPrefix extends undefined
+ ? never
+ : TKey extends `${TPrefix}${string}`
+ ? TKey
+ : never;
+ }[keyof TClient]
+ | {
+ [TKey in keyof TServer]: TPrefix extends undefined
+ ? TKey
+ : TKey extends `${TPrefix}${string}`
+ ? never
+ : TKey;
+ }[keyof TServer]
+ | {
+ [TKey in keyof TShared]: TKey extends string ? TKey : never;
+ }[keyof TShared],
+ string | boolean | number | undefined
+ >;
+ runtimeEnv?: never;
}
export interface ClientOptions<
- TPrefix extends string | undefined,
- TClient extends Record,
+ TPrefix extends string | undefined,
+ TClient extends Record,
> {
- /**
- * The prefix that client-side variables must have. This is enforced both at
- * a type-level and at runtime.
- */
- clientPrefix: TPrefix;
+ /**
+ * The prefix that client-side variables must have. This is enforced both at
+ * a type-level and at runtime.
+ */
+ clientPrefix: TPrefix;
- /**
- * Specify your client-side environment variables schema here. This way you can ensure the app isn't
- * built with invalid env vars.
- */
- client: Partial<{
- [TKey in keyof TClient]: TKey extends `${TPrefix}${string}`
- ? TClient[TKey]
- : ErrorMessage<`${TKey extends string
- ? TKey
- : never} is not prefixed with ${TPrefix}.`>;
- }>;
+ /**
+ * Specify your client-side environment variables schema here. This way you can ensure the app isn't
+ * built with invalid env vars.
+ */
+ client: Partial<{
+ [TKey in keyof TClient]: TKey extends `${TPrefix}${string}`
+ ? TClient[TKey]
+ : ErrorMessage<`${TKey extends string
+ ? TKey
+ : never} is not prefixed with ${TPrefix}.`>;
+ }>;
}
export interface ServerOptions<
- TPrefix extends string | undefined,
- TServer extends Record,
+ TPrefix extends string | undefined,
+ TServer extends Record,
> {
- /**
- * Specify your server-side environment variables schema here. This way you can ensure the app isn't
- * built with invalid env vars.
- */
- server: Partial<{
- [TKey in keyof TServer]: TPrefix extends undefined
- ? TServer[TKey]
- : TPrefix extends ""
- ? TServer[TKey]
- : TKey extends `${TPrefix}${string}`
- ? ErrorMessage<`${TKey extends `${TPrefix}${string}`
- ? TKey
- : never} should not prefixed with ${TPrefix}.`>
- : TServer[TKey];
- }>;
+ /**
+ * Specify your server-side environment variables schema here. This way you can ensure the app isn't
+ * built with invalid env vars.
+ */
+ server: Partial<{
+ [TKey in keyof TServer]: TPrefix extends undefined
+ ? TServer[TKey]
+ : TPrefix extends ""
+ ? TServer[TKey]
+ : TKey extends `${TPrefix}${string}`
+ ? ErrorMessage<`${TKey extends `${TPrefix}${string}`
+ ? TKey
+ : never} should not prefixed with ${TPrefix}.`>
+ : TServer[TKey];
+ }>;
}
export type ServerClientOptions<
- TPrefix extends string | undefined,
- TServer extends Record,
- TClient extends Record,
+ TPrefix extends string | undefined,
+ TServer extends Record,
+ TClient extends Record,
> =
- | (ClientOptions & ServerOptions)
- | (ServerOptions &
- Impossible>)
- | (ClientOptions &
- Impossible>);
+ | (ClientOptions & ServerOptions)
+ | (ServerOptions & Impossible>)
+ | (ClientOptions & Impossible>);
export type EnvOptions<
- TPrefix extends string | undefined,
- TServer extends Record,
- TClient extends Record,
- TShared extends Record,
- TExtends extends Array>,
+ TPrefix extends string | undefined,
+ TServer extends Record,
+ TClient extends Record,
+ TShared extends Record,
+ TExtends extends Array>,
> =
- | (LooseOptions &
- ServerClientOptions)
- | (StrictOptions &
- ServerClientOptions);
+ | (LooseOptions &
+ ServerClientOptions)
+ | (StrictOptions &
+ ServerClientOptions);
export function createEnv<
- TPrefix extends string | undefined,
- TServer extends Record = NonNullable,
- TClient extends Record = NonNullable,
- TShared extends Record = NonNullable,
- const TExtends extends Array> = [],
+ TPrefix extends string | undefined,
+ TServer extends Record = NonNullable,
+ TClient extends Record = NonNullable,
+ TShared extends Record = NonNullable,
+ const TExtends extends Array> = [],
>(
- opts: EnvOptions,
+ opts: EnvOptions,
): Readonly<
- Simplify<
- z.infer> &
- z.infer> &
- z.infer> &
- UnReadonlyObject>
- >
+ Simplify<
+ z.infer> &
+ z.infer> &
+ z.infer> &
+ UnReadonlyObject>
+ >
> {
- const runtimeEnv = opts.runtimeEnvStrict ?? opts.runtimeEnv ?? process.env;
+ const runtimeEnv = opts.runtimeEnvStrict ?? opts.runtimeEnv ?? process.env;
- const emptyStringAsUndefined = opts.emptyStringAsUndefined ?? false;
- if (emptyStringAsUndefined) {
- for (const [key, value] of Object.entries(runtimeEnv)) {
- if (value === "") {
- delete runtimeEnv[key];
- }
- }
+ const emptyStringAsUndefined = opts.emptyStringAsUndefined ?? false;
+ if (emptyStringAsUndefined) {
+ for (const [key, value] of Object.entries(runtimeEnv)) {
+ if (value === "") {
+ delete runtimeEnv[key];
+ }
}
+ }
- const skip = !!opts.skipValidation;
- // biome-ignore lint/suspicious/noExplicitAny:
- if (skip) return runtimeEnv as any;
+ const skip = !!opts.skipValidation;
+ // biome-ignore lint/suspicious/noExplicitAny:
+ if (skip) return runtimeEnv as any;
- const _client = typeof opts.client === "object" ? opts.client : {};
- const _server = typeof opts.server === "object" ? opts.server : {};
- const _shared = typeof opts.shared === "object" ? opts.shared : {};
- const client = z.object(_client);
- const server = z.object(_server);
- const shared = z.object(_shared);
- const isServer = opts.isServer ?? typeof window === "undefined";
+ const _client = typeof opts.client === "object" ? opts.client : {};
+ const _server = typeof opts.server === "object" ? opts.server : {};
+ const _shared = typeof opts.shared === "object" ? opts.shared : {};
+ const client = z.object(_client);
+ const server = z.object(_server);
+ const shared = z.object(_shared);
+ const isServer = opts.isServer ?? typeof window === "undefined";
- const allClient = client.merge(shared);
- const allServer = server.merge(shared).merge(client);
- const parsed = isServer
- ? allServer.safeParse(runtimeEnv) // on server we can validate all env vars
- : allClient.safeParse(runtimeEnv); // on client we can only validate the ones that are exposed
+ const allClient = client.merge(shared);
+ const allServer = server.merge(shared).merge(client);
+ const parsed = isServer
+ ? allServer.safeParse(runtimeEnv) // on server we can validate all env vars
+ : allClient.safeParse(runtimeEnv); // on client we can only validate the ones that are exposed
- const onValidationError =
- opts.onValidationError ??
- ((error: ZodError) => {
- console.error(
- "❌ Invalid environment variables:",
- error.flatten().fieldErrors,
- );
- throw new Error("Invalid environment variables");
- });
+ const onValidationError =
+ opts.onValidationError ??
+ ((error: ZodError) => {
+ console.error(
+ "❌ Invalid environment variables:",
+ error.flatten().fieldErrors,
+ );
+ throw new Error("Invalid environment variables");
+ });
- const onInvalidAccess =
- opts.onInvalidAccess ??
- ((_variable: string) => {
- throw new Error(
- "❌ Attempted to access a server-side environment variable on the client",
- );
- });
+ const onInvalidAccess =
+ opts.onInvalidAccess ??
+ ((_variable: string) => {
+ throw new Error(
+ "❌ Attempted to access a server-side environment variable on the client",
+ );
+ });
- if (parsed.success === false) {
- return onValidationError(parsed.error);
- }
+ if (parsed.success === false) {
+ return onValidationError(parsed.error);
+ }
- const extendedObj = (opts.extends ?? []).reduce((acc, curr) => {
- return Object.assign(acc, curr);
- }, {});
- const fullObj = Object.assign({}, parsed.data, extendedObj);
+ const extendedObj = (opts.extends ?? []).reduce((acc, curr) => {
+ return Object.assign(acc, curr);
+ }, {});
+ const fullObj = Object.assign({}, parsed.data, extendedObj);
- const env = new Proxy(fullObj, {
- get(target, prop) {
- if (
- typeof prop !== "string" ||
- prop === "__esModule" ||
- prop === "$$typeof"
- )
- return undefined;
- if (
- !isServer &&
- opts.clientPrefix &&
- !prop.startsWith(opts.clientPrefix) &&
- shared.shape[prop as keyof typeof shared.shape] === undefined
- ) {
- return onInvalidAccess(prop);
- }
- return target[prop];
- },
- // Maybe reconsider this in the future:
- // https://github.com/t3-oss/t3-env/pull/111#issuecomment-1682931526
- // set(_target, prop) {
- // // Readonly - this is the error message you get from assigning to a frozen object
- // throw new Error(
- // typeof prop === "string"
- // ? `Cannot assign to read only property ${prop} of object #