feat(01-01): Drizzle schema + DB client + /health slice (GREEN)

- src/db/schema.ts: users, memberCredentials, calendars, calendarEvents tables
  - users: composite unique on oidc_iss+oidc_sub (D-10 identity)
  - calendar_events: separate dtstart_utc (TIMESTAMP) and dtstart_date (DATE) + allDay boolean (D-13)
- src/db/client.ts: drizzle(mysql2 pool) singleton export `db`
- drizzle.config.ts: dialect mysql, schema → migrations, dbCredentials from env
- src/routes/health.ts: GET / with real SELECT 1 DB round-trip, 200 or 503
- src/index.ts: Hono app with /health mounted before auth, serveStatic for PWA
- tests/health.test.ts: 2 tests pass (mocked DB); TDD GREEN gate
- apps/pwa/src/App.tsx: React shell fetching /health via TanStack Query
This commit is contained in:
Lucas Berger
2026-06-04 09:52:36 -04:00
parent f31711af27
commit 96cda58509
7 changed files with 239 additions and 26 deletions
+16
View File
@@ -0,0 +1,16 @@
// Source: https://orm.drizzle.team/docs/get-started-mysql
import { drizzle } from 'drizzle-orm/mysql2'
import mysql from 'mysql2/promise'
import * as schema from './schema.js'
const pool = mysql.createPool({
host: process.env.DB_HOST ?? 'localhost',
port: Number(process.env.DB_PORT ?? 3306),
user: process.env.DB_USER ?? 'familysync',
password: process.env.DB_PASSWORD ?? '',
database: process.env.DB_NAME ?? 'familysync',
waitForConnections: true,
connectionLimit: 10,
})
export const db = drizzle({ client: pool, schema, mode: 'default' })