typescript-express-starter
Version:
Quick and Easy TypeScript Express Starter
85 lines (70 loc) • 2.58 kB
text/typescript
import { config } from "dotenv";
import { existsSync } from "fs";
import { resolve } from "path";
import { z } from "zod";
/**
* 1) dotenv 로드 순서
* - .env (공통)
* - .env.{NODE_ENV}.local (환경별 override, 있으면 덮어씀)
*/
config(); // .env
const nodeEnv = process.env.NODE_ENV || "development";
const layerPath = resolve(process.cwd(), `.env.${nodeEnv}.local`);
if (existsSync(layerPath)) {
config({ path: layerPath });
}
/**
* 2) Zod 스키마 정의
* - 필수/선택/기본값 정책은 필요에 맞게 수정 가능
*/
const EnvSchema = z
.object({
NODE_ENV: z
.enum(["development", "production", "test"])
.default("development"),
PORT: z.coerce.number().int().positive().optional(), // 기본값은 app.ts에서 3000 처리
SECRET_KEY: z.string().min(1),
LOG_FORMAT: z.string().min(1).optional(), // 기본값은 app.ts에서 'dev'
LOG_DIR: z.string().min(1),
LOG_LEVEL: z.string().min(1),
ORIGIN: z.string().min(1), // 필요시 배열화 가능
CREDENTIALS: z.coerce.boolean(), // 'true'/'false' 문자열 → boolean
CORS_ORIGINS: z.string().optional(), // "http://a.com,http://b.com"
API_SERVER_URL: z.string().url().optional(),
SENTRY_DSN: z.string().default(""),
REDIS_URL: z.string().url().default("redis://localhost:6379"),
// Database configuration for Drizzle
DATABASE_URL: z.string().url().min(1),
})
.strip();
/**
* 3) 검증(모듈 import 시점에 실행)
*/
const parsed = EnvSchema.safeParse(process.env);
if (!parsed.success) {
console.error("\n❌ Invalid environment variables:\n");
console.error(parsed.error.format());
process.exit(1);
}
const env = parsed.data;
/**
* 4) 타입 안전한 상수 export
* - 다른 파일에서는 process.env 직접 쓰지 말고 여기서만 가져가세요.
*/
export const NODE_ENV = env.NODE_ENV;
export const PORT = env.PORT; // app.ts에서 PORT || 3000
export const SECRET_KEY = env.SECRET_KEY;
export const LOG_FORMAT = env.LOG_FORMAT; // app.ts에서 LOG_FORMAT || 'dev'
export const LOG_DIR = env.LOG_DIR;
export const LOG_LEVEL = env.LOG_LEVEL;
export const ORIGIN = env.ORIGIN;
export const CREDENTIALS = env.CREDENTIALS;
export const SENTRY_DSN = env.SENTRY_DSN;
export const REDIS_URL = env.REDIS_URL;
export const API_SERVER_URL = env.API_SERVER_URL;
export const DATABASE_URL = env.DATABASE_URL;
// CORS Origins를 배열로도 제공 (없으면 [])
export const CORS_ORIGIN_LIST =
env.CORS_ORIGINS?.split(",")
.map((s) => s.trim())
.filter(Boolean) ?? [];