41 lines
1.3 KiB
TypeScript
41 lines
1.3 KiB
TypeScript
import { z } from 'zod';
|
|
import dotenv from 'dotenv';
|
|
import path from 'node:path';
|
|
|
|
dotenv.config({ path: path.resolve(__dirname, '../../../.env') });
|
|
|
|
const envSchema = z.object({
|
|
DATABASE_URL: z.string().min(1),
|
|
ENCRYPTION_KEY: z.string().length(64, 'ENCRYPTION_KEY must be 64 hex characters (32 bytes)'),
|
|
AI_API_KEY: z.string().optional(),
|
|
AI_BASE_URL: z.string().url().default('https://openrouter.ai/api/v1'),
|
|
AI_MODEL: z.string().default('openrouter/free'),
|
|
// Legacy alias — still accepted
|
|
OPENAI_API_KEY: z.string().optional(),
|
|
API_KEY: z.string().optional(),
|
|
PORT: z.coerce.number().default(3000),
|
|
PUBLIC_BASE_URL: z.string().url().optional(),
|
|
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
|
|
});
|
|
|
|
const parsed = envSchema.safeParse(process.env);
|
|
|
|
if (!parsed.success) {
|
|
console.error('Invalid environment variables:', parsed.error.flatten().fieldErrors);
|
|
process.exit(1);
|
|
}
|
|
|
|
const data = parsed.data;
|
|
|
|
function resolveDatabaseUrl(url: string): string {
|
|
if (!url.startsWith('file:')) return url;
|
|
const filePath = url.slice('file:'.length);
|
|
if (path.isAbsolute(filePath)) return url;
|
|
return `file:${path.resolve(__dirname, '../../../', filePath)}`;
|
|
}
|
|
|
|
export const config = {
|
|
...data,
|
|
DATABASE_URL: resolveDatabaseUrl(data.DATABASE_URL),
|
|
AI_API_KEY: data.AI_API_KEY ?? data.OPENAI_API_KEY,
|
|
};
|