final touches for beta skymoney (at least i think)
This commit is contained in:
@@ -1,26 +1,62 @@
|
||||
// api/src/env.ts
|
||||
import { z } from "zod";
|
||||
|
||||
const BoolFromEnv = z
|
||||
.union([z.boolean(), z.string()])
|
||||
.transform((val) => {
|
||||
if (typeof val === "boolean") return val;
|
||||
const normalized = val.trim().toLowerCase();
|
||||
return normalized === "true" || normalized === "1";
|
||||
});
|
||||
|
||||
const Env = z.object({
|
||||
NODE_ENV: z.enum(["development", "test", "production"]).default("development"),
|
||||
PORT: z.coerce.number().int().positive().default(8080),
|
||||
HOST: z.string().default("0.0.0.0"),
|
||||
DATABASE_URL: z.string().min(1),
|
||||
|
||||
// Comma-separated list of allowed origins; empty => allow all (dev)
|
||||
CORS_ORIGIN: z.string().optional(),
|
||||
|
||||
// 🔹 New: rate-limit knobs (have defaults so typing is happy)
|
||||
RATE_LIMIT_MAX: z.coerce.number().int().positive().default(200),
|
||||
RATE_LIMIT_WINDOW_MS: z.coerce.number().int().positive().default(60_000),
|
||||
JWT_SECRET: z.string().min(32),
|
||||
COOKIE_SECRET: z.string().min(32),
|
||||
COOKIE_DOMAIN: z.string().optional(),
|
||||
AUTH_DISABLED: BoolFromEnv.optional().default(false),
|
||||
SEED_DEFAULT_BUDGET: BoolFromEnv.default(true),
|
||||
SESSION_TIMEOUT_MINUTES: z.coerce.number().int().positive().default(30),
|
||||
});
|
||||
|
||||
export const env = Env.parse({
|
||||
const rawEnv = {
|
||||
NODE_ENV: process.env.NODE_ENV,
|
||||
PORT: process.env.PORT,
|
||||
HOST: process.env.HOST,
|
||||
DATABASE_URL: process.env.DATABASE_URL,
|
||||
CORS_ORIGIN: "http://localhost:5173,http://127.0.0.1:5173",
|
||||
CORS_ORIGIN: process.env.CORS_ORIGIN,
|
||||
RATE_LIMIT_MAX: process.env.RATE_LIMIT_MAX,
|
||||
RATE_LIMIT_WINDOW_MS: process.env.RATE_LIMIT_WINDOW_MS,
|
||||
});
|
||||
JWT_SECRET: process.env.JWT_SECRET ?? "dev-jwt-secret-change-me",
|
||||
COOKIE_SECRET: process.env.COOKIE_SECRET ?? "dev-cookie-secret-change-me",
|
||||
COOKIE_DOMAIN: process.env.COOKIE_DOMAIN,
|
||||
AUTH_DISABLED: process.env.AUTH_DISABLED,
|
||||
SEED_DEFAULT_BUDGET: process.env.SEED_DEFAULT_BUDGET,
|
||||
};
|
||||
|
||||
const parsed = Env.parse(rawEnv);
|
||||
|
||||
if (parsed.NODE_ENV === "production") {
|
||||
if (!parsed.CORS_ORIGIN) {
|
||||
throw new Error("CORS_ORIGIN must be set in production.");
|
||||
}
|
||||
if (rawEnv.AUTH_DISABLED && parsed.AUTH_DISABLED) {
|
||||
throw new Error("AUTH_DISABLED cannot be enabled in production.");
|
||||
}
|
||||
if (parsed.SEED_DEFAULT_BUDGET) {
|
||||
throw new Error("SEED_DEFAULT_BUDGET must be disabled in production.");
|
||||
}
|
||||
if (parsed.JWT_SECRET.includes("dev-jwt-secret-change-me")) {
|
||||
throw new Error("JWT_SECRET must be set to a strong value in production.");
|
||||
}
|
||||
if (parsed.COOKIE_SECRET.includes("dev-cookie-secret-change-me")) {
|
||||
throw new Error("COOKIE_SECRET must be set to a strong value in production.");
|
||||
}
|
||||
}
|
||||
|
||||
export const env = parsed;
|
||||
|
||||
Reference in New Issue
Block a user