101 lines
3.9 KiB
TypeScript
101 lines
3.9 KiB
TypeScript
import { z } from "zod";
|
|
|
|
const supportedLocales = ["de", "en"] as const;
|
|
|
|
const configSchema = z.object({
|
|
port: z.coerce.number().min(1).max(65535).default(8000),
|
|
logLevel: z.enum(["debug", "info", "warn", "error"]).default("info"),
|
|
databasePath: z.string().default("./data/contracts.db"),
|
|
paperlessBaseUrl: z.string().url().optional(),
|
|
paperlessToken: z.string().min(1).optional(),
|
|
paperlessExternalUrl: z.string().url().optional(),
|
|
paperlessWebhookUrl: z.string().url().optional(),
|
|
appExternalUrl: z.string().url().optional(),
|
|
appLocale: z.enum(supportedLocales).default("de"),
|
|
schedulerIntervalMinutes: z.coerce.number().min(5).default(60),
|
|
alertDaysBefore: z.coerce.number().min(1).default(30),
|
|
mailServer: z.string().optional(),
|
|
mailPort: z.coerce.number().min(1).max(65535).default(587),
|
|
mailUsername: z.string().optional(),
|
|
mailPassword: z.string().optional(),
|
|
mailUseTls: z.coerce.boolean().default(true),
|
|
mailFrom: z.string().email().optional(),
|
|
mailTo: z.string().email().optional(),
|
|
authUsername: z.string().optional(),
|
|
authPassword: z.string().optional(),
|
|
authJwtSecret: z.string().optional(),
|
|
authTokenExpiresInHours: z.coerce.number().min(1).max(168).default(12),
|
|
ntfyServerUrl: z.string().url().optional(),
|
|
ntfyTopic: z.string().min(1).optional(),
|
|
ntfyToken: z.string().optional(),
|
|
ntfyPriority: z.string().optional(),
|
|
icalSecret: z.string().optional(),
|
|
aiEnabled: z.coerce.boolean().default(false),
|
|
aiProvider: z.enum(["openai", "openai-compatible", "gemini"]).optional(),
|
|
aiBaseUrl: z.string().url().optional(),
|
|
aiModel: z.string().min(1).optional(),
|
|
aiApiKey: z.string().min(1).optional(),
|
|
aiSystemPrompt: z.string().optional(),
|
|
aiTimeoutSeconds: z.coerce.number().min(5).max(300).default(60),
|
|
aiMaxTokens: z.coerce.number().min(256).max(16000).default(2000),
|
|
paperlessWebhookSecret: z.string().min(10).optional()
|
|
});
|
|
|
|
function parseBoolean(value: string | undefined, fallback: boolean): boolean {
|
|
if (value === undefined) {
|
|
return fallback;
|
|
}
|
|
return ["1", "true", "yes", "on"].includes(value.toLowerCase());
|
|
}
|
|
|
|
function readEnv(name: string): string | undefined {
|
|
const value = process.env[name];
|
|
if (value === undefined) {
|
|
return undefined;
|
|
}
|
|
return value.trim().length > 0 ? value : undefined;
|
|
}
|
|
|
|
const rawConfig = {
|
|
port: readEnv("PORT"),
|
|
logLevel: readEnv("LOG_LEVEL"),
|
|
databasePath: readEnv("DATABASE_PATH"),
|
|
paperlessBaseUrl: readEnv("PAPERLESS_BASE_URL"),
|
|
paperlessToken: readEnv("PAPERLESS_TOKEN"),
|
|
paperlessExternalUrl: readEnv("PAPERLESS_EXTERNAL_URL"),
|
|
paperlessWebhookUrl: readEnv("PAPERLESS_WEBHOOK_URL"),
|
|
appExternalUrl: readEnv("APP_EXTERNAL_URL"),
|
|
appLocale: readEnv("APP_LOCALE"),
|
|
schedulerIntervalMinutes: readEnv("SCHEDULER_INTERVAL_MINUTES"),
|
|
alertDaysBefore: readEnv("ALERT_DAYS_BEFORE"),
|
|
mailServer: readEnv("MAIL_SERVER"),
|
|
mailPort: readEnv("MAIL_PORT"),
|
|
mailUsername: readEnv("MAIL_USERNAME"),
|
|
mailPassword: readEnv("MAIL_PASSWORD"),
|
|
mailUseTls: parseBoolean(readEnv("MAIL_USE_TLS"), true),
|
|
mailFrom: readEnv("MAIL_FROM"),
|
|
mailTo: readEnv("MAIL_TO"),
|
|
authUsername: readEnv("AUTH_USERNAME"),
|
|
authPassword: readEnv("AUTH_PASSWORD"),
|
|
authJwtSecret: readEnv("AUTH_JWT_SECRET"),
|
|
authTokenExpiresInHours: readEnv("AUTH_TOKEN_EXPIRES_IN_HOURS"),
|
|
ntfyServerUrl: readEnv("NTFY_SERVER_URL"),
|
|
ntfyTopic: readEnv("NTFY_TOPIC"),
|
|
ntfyToken: readEnv("NTFY_TOKEN"),
|
|
ntfyPriority: readEnv("NTFY_PRIORITY"),
|
|
icalSecret: readEnv("ICAL_SECRET"),
|
|
aiEnabled: parseBoolean(readEnv("AI_ENABLED"), false),
|
|
aiProvider: readEnv("AI_PROVIDER"),
|
|
aiBaseUrl: readEnv("AI_BASE_URL"),
|
|
aiModel: readEnv("AI_MODEL"),
|
|
aiApiKey: readEnv("AI_API_KEY"),
|
|
aiSystemPrompt: readEnv("AI_SYSTEM_PROMPT"),
|
|
aiTimeoutSeconds: readEnv("AI_TIMEOUT_SECONDS"),
|
|
aiMaxTokens: readEnv("AI_MAX_TOKENS"),
|
|
paperlessWebhookSecret: readEnv("PAPERLESS_WEBHOOK_SECRET")
|
|
};
|
|
|
|
export type AppConfig = z.infer<typeof configSchema>;
|
|
|
|
export const config: AppConfig = configSchema.parse(rawConfig);
|