feat(server): REST API, auth, sources, changes, export
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 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
7b0a6738dd
commit
6963e297b0
@@ -0,0 +1,30 @@
|
||||
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 !== ""),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user