Edo Limburg 40ccbbad1a Add storage, dedup modules and infrastructure configuration
- Add storage module with SQLite persistence via better-sqlite3
- Add deduplication module for feed item dedup
- Add infrastructure directory for deployment config
- Add .env.example for environment variables
- Update dependencies: kysely, better-sqlite3, pg
2026-05-05 21:59:50 +02:00

92 lines
2.2 KiB
TypeScript

/**
* Database configuration types and loader.
* Supports SQLite (local) and PostgreSQL (production) via environment variables.
*/
export interface SqliteConfig {
path: string;
}
export interface PostgresConfig {
host: string;
port: number;
database: string;
user: string;
password: string;
}
export interface PostgresUrlConfig {
connectionString: string;
}
export type DatabaseType = 'sqlite' | 'postgres';
export interface DatabaseConfig {
type: DatabaseType;
sqlite?: SqliteConfig;
postgres?: PostgresConfig | PostgresUrlConfig;
}
function getEnvVar(name: string, defaultValue?: string): string {
const value = process.env[name];
if (value === undefined) {
if (defaultValue !== undefined) {
return defaultValue;
}
throw new Error(`Missing required environment variable: ${name}`);
}
return value;
}
export function loadConfig(): DatabaseConfig {
const type = getEnvVar('PULSE_DATABASE_TYPE', 'sqlite') as DatabaseType;
if (type === 'sqlite') {
return {
type: 'sqlite',
sqlite: {
path: getEnvVar('PULSE_SQLITE_PATH', './data/pulse.db'),
},
};
}
if (type === 'postgres') {
const connectionString = process.env.PULSE_DATABASE_URL;
if (connectionString) {
return {
type: 'postgres',
postgres: { connectionString },
};
}
return {
type: 'postgres',
postgres: {
host: getEnvVar('PULSE_POSTGRES_HOST'),
port: parseInt(getEnvVar('PULSE_POSTGRES_PORT', '5432'), 10),
database: getEnvVar('PULSE_POSTGRES_DATABASE'),
user: getEnvVar('PULSE_POSTGRES_USER'),
password: getEnvVar('PULSE_POSTGRES_PASSWORD'),
},
};
}
throw new Error(`Unsupported database type: ${type}. Use 'sqlite' or 'postgres'.`);
}
export function validateConfig(config: DatabaseConfig): void {
if (config.type === 'sqlite') {
if (!config.sqlite) {
throw new Error('SQLite configuration missing');
}
if (!config.sqlite.path) {
throw new Error('SQLite path is required');
}
} else if (config.type === 'postgres') {
if (!config.postgres) {
throw new Error('PostgreSQL configuration missing');
}
}
}