/** * trigger 存储 adapter —— Drizzle 只准出现在 adapter(编码规范 §5.3)。 */ import { eq } from 'drizzle-orm'; import type { TriggerConfig } from '@contracts'; import { triggerConfigSchema } from '@contracts'; import type { Db } from '@shared/db.ts'; import type { TriggerStore } from '../../port.ts'; import { triggerClaimTable, triggerTable } from './trigger-schema.ts'; type Row = typeof triggerTable.$inferSelect; function toConfig(row: Row): TriggerConfig { return triggerConfigSchema.parse({ id: row.id, name: row.name, enabled: row.enabled, processPackageId: row.processPackageId, mapping: row.mapping, spec: row.spec, }); } export function createTriggerStore(db: Db): TriggerStore { return { async list() { const rows = await db.select().from(triggerTable).orderBy(triggerTable.name); return rows.map(toConfig); }, async get(id) { const rows = await db.select().from(triggerTable).where(eq(triggerTable.id, id)).limit(1); return rows[0] === undefined ? undefined : toConfig(rows[0]); }, async upsert(config) { const values = { id: config.id, name: config.name, enabled: config.enabled, processPackageId: config.processPackageId, mapping: config.mapping, spec: config.spec, }; const [row] = await db .insert(triggerTable) .values(values) .onConflictDoUpdate({ target: triggerTable.id, set: values }) .returning(); if (row === undefined) throw new Error('触发器写入未返回行'); return toConfig(row); }, async setEnabled(id, enabled) { await db.update(triggerTable).set({ enabled }).where(eq(triggerTable.id, id)); }, async remove(id) { await db.delete(triggerTable).where(eq(triggerTable.id, id)); }, async claim(key) { const inserted = await db .insert(triggerClaimTable) .values({ key }) .onConflictDoNothing() .returning({ key: triggerClaimTable.key }); return inserted.length > 0; }, async lastFiredAt(id) { const rows = await db.select({ at: triggerTable.lastFiredAt }).from(triggerTable).where(eq(triggerTable.id, id)).limit(1); return rows[0]?.at ?? undefined; }, async markFired(id, at) { await db.update(triggerTable).set({ lastFiredAt: at }).where(eq(triggerTable.id, id)); }, }; }