import { type CommonReservedFields, type NoReservedFields, defaultGqlPermission, defaultPermission, } from "@tailor-platform/erp-kit/core"; import { db, type TailorAnyDBField } from "@tailor-platform/sdk"; import { NOTIFICATION_CHANNEL_IDS } from "./notificationChannel"; const builtins = { targetType: db .string() .description("Polymorphic discriminator of the bound source entity (e.g. PurchaseOrder)"), targetId: db.string().description("Polymorphic id of the bound source entity (no FK constraint)"), channelId: db .enum(NOTIFICATION_CHANNEL_IDS) .description("DESTINATION channel this binding routes to (e.g. SLACK, TEAMS)"), externalChannelRef: db .string() .description( "Opaque destination identifier the adapter posts to (e.g. Slack channel id C0123456789)", ), displayLabel: db .string({ optional: true }) .description("Human-readable destination label at bind time (e.g. #po-acme)"), isActive: db .bool() .description("Per-binding kill-switch; inactive bindings are skipped at dispatch"), }; type ReservedFields = keyof typeof builtins | CommonReservedFields; export interface CreateChannelRoutingBindingTypeParams> { fields?: NoReservedFields; } export function createChannelRoutingBindingType>( params: CreateChannelRoutingBindingTypeParams, ) { return db .table("ChannelRoutingBinding", { ...builtins, ...((params.fields ?? {}) as F), ...db.fields.timestamps(), }) .indexes({ // A source entity may hold multiple bindings on the same destination // channel as long as each routes to a distinct externalChannelRef // (e.g. two Slack channels via distinct rows); the ref is part of the key. fields: ["targetType", "targetId", "channelId", "externalChannelRef"], unique: true, name: "channel_routing_binding_unique_idx", }) .permission(defaultPermission) .gqlPermission(defaultGqlPermission); } export const channelRoutingBinding = createChannelRoutingBindingType({});