{"version":3,"file":"notification-columns.mjs","names":[],"sources":["../../../../../../../notifications/src/migration/notification-columns.ts"],"sourcesContent":["/**\n * Column factory for the notifications table, driven by the model's\n * `columnMap`. The recipient / read-state / tenant columns take the NAMES the\n * model declares, so the table, the repository, and the model accessors all\n * agree by construction. The stable lexical columns (`type`, `title`, `body`,\n * `payload`, `idempotency_key`) keep fixed names.\n *\n * Read-state follows the map's presence rules (see `NotificationColumnMap`):\n * `readAt` → a nullable timestamp, `isRead` → an indexed boolean, both → both.\n *\n * Spread + extend for app-specific extras (FK references, composite indexes).\n *\n * @example\n *   import { Migration } from \"@warlock.js/cascade\";\n *   import { notificationColumns } from \"@warlock.js/notifications\";\n *   import { Notification } from \"../notification.model\";\n *\n *   export default Migration.create(Notification, notificationColumns(Notification));\n *\n * @example  // with extras (multi-tenant FK)\n *   export default Migration.create(Notification, {\n *     ...notificationColumns(Notification),\n *     organization_id: uuid().references(Organization.table).notNullable(),\n *   });\n */\nimport { boolCol, type ColumnMap, json, string, text, timestamp, uuid } from \"@warlock.js/cascade\";\nimport { type NotificationColumnMapHost, resolveColumnMap } from \"../in-app/column-map\";\n\n/**\n * Returns the column map for a notification table, named from the model's\n * `columnMap`. Without a model, falls back to the resolved defaults\n * (`user_id` recipient + `read_at` read-state).\n */\nexport function notificationColumns(model?: NotificationColumnMapHost): ColumnMap {\n  const { recipient, tenant, readAt, isRead } = resolveColumnMap(model?.columnMap);\n\n  const columns: ColumnMap = {\n    [recipient]: uuid().index().notNullable(),\n    type: string().index().notNullable(),\n    title: string().notNullable(),\n    body: text().nullable(),\n    payload: json().nullable(),\n  };\n\n  if (readAt) {\n    columns[readAt] = timestamp().nullable();\n  }\n\n  if (isRead) {\n    columns[isRead] = boolCol().default(false).index();\n  }\n\n  if (tenant) {\n    columns[tenant] = uuid().index().notNullable();\n  }\n\n  // Unique so a retried send can't insert a duplicate. Nullable: most rows\n  // have no key (NULLs are distinct in a unique index). `createFor` does\n  // find-or-create; this constraint is the race backstop.\n  columns.idempotency_key = string().nullable().unique();\n\n  return columns;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,SAAgB,oBAAoB,OAA8C;CAChF,MAAM,EAAE,WAAW,QAAQ,QAAQ,WAAW,iBAAiB,OAAO,SAAS;CAE/E,MAAM,UAAqB;GACxB,YAAY,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,YAAY;EACxC,MAAM,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,YAAY;EACnC,OAAO,OAAO,CAAC,CAAC,YAAY;EAC5B,MAAM,KAAK,CAAC,CAAC,SAAS;EACtB,SAAS,KAAK,CAAC,CAAC,SAAS;CAC3B;CAEA,IAAI,QACF,QAAQ,UAAU,UAAU,CAAC,CAAC,SAAS;CAGzC,IAAI,QACF,QAAQ,UAAU,QAAQ,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,MAAM;CAGnD,IAAI,QACF,QAAQ,UAAU,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,YAAY;CAM/C,QAAQ,kBAAkB,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO;CAErD,OAAO;AACT"}