1
8
9export interface RealtimeConfig {
10
11 port: number
12
13 healthPort: number
14
15 jwtSecret: string
16
17 redisUrl: string
18
19 apiUrl: string
20
21 logLevel: string
22
23 rateLimitWindowMs: number
24
25 rateLimitMax: number
26
27 maxRoomSize: number
28
29 useRedis: boolean
30
31 useDatabase: boolean
32
39 internalServiceToken: string
40
41 trustProxy: boolean
42}
43
44
45function parseIntEnv(name: string, value: string | undefined, fallback: number): number {
46 if (value === undefined || value === '') return fallback
47 const parsed = Number.parseInt(value, 10)
48 if (!Number.isInteger(parsed) || parsed <= 0) {
49 throw new Error(`Invalid value for ${name}: "${value}" (expected a positive integer)`)
50 }
51 return parsed
52}
53
54
55function parseBoolEnv(name: string, value: string | undefined, fallback: boolean): boolean {
56 if (value === undefined || value === '') return fallback
57 return !/^(0|false|no|off)$/i.test(value.trim())
58}
59
60
67export function loadConfig(env: NodeJS.ProcessEnv = process.env): RealtimeConfig {
68 const jwtSecret = env.JWT_SECRET?.trim() ?? ''
69 if (jwtSecret.length === 0) {
70 throw new Error('Missing required environment variable: JWT_SECRET')
71 }
72
73 return {
74
75
76
77
78
79 port: parseIntEnv('REALTIME_PORT', env.REALTIME_PORT ?? env.PORT, 4001),
80 healthPort: parseIntEnv('REALTIME_HEALTH_PORT', env.REALTIME_HEALTH_PORT ?? env.HEALTH_PORT, 4002),
81 jwtSecret,
82 redisUrl: env.REDIS_URL ?? 'redis://localhost:6379',
83 apiUrl: env.API_URL ?? 'http://localhost:4000',
84 logLevel: env.LOG_LEVEL ?? 'info',
85 rateLimitWindowMs: parseIntEnv('RATE_LIMIT_WINDOW_MS', env.RATE_LIMIT_WINDOW_MS, 60000),
86 rateLimitMax: parseIntEnv('RATE_LIMIT_MAX', env.RATE_LIMIT_MAX, 300),
87 maxRoomSize: parseIntEnv('MAX_ROOM_SIZE', env.MAX_ROOM_SIZE, 200),
88 useRedis: parseBoolEnv('REALTIME_REDIS', env.REALTIME_REDIS, true),
89 useDatabase: parseBoolEnv('REALTIME_DB', env.REALTIME_DB, true),
90 internalServiceToken: env.INTERNAL_SERVICE_TOKEN?.trim() ?? '',
91 trustProxy: parseBoolEnv('REALTIME_TRUST_PROXY', env.REALTIME_TRUST_PROXY, false),
92 }
93}
94