SPB Git

spb/vquant Public MIT

VibeQuant — AI-powered institutional-grade financial intelligence platform.

TypeScript 84.3% Python 11.7% JavaScript 1.6% CSS 1.5% HTML 0.7%
2.9 KB · 77 lines typescript
Raw Blame History
1/*2 * =============================================================================3 *  VibeQuant (vquant) — AI-Powered Financial Intelligence Platform4 * -----------------------------------------------------------------------------5 *  File:      server/db.ts6 *7 *  Author:    Simon-Pierre Boucher8 *  Contact:   contact@spboucher.ai9 *  Website:   https://www.spboucher.ai10 *  Demo:      https://www.vquant.ai11 *  License:   MIT (see LICENSE)12 *13 *  Copyright © 2026 Simon-Pierre Boucher. All rights reserved.14 * =============================================================================15 */1617import { Pool as NeonPool, neonConfig } from '@neondatabase/serverless';18import { drizzle as drizzleNeon } from 'drizzle-orm/neon-serverless';19import { drizzle as drizzleNode } from 'drizzle-orm/node-postgres';20import { drizzle as drizzleSqlite, type BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';21import type { NodePgDatabase } from 'drizzle-orm/node-postgres';22import type { NeonDatabase } from 'drizzle-orm/neon-serverless';23import { Pool as PgPool } from 'pg';24import Database from 'better-sqlite3';25import ws from "ws";26import * as schemaPg from "@shared/schema";27import * as schemaSqlite from "@shared/schema-sqlite";28import path from 'path';29import { logger } from './utils/logger';3031const databaseUrl = process.env.DATABASE_URL || 'sqlite://local.db';3233const isSqlite = databaseUrl.startsWith('sqlite://');34const isLocalDb = databaseUrl.includes('localhost') || databaseUrl.includes('127.0.0.1');3536// Both schemas export the same table names and structure.37// We use the SQLite schema as the canonical type since it's the superset.38type AppSchema = typeof schemaSqlite;39type AppDb = BetterSQLite3Database<AppSchema> | NodePgDatabase<typeof schemaPg> | NeonDatabase<typeof schemaPg>;40type AppPool = Database.Database | PgPool | NeonPool;4142let pool: AppPool;43let db: AppDb;44let schema: AppSchema;4546if (isSqlite) {47  const dbPath = databaseUrl.replace('sqlite://', '');48  const fullPath = path.isAbsolute(dbPath) ? dbPath : path.join(process.cwd(), dbPath);4950  const sqlite = new Database(fullPath);51  sqlite.pragma('journal_mode = WAL');5253  db = drizzleSqlite(sqlite, { schema: schemaSqlite });54  pool = sqlite;55  schema = schemaSqlite;5657  logger.info(`Using SQLite database at: ${fullPath}`);58} else if (isLocalDb) {59  const pgPool = new PgPool({ connectionString: databaseUrl });60  db = drizzleNode(pgPool, { schema: schemaPg });61  pool = pgPool;62  schema = schemaPg as unknown as AppSchema;6364  logger.info('Using local PostgreSQL database');65} else {66  neonConfig.webSocketConstructor = ws;67  const neonPool = new NeonPool({ connectionString: databaseUrl });68  db = drizzleNeon({ client: neonPool, schema: schemaPg });69  pool = neonPool;70  schema = schemaPg as unknown as AppSchema;7172  logger.info('Using Neon serverless PostgreSQL database');73}7475export { pool, db, schema, isSqlite };76export type { AppDb, AppPool, AppSchema };77