createApp() serves /api/v1 from a typed route table (zod bodies and queries), with session-cookie and Bearer app-token auth, a CSRF header for cookie writes, login/register rate limiting, body caps, JSON error mapping, OpenAPI generation and a 404 /ingest mount. Co-Authored-By: Claude Opus 5.5 <[email protected]>
31 lines
1.0 KiB
TypeScript
31 lines
1.0 KiB
TypeScript
export interface Config {
|
|
databaseUrl: string;
|
|
dataDir: string;
|
|
secret: string;
|
|
publicUrl: string | undefined;
|
|
port: number;
|
|
pluginDirs: string[];
|
|
}
|
|
|
|
export const MISSING_SECRET = "Set STTRACKER_SECRET to a long random string. It encrypts source credentials.";
|
|
|
|
/** Read the server config from the environment. Throws when `STTRACKER_SECRET` is missing. */
|
|
export function loadConfig(env: Record<string, string | undefined> = process.env): Config {
|
|
const secret = env.STTRACKER_SECRET;
|
|
if (!secret) throw new Error(MISSING_SECRET);
|
|
const dataDir = env.DATA_DIR || "./data";
|
|
const port = Number(env.PORT || 3000);
|
|
if (!Number.isInteger(port) || port < 0 || port > 65535) throw new Error(`PORT must be a port number, got "${env.PORT}"`);
|
|
return {
|
|
databaseUrl: env.DATABASE_URL || `sqlite://${dataDir}/sttracker.db`,
|
|
dataDir,
|
|
secret,
|
|
publicUrl: env.PUBLIC_URL || undefined,
|
|
port,
|
|
pluginDirs: (env.PLUGIN_DIRS || `plugins,${dataDir}/plugins`)
|
|
.split(",")
|
|
.map((d) => d.trim())
|
|
.filter((d) => d !== ""),
|
|
};
|
|
}
|