From 850f4f826b536d913235e174dc07aef74e51bf60 Mon Sep 17 00:00:00 2001 From: benj Date: Fri, 1 May 2026 09:36:21 +0800 Subject: irs 990 doc prarsers and some web stuff --- web/api/src/db.ts | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 web/api/src/db.ts (limited to 'web/api/src/db.ts') diff --git a/web/api/src/db.ts b/web/api/src/db.ts new file mode 100644 index 0000000..39fe536 --- /dev/null +++ b/web/api/src/db.ts @@ -0,0 +1,72 @@ +import Database from 'better-sqlite3'; +import { resolve } from 'node:path'; + +// TEMPORARY dev wiring. The API reads directly from the SvelteKit UI's +// SQLite file so "create a key in the UI → use it in the API" works with +// zero infra. This whole module gets replaced when the API moves to +// @tidyindex/core + Drizzle + Neon (or self-hosted Postgres via Hyperdrive). +const DB_PATH = resolve( + process.env.DATABASE_PATH ?? '../ui/data/dashboard.db' +); + +export const db = new Database(DB_PATH); +db.pragma('foreign_keys = ON'); + +export interface ApiKeyLookup { + keyId: string; + name: string; + scopes: string[]; + account: { + id: string; + email: string | null; + plan: string; + }; +} + +const lookupStmt = db.prepare< + [string], + { + key_id: string; + key_name: string; + key_scopes: string; + account_id: string; + account_email: string | null; + account_plan: string; + } +>(` + SELECT + k.id AS key_id, + k.name AS key_name, + k.scopes AS key_scopes, + a.id AS account_id, + a.email AS account_email, + a.plan AS account_plan + FROM api_keys k + JOIN accounts a ON a.id = k.account_id + WHERE k.key_hash = ? AND k.active = 1 +`); + +const touchStmt = db.prepare<[number, string]>( + `UPDATE api_keys SET last_used_at = ? WHERE id = ?` +); + +export function lookupApiKey(hash: string): ApiKeyLookup | null { + const row = lookupStmt.get(hash); + if (!row) return null; + + // Update last_used_at so the UI shows the key as active. Cheap, + // synchronous, runs on the hot path — fine for dev; in prod this + // becomes a buffered write on the AccountMeter Durable Object. + touchStmt.run(Date.now(), row.key_id); + + return { + keyId: row.key_id, + name: row.key_name, + scopes: JSON.parse(row.key_scopes) as string[], + account: { + id: row.account_id, + email: row.account_email, + plan: row.account_plan + } + }; +} -- cgit v1.2.3