import { z } from 'zod' import { PANEL_MODES } from '@telemt/shared' export const configSchema = z.object({ databaseUrl: z.string().default('sqlite:data/app.db'), jwtSecret: z.string().min(8), jwtTtlHours: z.coerce.number().positive().default(24), issuer: z.string().default('telemt-panel'), serverPort: z.coerce.number().int().positive().default(8080), staticDir: z.string().optional(), logLevel: z.string().default('info'), isProd: z.boolean(), panelMode: z.enum(PANEL_MODES).default('standalone'), telemtApiUrl: z.string().default('http://127.0.0.1:9091'), telemtAuthHeader: z.string().default(''), panelEncryptionKey: z.string().default(''), panelPublicUrl: z.string().default('http://127.0.0.1:8080'), bootstrapUsername: z.string().default('admin'), bootstrapPassword: z.string().optional(), }) export type AppConfig = z.infer export function loadConfig(env: NodeJS.ProcessEnv = process.env): AppConfig { const isProd = env.NODE_ENV === 'production' const jwtFromEnv = env.JWT_SECRET?.trim() const jwtSecret = jwtFromEnv && jwtFromEnv.length > 0 ? jwtFromEnv : isProd ? '' : 'dev-secret-change-me' if (isProd && jwtSecret.length < 8) { throw new Error( 'JWT_SECRET is required in production and must be at least 8 characters (e.g. openssl rand -hex 32)', ) } return configSchema.parse({ databaseUrl: env.DATABASE_URL ?? 'sqlite:data/app.db', jwtSecret, jwtTtlHours: env.JWT_TTL_HOURS ?? 24, issuer: env.ISSUER ?? 'telemt-panel', serverPort: env.SERVER_PORT ?? 8080, staticDir: env.STATIC_DIR || undefined, logLevel: env.LOG_LEVEL ?? 'info', isProd, panelMode: env.PANEL_MODE ?? 'standalone', telemtApiUrl: env.TELEMT_API_URL ?? 'http://127.0.0.1:9091', telemtAuthHeader: env.TELEMT_AUTH_HEADER ?? '', panelEncryptionKey: env.PANEL_ENCRYPTION_KEY ?? (isProd ? '' : 'dev-encryption-key'), panelPublicUrl: env.PANEL_PUBLIC_URL ?? 'http://127.0.0.1:8080', bootstrapUsername: env.BOOTSTRAP_USERNAME ?? 'admin', bootstrapPassword: env.BOOTSTRAP_PASSWORD, }) }