From 63714f596015cf56c14b6a54b14ece61eefa18d7 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 10 Jun 2026 07:51:00 +0000 Subject: [PATCH] feat: db connection and migration --- server/db/migrate.ts | 23 +++++++++++++++++++++++ server/db/migrations/0001_init.sql | 22 ++++++++++++++++++++++ server/utils/db.ts | 13 +++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 server/db/migrate.ts create mode 100644 server/db/migrations/0001_init.sql create mode 100644 server/utils/db.ts diff --git a/server/db/migrate.ts b/server/db/migrate.ts new file mode 100644 index 0000000..1380f00 --- /dev/null +++ b/server/db/migrate.ts @@ -0,0 +1,23 @@ +// Idempotent migration runner. Run via `bun run migrate` / on container start. +import { readFileSync } from "node:fs"; +import { fileURLToPath } from "node:url"; +import { dirname, join } from "node:path"; +import postgres from "postgres"; + +const url = process.env.DATABASE_URL; +if (!url) { + console.error("DATABASE_URL not set"); + process.exit(1); +} + +const here = dirname(fileURLToPath(import.meta.url)); +const sql = postgres(url, { max: 1 }); + +try { + const ddl = readFileSync(join(here, "migrations", "0001_init.sql"), "utf8"); + // Trusted local DDL file, not user input. + await sql.unsafe(ddl); + console.log("migration 0001_init applied"); +} finally { + await sql.end(); +} diff --git a/server/db/migrations/0001_init.sql b/server/db/migrations/0001_init.sql new file mode 100644 index 0000000..3bd722d --- /dev/null +++ b/server/db/migrations/0001_init.sql @@ -0,0 +1,22 @@ +-- ClaudeDo Online Inbox — initial schema. +-- Mirrors the desktop's Idle task backlog. Idempotent. + +create table if not exists lists ( + id text primary key, -- GUID supplied by the desktop, reused verbatim + name text not null, + updated_at timestamptz not null default now() +); + +create table if not exists tasks ( + id text primary key, -- GUID; shared id space (web + desktop) + list_id text not null references lists(id) on delete cascade, + title text not null, + description text, + source text not null, -- 'web' | 'desktop' + consumed boolean not null default false, -- web->desktop handoff flag + created_at timestamptz not null default now(), + updated_at timestamptz not null default now() +); + +create index if not exists idx_tasks_list_id on tasks(list_id); +create index if not exists idx_tasks_unconsumed on tasks(consumed) where consumed = false; diff --git a/server/utils/db.ts b/server/utils/db.ts new file mode 100644 index 0000000..c10e28b --- /dev/null +++ b/server/utils/db.ts @@ -0,0 +1,13 @@ +import postgres from "postgres"; + +let _sql: ReturnType | null = null; + +/** Lazily-created shared postgres.js connection pool. */ +export function getSql() { + if (!_sql) { + const url = process.env.DATABASE_URL; + if (!url) throw new Error("DATABASE_URL not set"); + _sql = postgres(url, { max: 5, idle_timeout: 30 }); + } + return _sql; +}