import { ok, err, type CommandContext } from "@tailor-platform/erp-kit/core"; import type { Transaction } from "../generated/kysely-tailordb"; import { ForbiddenError } from "../lib/errors.generated"; export interface CreateNotificationSubscriptionInput { userId: string; sourceType: string; sourceId: string; } /** * Creates a NotificationSubscription for a (userId, sourceType, sourceId) triple. Idempotent on the unique triple; self-service only. */ export async function run( db: Transaction, input: CreateNotificationSubscriptionInput, ctx: CommandContext, ) { const { userId, sourceType, sourceId } = input; if (ctx.actorId !== userId) { return err(new ForbiddenError(userId)); } const existing = await db .selectFrom("NotificationSubscription") .selectAll() .where("userId", "=", userId) .where("sourceType", "=", sourceType) .where("sourceId", "=", sourceId) .forUpdate() .executeTakeFirst(); if (existing) { return ok({ subscription: existing }); } const inserted = await db .insertInto("NotificationSubscription") .values({ id: crypto.randomUUID(), userId, sourceType, sourceId, subscribedAt: new Date(), }) .returningAll() .executeTakeFirstOrThrow(); return ok({ subscription: inserted }); }