feat(db): phase 4 group 1 — lib/ settings + notifications to Drizzle
Convert lib/settings.ts, lib/notifications/{in-app,email,capa-escalation,
effectiveness-recheck}.ts from Supabase PostgREST to Drizzle asAdmin queries.
Drop supabase arg from all call sites in app/api/ and cron routes. Rewrite
notification unit tests to mock @/lib/db/with-user instead of SupabaseClient.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+30
-19
@@ -1,5 +1,8 @@
|
||||
import 'server-only'
|
||||
import { Resend } from 'resend'
|
||||
import { createClient } from '@/lib/supabase/server'
|
||||
import { asAdmin } from '@/lib/db/with-user'
|
||||
import { users, incidents, sites } from '@/lib/db/schema'
|
||||
import { and, eq, inArray } from 'drizzle-orm'
|
||||
import { newIncidentTemplate } from '@/lib/notifications/templates/new-incident'
|
||||
|
||||
export async function sendNewIncidentEmail(
|
||||
@@ -8,29 +11,37 @@ export async function sendNewIncidentEmail(
|
||||
reference_no: string,
|
||||
incidentType: string,
|
||||
): Promise<void> {
|
||||
const supabase = await createClient()
|
||||
|
||||
const { data: recipients } = await supabase
|
||||
.from('users')
|
||||
.select('email, name, role')
|
||||
.in('role', ['supervisor', 'hse'])
|
||||
.eq('site_id', siteId)
|
||||
const recipients = await asAdmin(db =>
|
||||
db.select({ email: users.email })
|
||||
.from(users)
|
||||
.where(and(
|
||||
inArray(users.role, ['supervisor', 'hse']),
|
||||
eq(users.siteId, siteId),
|
||||
))
|
||||
)
|
||||
|
||||
if (!recipients || recipients.length === 0) return
|
||||
|
||||
const to = recipients.map((r: { email: string }) => r.email).filter(Boolean)
|
||||
const to = recipients.map(r => r.email).filter(Boolean) as string[]
|
||||
if (to.length === 0) return
|
||||
|
||||
const { data: incident } = await supabase
|
||||
.from('incidents')
|
||||
.select('reported_at, sites (name), reporter:users!reported_by (name)')
|
||||
.eq('id', incidentId)
|
||||
.single()
|
||||
|
||||
const siteName = (incident?.sites as unknown as { name: string } | null)?.name ?? 'Unknown Site'
|
||||
const reporterName = (incident?.reporter as unknown as { name: string } | null)?.name ?? 'Unknown'
|
||||
const reportedAt = incident?.reported_at
|
||||
? new Date(incident.reported_at).toLocaleString('en-MY', { timeZone: 'Asia/Kuala_Lumpur' })
|
||||
const incidentRows = await asAdmin(db =>
|
||||
db.select({
|
||||
reportedAt: incidents.reportedAt,
|
||||
siteName: sites.name,
|
||||
reporterName: users.name,
|
||||
})
|
||||
.from(incidents)
|
||||
.leftJoin(sites, eq(incidents.siteId, sites.id))
|
||||
.leftJoin(users, eq(incidents.reportedBy, users.id))
|
||||
.where(eq(incidents.id, incidentId))
|
||||
.limit(1)
|
||||
)
|
||||
const incident = incidentRows[0]
|
||||
const siteName = incident?.siteName ?? 'Unknown Site'
|
||||
const reporterName = incident?.reporterName ?? 'Unknown'
|
||||
const reportedAt = incident?.reportedAt
|
||||
? new Date(incident.reportedAt).toLocaleString('en-MY', { timeZone: 'Asia/Kuala_Lumpur' })
|
||||
: '-'
|
||||
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL ?? 'http://localhost:3000'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user