feat: implement incident reporting and management system
CI / Lint, typecheck, test, build (push) Canceled after 0s
CI / End-to-end tests (push) Canceled after 0s

- Add incident reporting routes and logic to handle creation, updating, and retrieval of incidents.
- Implement visibility rules for users based on roles (reporters, supervisors).
- Create tests for incident reporting functionality to ensure correctness and reliability.
- Introduce site and area management routes, including validation for area hierarchy.
- Establish user management routes with role-based access control for creating and updating users.
- Add setup routes for initializing the application with an organization and admin user.
- Implement shared enums and schemas for consistent validation and data handling across the application.
- Create a test helper for setting up an in-memory database and API client for testing.
- Add TypeScript configuration for server-side code with strict type checking and module resolution.
This commit is contained in:
jayjennings committed 2026-10-06 10:51:18 -07:00
1 parent a382fa904a
commit c69eccb5c1
47 files changed
+6297 -45

No files matched your search

+55
View File
@@ -0,0 +1,55 @@
import { PGlite } from '@electric-sql/pglite'
import { drizzle as drizzlePg } from 'drizzle-orm/node-postgres'
import { migrate as migratePg } from 'drizzle-orm/node-postgres/migrator'
import type { PgDatabase, PgQueryResultHKT } from 'drizzle-orm/pg-core'
import { drizzle as drizzlePglite } from 'drizzle-orm/pglite'
import { migrate as migratePglite } from 'drizzle-orm/pglite/migrator'
import { mkdirSync } from 'node:fs'
import { join } from 'node:path'
import pg from 'pg'
import * as schema from './schema.ts'
export type Db = PgDatabase<PgQueryResultHKT, typeof schema>
export interface Database {
db: Db
close(): Promise<void>
}
const migrationsFolder = join(import.meta.dirname, 'migrations')
/**
* Opens the database and applies pending migrations.
*
* - `postgres://…` connects to PostgreSQL (production).
* - `pglite://<dir>` uses embedded PostgreSQL stored in `<dir>` (local development, very small installs).
* - `memory://` uses a throwaway in-memory database (tests).
*/
export async function openDatabase(url: string): Promise<Database> {
if (/^postgres(ql)?:\/\//.test(url)) {
const pool = new pg.Pool({ connectionString: url })
const db = drizzlePg({ client: pool, schema, casing: 'snake_case' })
await migratePg(db, { migrationsFolder })
return { db: db as unknown as Db, close: () => pool.end() }
}
if (url !== 'memory://' && !url.startsWith('pglite://')) {
throw new Error(`Unsupported DATABASE_URL: expected postgres://, pglite:// or memory://`)
}
const dataDir = url === 'memory://' ? undefined : url.slice('pglite://'.length)
if (dataDir) mkdirSync(dataDir, { recursive: true })
const client = new PGlite(dataDir)
const db = drizzlePglite({ client, schema, casing: 'snake_case' })
await migratePglite(db, { migrationsFolder })
return { db: db as unknown as Db, close: () => client.close() }
}
/** True for a unique-constraint violation from either driver (Drizzle wraps driver errors in `cause`). */
export function isUniqueViolation(error: unknown): boolean {
let current: unknown = error
for (let depth = 0; current && typeof current === 'object' && depth < 5; depth++) {
if ((current as { code?: unknown }).code === '23505') return true
current = (current as { cause?: unknown }).cause
}
return false
}