qwen_2.5_model / src /database /data-source.ts
Muhammad Noman
Configure managed services for Hugging Face Space
b58ffca
Raw
History Blame Contribute Delete
4.5 kB
import { DataSource, DataSourceOptions } from 'typeorm';
import * as path from 'path';
import { resolveDataDatabaseType, resolvePostgresConnection } from '../config/managed-service-connections';
import { loadCliEnv } from './load-cli-env';
// Load env with the same precedence as the app (process.env > .env > configured data mount), so the
// migration CLI targets the SAME database the dashboard configured — not the default SQLite DB.
loadCliEnv();
const dbType = resolveDataDatabaseType();
const sourceGlob = (...segments: string[]): string => path.join(__dirname, ...segments).replace(/\\/g, '/');
// Scoped to the DATA-owned modules only (session/webhook/message/template/engine/integration), mirroring
// the runtime data connection (app.module.ts). A broad '**' glob would also sweep in the main-owned
// auth/audit entities and pollute `migration:generate` against the data DB with their DDL.
const dataEntities = [
sourceGlob('..', 'modules', 'session', '**', '*.entity{.ts,.js}'),
sourceGlob('..', 'modules', 'webhook', '**', '*.entity{.ts,.js}'),
sourceGlob('..', 'modules', 'message', '**', '*.entity{.ts,.js}'),
sourceGlob('..', 'modules', 'template', '**', '*.entity{.ts,.js}'),
sourceGlob('..', 'engine', '**', '*.entity{.ts,.js}'),
sourceGlob('..', 'modules', 'integration', '**', '*.entity{.ts,.js}'),
];
const dataMigrations = [sourceGlob('migrations', '*{.ts,.js}')];
// SQLite configuration
const sqliteDataSourceOptions: DataSourceOptions = {
type: 'better-sqlite3',
database: process.env.DATABASE_NAME || './data/openwa.sqlite',
entities: dataEntities,
migrations: dataMigrations,
synchronize: false,
logging: process.env.DATABASE_LOGGING === 'true',
};
// PostgreSQL configuration.
//
// Exported as plain DataSourceOptions, NOT a DataSource instance: the TypeORM CLI's loadDataSource()
// rejects a data-source file that exports more than one DataSource instance ("must contain only one
// export of DataSource"). Keeping the postgres config as an options object leaves exactly one instance
// export (the default below) so every `migration:*` command resolves it.
// Schema selection: a non-public POSTGRES_SCHEMA sets TypeORM's `schema` option AND the session
// search_path (via pg's startup `options` parameter) so the project's RAW, unqualified migration SQL
// (CREATE TABLE "x"..., ALTER TABLE "y"...) resolves to the configured schema. TypeORM's `schema`
// option alone does NOT set search_path — without the `options` override, raw DDL would land in
// `public` while the migration ledger lands in the configured schema. `<schema>,public` keeps public
// on the path so pg_catalog + any public helpers still resolve; the configured schema wins.
//
// Exported as a builder so the schema/search_path logic is unit-testable without mutating process.env
// or reloading the module. The default `postgresDataSourceOptions` reads the loaded env at module eval.
export function buildPostgresDataSourceOptions(env: NodeJS.ProcessEnv = process.env): DataSourceOptions {
const connection = resolvePostgresConnection(env);
const schema = env.POSTGRES_SCHEMA || 'public';
const useCustomSearchPath = schema !== 'public';
return {
type: 'postgres',
schema,
host: connection.host,
port: connection.port,
username: connection.username,
password: connection.password,
database: connection.database,
entities: dataEntities,
migrations: dataMigrations,
synchronize: false, // Never auto-sync in production
logging: env.DATABASE_LOGGING === 'true',
ssl: connection.ssl ? { rejectUnauthorized: connection.sslRejectUnauthorized } : false,
extra: {
max: parseInt(env.DATABASE_POOL_SIZE || '10', 10),
// Pool resilience only. NO statement_timeout here: this connection runs migrations, and a
// long CREATE INDEX / backfill must not be aborted mid-flight.
idleTimeoutMillis: parseInt(env.DATABASE_IDLE_TIMEOUT_MS || '30000', 10),
connectionTimeoutMillis: parseInt(env.DATABASE_CONNECTION_TIMEOUT_MS || '10000', 10),
// Only set for a non-public schema (see above).
...(useCustomSearchPath ? { options: `-c search_path=${schema},public` } : {}),
},
};
}
export const postgresDataSourceOptions: DataSourceOptions = buildPostgresDataSourceOptions();
// Exactly ONE DataSource instance is exported (the default), selected by DATABASE_TYPE.
export default new DataSource(dbType === 'postgres' ? postgresDataSourceOptions : sqliteDataSourceOptions);