Validation des chemins externalisée (library-path) avec codes d'erreur explicites, support d'alias LIBRARY_PATH_ALIASES pour traduire un chemin hôte vers le montage conteneur, rejet des doublons de chemin entre bibliothèques, documentation README/.env.example et docker-compose paramétrable via READABOOK_LIBRARY_HOST_PATH. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
62 lines
2.2 KiB
TypeScript
62 lines
2.2 KiB
TypeScript
import { mkdirSync } from "node:fs";
|
|
import { dirname, resolve } from "node:path";
|
|
|
|
export type AppConfig = {
|
|
nodeEnv: string;
|
|
host: string;
|
|
port: number;
|
|
databasePath: string;
|
|
storageDir: string;
|
|
jwtSecret: string;
|
|
cookieName: string;
|
|
cookieSecure: boolean;
|
|
openLibraryEnabled: boolean;
|
|
libraryPathAliases: Array<{ from: string; to: string }>;
|
|
initialAdminEmail: string;
|
|
initialAdminPassword: string;
|
|
initialAdminPasswordIsDefault: boolean;
|
|
};
|
|
|
|
const DEFAULT_INITIAL_ADMIN_EMAIL = "admin@readabook.local";
|
|
const DEFAULT_INITIAL_ADMIN_PASSWORD = "readabook-admin-change-me";
|
|
|
|
export function loadConfig(): AppConfig {
|
|
const databasePath = resolve(process.env.DATABASE_PATH ?? "./data/readabook.sqlite");
|
|
const storageDir = resolve(process.env.STORAGE_DIR ?? "./data/storage");
|
|
|
|
mkdirSync(dirname(databasePath), { recursive: true });
|
|
mkdirSync(storageDir, { recursive: true });
|
|
|
|
return {
|
|
nodeEnv: process.env.NODE_ENV ?? "development",
|
|
host: process.env.HOST ?? "0.0.0.0",
|
|
port: Number(process.env.PORT ?? 3000),
|
|
databasePath,
|
|
storageDir,
|
|
jwtSecret: process.env.JWT_SECRET ?? "dev-change-me-readabook",
|
|
cookieName: process.env.AUTH_COOKIE_NAME ?? "readabook_session",
|
|
cookieSecure: process.env.COOKIE_SECURE === "true",
|
|
openLibraryEnabled: process.env.OPEN_LIBRARY_ENABLED !== "false",
|
|
libraryPathAliases: parseLibraryPathAliases(process.env.LIBRARY_PATH_ALIASES),
|
|
initialAdminEmail: process.env.INITIAL_ADMIN_EMAIL ?? DEFAULT_INITIAL_ADMIN_EMAIL,
|
|
initialAdminPassword: process.env.INITIAL_ADMIN_PASSWORD ?? DEFAULT_INITIAL_ADMIN_PASSWORD,
|
|
initialAdminPasswordIsDefault: !process.env.INITIAL_ADMIN_PASSWORD
|
|
};
|
|
}
|
|
|
|
function parseLibraryPathAliases(value: string | undefined): Array<{ from: string; to: string }> {
|
|
if (!value) return [];
|
|
return value
|
|
.split(";")
|
|
.map((entry) => entry.trim())
|
|
.filter(Boolean)
|
|
.map((entry) => {
|
|
const separator = entry.indexOf("=");
|
|
if (separator === -1) return null;
|
|
const from = entry.slice(0, separator).trim();
|
|
const to = entry.slice(separator + 1).trim();
|
|
return from && to ? { from, to } : null;
|
|
})
|
|
.filter((entry): entry is { from: string; to: string } => Boolean(entry));
|
|
}
|