Skip to content

Commit 23905d2

Browse files
made env variables typesafe
1 parent c1db85b commit 23905d2

File tree

5 files changed

+36
-16
lines changed

5 files changed

+36
-16
lines changed

src/client.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@ import { StrictMode } from "react";
33
import { hydrateRoot } from "react-dom/client";
44
import * as Sentry from "@sentry/tanstackstart-react";
55
import { createRouter } from "./router";
6-
6+
import { env } from "./config/env";
77

88
const router = createRouter();
99

1010
Sentry.init({
11-
dsn: import.meta.env.VITE_SENTRY_DSN,
11+
dsn: env.VITE_SENTRY_DSN,
1212
sendDefaultPii: true,
1313
});
1414

1515
hydrateRoot(
1616
document,
1717
<StrictMode>
1818
<StartClient router={router} />
19-
</StrictMode>
19+
</StrictMode>,
2020
);

src/config/env.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { createIsomorphicFn } from "@tanstack/react-start";
2+
import { z } from "zod";
3+
4+
const clientEnvSchema = z.object({
5+
VITE_SENTRY_DSN: z.string().optional(),
6+
VITE_ANALYTICS_SCRIPT: z.url().optional(),
7+
VITE_ANALYTICS_WEBSITE_ID: z.uuid().optional(),
8+
});
9+
10+
const serverEnvSchema = z
11+
.object({ DATABASE_URL: z.url() })
12+
.and(clientEnvSchema);
13+
14+
const getEnv = createIsomorphicFn()
15+
.server(() => serverEnvSchema.parse(process.env))
16+
.client(() => clientEnvSchema.parse(import.meta.env));
17+
18+
type Env = z.infer<typeof serverEnvSchema>;
19+
20+
export const env = getEnv() as Env;

src/lib/db/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { drizzle } from "drizzle-orm/libsql";
22
import { EnhancedQueryLogger } from "drizzle-query-logger";
3+
import { env } from "~/config/env";
34

4-
const dbUrl = process.env.DATABASE_URL!;
5-
export const db = drizzle(dbUrl, {
5+
export const db = drizzle(env.DATABASE_URL, {
66
casing: "snake_case",
77
logger: new EnhancedQueryLogger(),
88
});

src/routes/__root.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@ import { ThemeToggle } from "~/components/theme-toggle";
1515
import { Footer } from "~/components/footer";
1616
import { themeQuery } from "~/lib/queries";
1717
import { ScrollArea } from "~/components/ui/scroll-area";
18+
import { env } from "~/config/env";
1819

1920
export const Route = wrapCreateRootRouteWithSentry(
2021
createRootRouteWithContext<{
2122
queryClient: QueryClient;
22-
}>()
23+
}>(),
2324
)({
2425
head: () => ({
2526
meta: [
@@ -86,14 +87,13 @@ function RootDocument({ children }: Readonly<{ children: React.ReactNode }>) {
8687
<html className={theme} suppressHydrationWarning>
8788
<head>
8889
<HeadContent />
89-
{import.meta.env.VITE_ANALYTICS_SCRIPT &&
90-
import.meta.env.VITE_ANALYTICS_WEBSITE_ID && (
91-
<script
92-
defer
93-
src={import.meta.env.VITE_ANALYTICS_SCRIPT}
94-
data-website-id={import.meta.env.VITE_ANALYTICS_WEBSITE_ID}
95-
></script>
96-
)}
90+
{env.VITE_ANALYTICS_SCRIPT && env.VITE_ANALYTICS_WEBSITE_ID && (
91+
<script
92+
defer
93+
src={env.VITE_ANALYTICS_SCRIPT}
94+
data-website-id={env.VITE_ANALYTICS_WEBSITE_ID}
95+
></script>
96+
)}
9797
</head>
9898
<body className="min-h-screen">
9999
<ScrollArea className="h-screen overflow-y-auto">

src/server.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import {
44
} from "@tanstack/react-start/server";
55
import * as Sentry from "@sentry/tanstackstart-react";
66
import { createRouter } from "./router";
7-
7+
import { env } from "./config/env";
88

99
Sentry.init({
10-
dsn: process.env.VITE_SENTRY_DSN,
10+
dsn: env.VITE_SENTRY_DSN,
1111
sendDefaultPii: true,
1212
});
1313

0 commit comments

Comments
 (0)