Skip to content

db — database

Imported from the facade: import { db } from "@/core/facade.ts".

The Drizzle ORM query client for SQLite plus the connection lifecycle in one object. db is a Proxy: the Drizzle surface (select/insert/update/delete/query) forwards to the live connection, so you call await db.init() once, then query normally. See Database.

Signature

MemberSignatureDescription
init() => Promise<DrizzleDatabase>Open the connection once (idempotent) and return it. Called at boot in src/main.ts.
close() => voidClose the connection and reset the singleton.
select(Drizzle)db.select().from(schema.users) — query rows.
insert(Drizzle)db.insert(schema.users).values({ ... }).returning() — create rows.
update(Drizzle)db.update(schema.users).set({ ... }).where(...) — modify rows.
delete(Drizzle)db.delete(schema.users).where(...) — remove rows.
query(Drizzle)db.query.users.findMany({ where, with, orderBy }) — relational queries with eager loading.

Calls on db before init() throw "Database is not initialized".

Types

ts
type DrizzleDatabase = LibSQLDatabase<typeof schema>; // schema from @/database/schema.ts

Use cases

Boot — connect once

db.init() is idempotent (safe to call many times) and is invoked at startup in src/main.ts.

ts
await db.init();

Create a row (insert + returning)

.returning() hands the stored row back — the usual create-handler pattern.

ts
import { db, pass } from "@/core/facade.ts";
import * as schema from "@/database/schema.ts";

const [user] = await db.insert(schema.users)
  .values({
    name: input.name,
    email: input.email,
    password: await pass.hashPassword(input.password),
  })
  .returning();
return { ok: true, user };

Query rows with filters

Use the sql helper for conditions; drizzle composes it safely.

ts
import { db, sql } from "@/core/facade.ts";

const activeUsers = await db.select().from(schema.users).where(sql`active = true`);

Look up a single row (by key)

Relational queries (db.query.<table>) read nicely with callback-style where.

ts
const user = await db.query.users.findFirst({
  where: (t, { eq }) => eq(t.email, input.email),
});

Eager-load relations

db.query.<table>.findMany({ with }) resolves related rows in one call — no manual joins.

ts
const author = await db.query.users.findFirst({
  where: (t, { eq }) => eq(t.id, id),
  with: { posts: true }, // posts relation from the schema
});

Update and delete

ts
await db.update(schema.users).set({ name: input.name }).where(sql`id = ${id}`);
await db.delete(schema.posts).where(sql`id = ${id}`);

Count rows

ts
import { count } from "drizzle-orm";

const [{ total }] = await db.select({ total: count() }).from(schema.users);

Notes

Seeders are plain default-exported functions in src/modules/<module>/database/seeders/*.seed.ts (see db:seed); one seeder can combine db.query.<table>.findFirst + db.insert + pass.hashPassword.

  • Driver is chosen automatically: node:sqlite (via Drizzle's sqlite-proxy) inside packaged/desktop builds, @libsql/client under plain deno run/dev.
  • All tables come from import * as schema from "@/database/schema.ts" (regenerated by deno task maker db:schema).
  • Pair with paginate and the sql helper for paged, filtered reads.

Released under the MIT License.