mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-07-08 03:54:58 +10:00
95 lines
3.5 KiB
TypeScript
95 lines
3.5 KiB
TypeScript
import { isAbsolute, join } from "node:path";
|
|
import { createEnv } from "@t3-oss/env-core";
|
|
import { z } from "zod";
|
|
import { findWorkspaceRoot } from "@reactive-resume/utils/monorepo.node";
|
|
|
|
const workspaceRoot = findWorkspaceRoot();
|
|
|
|
if (workspaceRoot) {
|
|
try {
|
|
// Native stand-in for dotenv: existing process.env still wins over file values.
|
|
process.loadEnvFile(join(workspaceRoot, ".env"));
|
|
} catch (error) {
|
|
// A missing .env is expected (e.g. production with injected env); anything else is a real problem.
|
|
if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) throw error;
|
|
}
|
|
}
|
|
|
|
export const env = createEnv({
|
|
server: {
|
|
// Application
|
|
APP_URL: z.url({ protocol: /https?/ }),
|
|
SERVER_PORT: z.coerce.number().int().min(1).max(65535).default(3001),
|
|
|
|
// Database
|
|
DATABASE_URL: z.url({ protocol: /postgres(ql)?/ }),
|
|
|
|
// Authentication
|
|
AUTH_SECRET: z.string().min(1),
|
|
BETTER_AUTH_API_KEY: z.string().min(1).optional(),
|
|
|
|
// Social Auth (Google)
|
|
GOOGLE_CLIENT_ID: z.string().min(1).optional(),
|
|
GOOGLE_CLIENT_SECRET: z.string().min(1).optional(),
|
|
|
|
// Social Auth (GitHub)
|
|
GITHUB_CLIENT_ID: z.string().min(1).optional(),
|
|
GITHUB_CLIENT_SECRET: z.string().min(1).optional(),
|
|
|
|
// Social Auth (LinkedIn)
|
|
LINKEDIN_CLIENT_ID: z.string().min(1).optional(),
|
|
LINKEDIN_CLIENT_SECRET: z.string().min(1).optional(),
|
|
|
|
// Custom OAuth Provider
|
|
OAUTH_PROVIDER_NAME: z.string().min(1).optional(),
|
|
OAUTH_CLIENT_ID: z.string().min(1).optional(),
|
|
OAUTH_CLIENT_SECRET: z.string().min(1).optional(),
|
|
OAUTH_DISCOVERY_URL: z.url({ protocol: /https?/ }).optional(),
|
|
OAUTH_AUTHORIZATION_URL: z.url({ protocol: /https?/ }).optional(),
|
|
OAUTH_TOKEN_URL: z.url({ protocol: /https?/ }).optional(),
|
|
OAUTH_USER_INFO_URL: z.url({ protocol: /https?/ }).optional(),
|
|
OAUTH_SCOPES: z
|
|
.string()
|
|
.min(1)
|
|
.transform((value) => value.split(" "))
|
|
.default(["openid", "profile", "email"]),
|
|
|
|
// Email (SMTP)
|
|
SMTP_HOST: z.string().min(1).optional(),
|
|
SMTP_PORT: z.coerce.number().int().min(1).max(65535).default(587),
|
|
SMTP_USER: z.string().min(1).optional(),
|
|
SMTP_PASS: z.string().min(1).optional(),
|
|
SMTP_FROM: z.string().min(1).optional(),
|
|
SMTP_SECURE: z.stringbool().default(false),
|
|
|
|
// Storage (Optional)
|
|
LOCAL_STORAGE_PATH: z.string().min(1).refine(isAbsolute, "LOCAL_STORAGE_PATH must be an absolute path").optional(),
|
|
S3_ACCESS_KEY_ID: z.string().min(1).optional(),
|
|
S3_SECRET_ACCESS_KEY: z.string().min(1).optional(),
|
|
S3_REGION: z.string().default("us-east-1"),
|
|
S3_ENDPOINT: z.url({ protocol: /https?/ }).optional(),
|
|
S3_BUCKET: z.string().min(1).optional(),
|
|
S3_FORCE_PATH_STYLE: z.stringbool().default(false),
|
|
|
|
// AI Agent Workspace (optional until the agent feature is used)
|
|
REDIS_URL: z.url({ protocol: /redis(s)?/ }).optional(),
|
|
ENCRYPTION_SECRET: z.string().min(32, "ENCRYPTION_SECRET must be at least 32 characters").optional(),
|
|
|
|
// Feature Flags
|
|
FLAG_DISABLE_SIGNUPS: z.stringbool().default(false),
|
|
FLAG_DISABLE_EMAIL_AUTH: z.stringbool().default(false),
|
|
FLAG_DISABLE_IMAGE_PROCESSING: z.stringbool().default(false),
|
|
FLAG_DISABLE_API_RATE_LIMIT: z.stringbool().default(false),
|
|
FLAG_SHOW_SPONSORS: z.stringbool().default(false),
|
|
FLAG_ALLOW_UNSAFE_AI_BASE_URL: z.stringbool().default(false),
|
|
FLAG_ALLOW_UNSAFE_OAUTH_REDIRECT_URI: z.stringbool().default(false),
|
|
|
|
// Crowdin (optional, for translation tooling)
|
|
CROWDIN_PROJECT_ID: z.string().optional(),
|
|
CROWDIN_API_TOKEN: z.string().optional(),
|
|
GOOGLE_CLOUD_API_KEY: z.string().optional(),
|
|
},
|
|
runtimeEnv: process.env,
|
|
emptyStringAsUndefined: true,
|
|
});
|