import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/core"; import type { Transaction } from "../generated/kysely-tailordb"; import { InvalidBodyError, ItemNotFoundError } from "../lib/errors.generated"; export interface CreatePipelineItemCommentInput { itemId: string; body: string; } const COMMENT_OWN_KEYS = new Set(["itemId", "body"]); export async function run>( db: Transaction, input: CreatePipelineItemCommentInput & CF, ctx: CommandContext, ) { // Consumer extension fields (declared via defineModule's pipelineItemComment.fields) // pass through to the insert untouched. const customFields: Record = {}; for (const [key, value] of Object.entries(input as Record)) { if (!COMMENT_OWN_KEYS.has(key)) { customFields[key] = value; } } const item = await db .selectFrom("PipelineItem") .selectAll() .where("id", "=", input.itemId) .executeTakeFirst(); if (!item) { return err(new ItemNotFoundError(input.itemId)); } if (!input.body.trim()) { return err(new InvalidBodyError(input.itemId)); } const comment = await db .insertInto("PipelineItemComment") .values({ ...customFields, itemId: input.itemId, authorUserId: ctx.actorId, body: input.body, createdAt: new Date(), }) .returningAll() .executeTakeFirstOrThrow(); return ok({ comment }); }