Switched to t3-env to manage environment vars
This commit is contained in:
parent
e0f638ef93
commit
17854b4ad4
3 changed files with 54 additions and 102 deletions
|
@ -18,6 +18,7 @@
|
|||
"@neondatabase/serverless": "^0.6.0",
|
||||
"@paralleldrive/cuid2": "^2.2.2",
|
||||
"@react-email/components": "^0.0.7",
|
||||
"@t3-oss/env-nextjs": "^0.6.1",
|
||||
"@tanstack/react-query": "^4.33.0",
|
||||
"@trpc/client": "10.38.1",
|
||||
"@trpc/next": "10.38.1",
|
||||
|
|
31
pnpm-lock.yaml
generated
31
pnpm-lock.yaml
generated
|
@ -20,6 +20,9 @@ dependencies:
|
|||
'@react-email/components':
|
||||
specifier: ^0.0.7
|
||||
version: 0.0.7
|
||||
'@t3-oss/env-nextjs':
|
||||
specifier: ^0.6.1
|
||||
version: 0.6.1(typescript@5.2.2)(zod@3.22.2)
|
||||
'@tanstack/react-query':
|
||||
specifier: ^4.33.0
|
||||
version: 4.33.0(react-dom@18.2.0)(react@18.2.0)
|
||||
|
@ -1293,6 +1296,27 @@ packages:
|
|||
defer-to-connect: 2.0.1
|
||||
dev: false
|
||||
|
||||
/@t3-oss/env-core@0.6.1(typescript@5.2.2)(zod@3.22.2):
|
||||
resolution: {integrity: sha512-KQD7qEDJtkWIWWmTVjNvk0wnHpkvAQ6CRbUxbWMFNG/fiosBQDQvtRpBNu6USxBscJCoC4z6y7P9MN52/mLOzw==}
|
||||
peerDependencies:
|
||||
typescript: '>=4.7.2'
|
||||
zod: ^3.0.0
|
||||
dependencies:
|
||||
typescript: 5.2.2
|
||||
zod: 3.22.2
|
||||
dev: false
|
||||
|
||||
/@t3-oss/env-nextjs@0.6.1(typescript@5.2.2)(zod@3.22.2):
|
||||
resolution: {integrity: sha512-z1dIC++Vxj9kmzX5nSPfcrCSkszy3dTEPC4Ssx7Ap5AqR3c2Qa7S0xf8axn6coy7D/vCXDAAnHYnCMDhtcY3SQ==}
|
||||
peerDependencies:
|
||||
typescript: '>=4.7.2'
|
||||
zod: ^3.0.0
|
||||
dependencies:
|
||||
'@t3-oss/env-core': 0.6.1(typescript@5.2.2)(zod@3.22.2)
|
||||
typescript: 5.2.2
|
||||
zod: 3.22.2
|
||||
dev: false
|
||||
|
||||
/@tanstack/query-core@4.33.0:
|
||||
resolution: {integrity: sha512-qYu73ptvnzRh6se2nyBIDHGBQvPY1XXl3yR769B7B6mIDD7s+EZhdlWHQ67JI6UOTFRaI7wupnTnwJ3gE0Mr/g==}
|
||||
dev: false
|
||||
|
@ -1919,7 +1943,7 @@ packages:
|
|||
dependencies:
|
||||
browserslist: 4.21.10
|
||||
caniuse-lite: 1.0.30001525
|
||||
fraction.js: 4.3.2
|
||||
fraction.js: 4.3.4
|
||||
normalize-range: 0.1.2
|
||||
picocolors: 1.0.0
|
||||
postcss: 8.4.29
|
||||
|
@ -3328,8 +3352,8 @@ packages:
|
|||
mime-types: 2.1.35
|
||||
dev: false
|
||||
|
||||
/fraction.js@4.3.2:
|
||||
resolution: {integrity: sha512-9VLF466MqX1OUP7/d9r7/Vsvu6Hpp+taXBLmiR5x6mEYfT0BDkGVBt5TyA1aDu1WzIE1sF8F66evOFaz7iAEGQ==}
|
||||
/fraction.js@4.3.4:
|
||||
resolution: {integrity: sha512-pwiTgt0Q7t+GHZA4yaLjObx4vXmmdcS0iSJ19o8d/goUGgItX9UZWKWNnLHehxviD8wU2IWRsnR8cD5+yOJP2Q==}
|
||||
dev: false
|
||||
|
||||
/fs-constants@1.0.0:
|
||||
|
@ -5863,7 +5887,6 @@ packages:
|
|||
resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==}
|
||||
engines: {node: '>=14.17'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/unbox-primitive@1.0.2:
|
||||
resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
|
||||
|
|
86
src/env.mjs
86
src/env.mjs
|
@ -1,10 +1,8 @@
|
|||
import { createEnv } from "@t3-oss/env-nextjs";
|
||||
import { z } from "zod";
|
||||
|
||||
/**
|
||||
* Specify your server-side environment variables schema here. This way you can ensure the app isn't
|
||||
* built with invalid env vars.
|
||||
*/
|
||||
const server = z.object({
|
||||
export const env = createEnv({
|
||||
server: {
|
||||
DATABASE_URL: z.string().url(),
|
||||
UPSTASH_REDIS_REST_URL: z.string().url(),
|
||||
UPSTASH_REDIS_REST_TOKEN: z.string(),
|
||||
|
@ -14,88 +12,18 @@ const server = z.object({
|
|||
NODE_ENV: z.enum(["development", "test", "production"]),
|
||||
ABLY_PRIVATE_KEY: z.string(),
|
||||
APP_ENV: z.string(),
|
||||
RESEND_API_KEY: z.string(),
|
||||
UNKEY_ROOT_KEY: z.string(),
|
||||
CLERK_SECRET_KEY: z.string(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Specify your client-side environment variables schema here. This way you can ensure the app isn't
|
||||
* built with invalid env vars. To expose them to the client, prefix them with `NEXT_PUBLIC_`.
|
||||
*/
|
||||
const client = z.object({
|
||||
},
|
||||
client: {
|
||||
NEXT_PUBLIC_ABLY_PUBLIC_KEY: z.string(),
|
||||
NEXT_PUBLIC_APP_ENV: z.string(),
|
||||
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: z.string(),
|
||||
});
|
||||
|
||||
/**
|
||||
* You can't destruct `process.env` as a regular object in the Next.js edge runtimes (e.g.
|
||||
* middlewares) or client-side so we need to destruct manually.
|
||||
*
|
||||
* @type {Record<keyof z.infer<typeof server> | keyof z.infer<typeof client>, string | undefined>}
|
||||
*/
|
||||
const processEnv = {
|
||||
DATABASE_URL: process.env.DATABASE_URL,
|
||||
UPSTASH_REDIS_REST_URL: process.env.UPSTASH_REDIS_REST_URL,
|
||||
UPSTASH_REDIS_REST_TOKEN: process.env.UPSTASH_REDIS_REST_TOKEN,
|
||||
UPSTASH_REDIS_EXPIRY_SECONDS: process.env.UPSTASH_REDIS_EXPIRY_SECONDS,
|
||||
UPSTASH_RATELIMIT_REQUESTS: process.env.UPSTASH_RATELIMIT_REQUESTS,
|
||||
UPSTASH_RATELIMIT_SECONDS: process.env.UPSTASH_RATELIMIT_SECONDS,
|
||||
NODE_ENV: process.env.NODE_ENV,
|
||||
ABLY_PRIVATE_KEY: process.env.ABLY_PRIVATE_KEY,
|
||||
},
|
||||
experimental__runtimeEnv: {
|
||||
NEXT_PUBLIC_ABLY_PUBLIC_KEY: process.env.NEXT_PUBLIC_ABLY_PUBLIC_KEY,
|
||||
APP_ENV: process.env.APP_ENV,
|
||||
NEXT_PUBLIC_APP_ENV: process.env.NEXT_PUBLIC_APP_ENV,
|
||||
RESEND_API_KEY: process.env.RESEND_API_KEY,
|
||||
UNKEY_ROOT_KEY: process.env.UNKEY_ROOT_KEY,
|
||||
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY:
|
||||
process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY,
|
||||
CLERK_SECRET_KEY: process.env.CLERK_SECRET_KEY,
|
||||
};
|
||||
|
||||
// Don't touch the part below
|
||||
// --------------------------
|
||||
|
||||
const merged = server.merge(client);
|
||||
|
||||
/** @typedef {z.input<typeof merged>} MergedInput */
|
||||
/** @typedef {z.infer<typeof merged>} MergedOutput */
|
||||
/** @typedef {z.SafeParseReturnType<MergedInput, MergedOutput>} MergedSafeParseReturn */
|
||||
|
||||
let env = /** @type {MergedOutput} */ (process.env);
|
||||
|
||||
if (!!process.env.SKIP_ENV_VALIDATION == false) {
|
||||
const isServer = typeof window === "undefined";
|
||||
|
||||
const parsed = /** @type {MergedSafeParseReturn} */ (
|
||||
isServer
|
||||
? merged.safeParse(processEnv) // on server we can validate all env vars
|
||||
: client.safeParse(processEnv) // on client we can only validate the ones that are exposed
|
||||
);
|
||||
|
||||
if (parsed.success === false) {
|
||||
console.error(
|
||||
"❌ Invalid environment variables:",
|
||||
parsed.error.flatten().fieldErrors
|
||||
);
|
||||
throw new Error("Invalid environment variables");
|
||||
}
|
||||
|
||||
env = new Proxy(parsed.data, {
|
||||
get(target, prop) {
|
||||
if (typeof prop !== "string") return undefined;
|
||||
// Throw a descriptive error if a server-side env var is accessed on the client
|
||||
// Otherwise it would just be returning `undefined` and be annoying to debug
|
||||
if (!isServer && !prop.startsWith("NEXT_PUBLIC_"))
|
||||
throw new Error(
|
||||
process.env.NODE_ENV === "production"
|
||||
? "❌ Attempted to access a server-side environment variable on the client"
|
||||
: `❌ Attempted to access server-side environment variable '${prop}' on the client`
|
||||
);
|
||||
return target[/** @type {keyof typeof target} */ (prop)];
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export { env };
|
||||
|
|
Loading…
Add table
Reference in a new issue