WIP! A BB-style forum, on the ATmosphere! We're still working... we'll be back soon when we have something to show off!
node typescript hono htmx atproto

feat(db): URL-based driver detection in createDb (postgres vs SQLite)

+27 -31
+27 -31
packages/db/src/index.ts
··· 1 - import { drizzle } from "drizzle-orm/postgres-js"; 1 + import { drizzle as drizzlePg } from "drizzle-orm/postgres-js"; 2 + import { drizzle as drizzleSqlite } from "drizzle-orm/libsql"; 3 + import { createClient } from "@libsql/client"; 2 4 import postgres from "postgres"; 3 - import * as schema from "./schema.js"; 5 + import * as pgSchema from "./schema.js"; 6 + import * as sqliteSchema from "./schema.sqlite.js"; 4 7 5 - export function createDb(databaseUrl: string) { 6 - const client = postgres(databaseUrl); 7 - return drizzle(client, { schema }); 8 + /** 9 + * Create a Drizzle database instance from a connection URL. 10 + * 11 + * URL prefix determines the driver: 12 + * postgres:// or postgresql:// → postgres.js (PostgreSQL) 13 + * file: → @libsql/client (SQLite file) 14 + * file::memory: → @libsql/client (SQLite in-memory, tests) 15 + * libsql:// → @libsql/client (Turso cloud) 16 + */ 17 + export function createDb(databaseUrl: string): Database { 18 + if (databaseUrl.startsWith("postgres")) { 19 + return drizzlePg(postgres(databaseUrl), { schema: pgSchema }) as Database; 20 + } 21 + return drizzleSqlite( 22 + createClient({ url: databaseUrl }), 23 + { schema: sqliteSchema } 24 + ) as unknown as Database; 8 25 } 9 26 10 - export type Database = ReturnType<typeof createDb>; 27 + // Database type uses the Postgres schema as the TypeScript source of truth. 28 + // Both dialects produce compatible column names and TypeScript types, 29 + // so the cast is safe at the app layer. 30 + export type Database = ReturnType<typeof drizzlePg<typeof pgSchema>>; 11 31 12 - /** 13 - * Transaction type extracted from Drizzle's database instance. 14 - * Use this when you need to work with a transaction object directly. 15 - */ 16 - export type Transaction = Parameters<Parameters<Database['transaction']>[0]>[0]; 32 + export type Transaction = Parameters<Parameters<Database["transaction"]>[0]>[0]; 17 33 18 - /** 19 - * Union type for functions that need to work with either the database 20 - * instance or an active transaction. This is useful for helper functions 21 - * that can be called both standalone and within a transaction context. 22 - * 23 - * Example: 24 - * ```typescript 25 - * async function getUser(id: string, dbOrTx: DbOrTransaction = db) { 26 - * return dbOrTx.select().from(users).where(eq(users.id, id)); 27 - * } 28 - * 29 - * // Can be called standalone 30 - * await getUser('123', db); 31 - * 32 - * // Or within a transaction 33 - * await db.transaction(async (tx) => { 34 - * await getUser('123', tx); 35 - * }); 36 - * ``` 37 - */ 38 34 export type DbOrTransaction = Database | Transaction; 39 35 40 36 export * from "./schema.js";