@warlock.js/notifications 5.30.0 → 5.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (421) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/cjs/index.cjs +2 -2
  3. package/cjs/index.cjs.map +1 -1
  4. package/esm/channels/database-channel.d.mts +2 -3
  5. package/esm/channels/database-channel.d.mts.map +1 -1
  6. package/esm/channels/index.d.mts +2 -1
  7. package/esm/channels/index.mjs +1 -1
  8. package/esm/channels/mail-channel.d.mts +6 -4
  9. package/esm/channels/mail-channel.d.mts.map +1 -1
  10. package/esm/config.d.mts +13 -9
  11. package/esm/config.d.mts.map +1 -1
  12. package/esm/config.mjs.map +1 -1
  13. package/esm/contracts/channel.contract.d.mts +1 -3
  14. package/esm/contracts/channel.contract.d.mts.map +1 -1
  15. package/esm/contracts/index.d.mts +2 -1
  16. package/esm/contracts/notification.contract.d.mts +1 -3
  17. package/esm/contracts/notification.contract.d.mts.map +1 -1
  18. package/esm/contracts/preference-provider.contract.d.mts +1 -3
  19. package/esm/contracts/preference-provider.contract.d.mts.map +1 -1
  20. package/esm/contracts/queue-dispatcher.contract.d.mts +1 -3
  21. package/esm/contracts/queue-dispatcher.contract.d.mts.map +1 -1
  22. package/esm/contracts/rate-limiter.contract.d.mts +1 -3
  23. package/esm/contracts/rate-limiter.contract.d.mts.map +1 -1
  24. package/esm/dispatch/define-channel.d.mts +2 -2
  25. package/esm/dispatch/define-channel.d.mts.map +1 -1
  26. package/esm/dispatch/define-notification.d.mts +5 -6
  27. package/esm/dispatch/define-notification.d.mts.map +1 -1
  28. package/esm/dispatch/define-notification.mjs.map +1 -1
  29. package/esm/dispatch/index.d.mts +2 -1
  30. package/esm/dispatch/index.mjs +1 -1
  31. package/esm/dispatch/notifications-event-bus.d.mts +2 -3
  32. package/esm/dispatch/notifications-event-bus.d.mts.map +1 -1
  33. package/esm/dispatch/notify.d.mts +3 -5
  34. package/esm/dispatch/notify.d.mts.map +1 -1
  35. package/esm/dispatch/notify.mjs.map +1 -1
  36. package/esm/errors.d.mts +5 -6
  37. package/esm/errors.d.mts.map +1 -1
  38. package/esm/in-app/base-notifications-repository.d.mts +6 -6
  39. package/esm/in-app/base-notifications-repository.d.mts.map +1 -1
  40. package/esm/in-app/base-notifications-repository.mjs +1 -1
  41. package/esm/in-app/base-notifications-repository.mjs.map +1 -1
  42. package/esm/in-app/column-map.d.mts +11 -8
  43. package/esm/in-app/column-map.d.mts.map +1 -1
  44. package/esm/in-app/database-notification.d.mts +2 -3
  45. package/esm/in-app/database-notification.d.mts.map +1 -1
  46. package/esm/in-app/in-app.d.mts +6 -5
  47. package/esm/in-app/in-app.d.mts.map +1 -1
  48. package/esm/in-app/index.d.mts +2 -1
  49. package/esm/in-app/index.mjs +1 -1
  50. package/esm/index.d.mts +6 -0
  51. package/esm/migration/index.d.mts +2 -1
  52. package/esm/migration/index.mjs +1 -1
  53. package/esm/migration/notification-columns.d.mts +6 -7
  54. package/esm/migration/notification-columns.d.mts.map +1 -1
  55. package/esm/migration/notification-columns.mjs.map +1 -1
  56. package/esm/queue/bullmq-queue.d.mts +9 -7
  57. package/esm/queue/bullmq-queue.d.mts.map +1 -1
  58. package/esm/queue/bullmq-queue.mjs.map +1 -1
  59. package/esm/queue/herald-queue.d.mts +6 -4
  60. package/esm/queue/herald-queue.d.mts.map +1 -1
  61. package/esm/queue/index.d.mts +2 -1
  62. package/esm/queue/index.mjs +1 -1
  63. package/esm/queue/load-herald.d.mts +1 -2
  64. package/esm/queue/load-herald.d.mts.map +1 -1
  65. package/esm/queue/load-herald.mjs +1 -1
  66. package/esm/queue/load-queue.d.mts +2 -3
  67. package/esm/queue/load-queue.d.mts.map +1 -1
  68. package/esm/queue/notifications-worker.d.mts +5 -4
  69. package/esm/queue/notifications-worker.d.mts.map +1 -1
  70. package/esm/queue/notifications-worker.mjs.map +1 -1
  71. package/esm/queue/queue-package-not-installed.error.d.mts +1 -2
  72. package/esm/queue/queue-package-not-installed.error.d.mts.map +1 -1
  73. package/esm/types.d.mts +22 -18
  74. package/esm/types.d.mts.map +1 -1
  75. package/llms-full.txt +89 -81
  76. package/package.json +10 -9
  77. package/skills/configure-notifications/SKILL.md +7 -7
  78. package/skills/define-channel/SKILL.md +9 -7
  79. package/skills/define-notification/SKILL.md +22 -25
  80. package/skills/index.md +4 -1
  81. package/skills/notifications-basics/SKILL.md +12 -12
  82. package/skills/observe-notifications/SKILL.md +14 -10
  83. package/skills/send-ad-hoc/SKILL.md +9 -9
  84. package/skills/use-in-app/SKILL.md +6 -4
  85. package/skills/write-notification-migration/SKILL.md +10 -7
  86. package/cjs/channel_api-C5ZZDkgQ.cjs +0 -7463
  87. package/cjs/channel_api-C5ZZDkgQ.cjs.map +0 -1
  88. package/cjs/chunk-fl3r8ClO.cjs +0 -41
  89. package/cjs/rabbitmq-driver-BFoWr21L.cjs +0 -3
  90. package/cjs/src-eu2jxS21.cjs +0 -11190
  91. package/cjs/src-eu2jxS21.cjs.map +0 -1
  92. package/esm/_virtual/_rolldown/runtime.mjs +0 -32
  93. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/Random/_internal.mjs +0 -6
  94. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/Random/_internal.mjs.map +0 -1
  95. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/Random/bool.mjs +0 -3
  96. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/Random/color.mjs +0 -3
  97. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/Random/date.mjs +0 -3
  98. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/Random/float.mjs +0 -3
  99. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/Random/id.mjs +0 -3
  100. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/Random/int.mjs +0 -3
  101. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/Random/nanoid.mjs +0 -3
  102. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/Random/pick.mjs +0 -3
  103. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/Random/random.mjs +0 -16
  104. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/Random/sample.mjs +0 -3
  105. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/Random/string.mjs +0 -3
  106. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/Random/token.mjs +0 -3
  107. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/Random/uuid.mjs +0 -3
  108. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/Random/weighted.mjs +0 -3
  109. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/async/retry.mjs +0 -3
  110. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/index.mjs +0 -24
  111. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/mixed/clone/clone.mjs +0 -82
  112. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/mixed/clone/clone.mjs.map +0 -1
  113. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/number/round.mjs +0 -17
  114. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/number/round.mjs.map +0 -1
  115. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/object/except.mjs +0 -13
  116. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/object/except.mjs.map +0 -1
  117. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/object/get.mjs +0 -18
  118. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/object/get.mjs.map +0 -1
  119. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/object/omit.mjs +0 -17
  120. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/object/omit.mjs.map +0 -1
  121. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/object/unset.mjs +0 -30
  122. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/object/unset.mjs.map +0 -1
  123. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/string/capitalize.mjs +0 -19
  124. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/string/capitalize.mjs.map +0 -1
  125. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/string/ltrim.mjs +0 -18
  126. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/string/ltrim.mjs.map +0 -1
  127. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/string/readMoreChars.mjs +0 -14
  128. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/string/readMoreChars.mjs.map +0 -1
  129. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/string/rtrim.mjs +0 -18
  130. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/string/rtrim.mjs.map +0 -1
  131. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/string/toCamelCase.mjs +0 -22
  132. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/string/toCamelCase.mjs.map +0 -1
  133. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/string/toKebabCase.mjs +0 -17
  134. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/string/toKebabCase.mjs.map +0 -1
  135. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/string/toSnakeCase.mjs +0 -21
  136. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/string/toSnakeCase.mjs.map +0 -1
  137. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/string/toStudlyCase.mjs +0 -21
  138. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/string/toStudlyCase.mjs.map +0 -1
  139. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/string/trim.mjs +0 -20
  140. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/string/trim.mjs.map +0 -1
  141. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/string/ucfirst.mjs +0 -15
  142. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/string/ucfirst.mjs.map +0 -1
  143. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/string/words.mjs +0 -25
  144. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/string/words.mjs.map +0 -1
  145. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/utils/escapeRegex.mjs +0 -11
  146. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/utils/escapeRegex.mjs.map +0 -1
  147. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/utils/lazy.mjs +0 -100
  148. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/utils/lazy.mjs.map +0 -1
  149. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/utils/tap.mjs +0 -27
  150. package/esm/node_modules/.pnpm/@mongez_reinforcements@4.0.2/node_modules/@mongez/reinforcements/esm/utils/tap.mjs.map +0 -1
  151. package/esm/node_modules/.pnpm/@mongez_supportive-is@3.0.0/node_modules/@mongez/supportive-is/esm/index.mjs +0 -358
  152. package/esm/node_modules/.pnpm/@mongez_supportive-is@3.0.0/node_modules/@mongez/supportive-is/esm/index.mjs.map +0 -1
  153. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/channel_api.mjs +0 -28
  154. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/channel_api.mjs.map +0 -1
  155. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/api_args.mjs +0 -241
  156. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/api_args.mjs.map +0 -1
  157. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/bitset.mjs +0 -130
  158. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/bitset.mjs.map +0 -1
  159. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/channel.mjs +0 -302
  160. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/channel.mjs.map +0 -1
  161. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/channel_model.mjs +0 -206
  162. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/channel_model.mjs.map +0 -1
  163. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/codec.mjs +0 -273
  164. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/codec.mjs.map +0 -1
  165. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/connect.mjs +0 -143
  166. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/connect.mjs.map +0 -1
  167. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/connection.mjs +0 -416
  168. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/connection.mjs.map +0 -1
  169. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/credentials.mjs +0 -50
  170. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/credentials.mjs.map +0 -1
  171. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/defs.mjs +0 -4600
  172. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/defs.mjs.map +0 -1
  173. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/error.mjs +0 -29
  174. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/error.mjs.map +0 -1
  175. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/format.mjs +0 -28
  176. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/format.mjs.map +0 -1
  177. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/frame.mjs +0 -130
  178. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/frame.mjs.map +0 -1
  179. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/heartbeat.mjs +0 -40
  180. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/heartbeat.mjs.map +0 -1
  181. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/mux.mjs +0 -86
  182. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/mux.mjs.map +0 -1
  183. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/package.mjs +0 -41
  184. package/esm/node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/package.mjs.map +0 -1
  185. package/esm/node_modules/.pnpm/buffer-more-ints@1.0.0/node_modules/buffer-more-ints/buffer-more-ints.mjs +0 -360
  186. package/esm/node_modules/.pnpm/buffer-more-ints@1.0.0/node_modules/buffer-more-ints/buffer-more-ints.mjs.map +0 -1
  187. package/esm/node_modules/.pnpm/dayjs@1.11.23/node_modules/dayjs/dayjs.min.mjs +0 -305
  188. package/esm/node_modules/.pnpm/dayjs@1.11.23/node_modules/dayjs/dayjs.min.mjs.map +0 -1
  189. package/esm/node_modules/.pnpm/querystringify@2.2.0/node_modules/querystringify/index.mjs +0 -80
  190. package/esm/node_modules/.pnpm/querystringify@2.2.0/node_modules/querystringify/index.mjs.map +0 -1
  191. package/esm/node_modules/.pnpm/requires-port@1.0.0/node_modules/requires-port/index.mjs +0 -35
  192. package/esm/node_modules/.pnpm/requires-port@1.0.0/node_modules/requires-port/index.mjs.map +0 -1
  193. package/esm/node_modules/.pnpm/url-parse@1.5.10/node_modules/url-parse/index.mjs +0 -388
  194. package/esm/node_modules/.pnpm/url-parse@1.5.10/node_modules/url-parse/index.mjs.map +0 -1
  195. package/esm/packages/herald/src/communicators/broker-registry.mjs +0 -204
  196. package/esm/packages/herald/src/communicators/broker-registry.mjs.map +0 -1
  197. package/esm/packages/herald/src/communicators/broker.mjs +0 -110
  198. package/esm/packages/herald/src/communicators/broker.mjs.map +0 -1
  199. package/esm/packages/herald/src/communicators/index.mjs +0 -4
  200. package/esm/packages/herald/src/decorators/consumable.mjs +0 -36
  201. package/esm/packages/herald/src/decorators/consumable.mjs.map +0 -1
  202. package/esm/packages/herald/src/decorators/index.mjs +0 -3
  203. package/esm/packages/herald/src/drivers/index.mjs +0 -5
  204. package/esm/packages/herald/src/drivers/rabbitmq/index.mjs +0 -4
  205. package/esm/packages/herald/src/drivers/rabbitmq/rabbitmq-channel.mjs +0 -403
  206. package/esm/packages/herald/src/drivers/rabbitmq/rabbitmq-channel.mjs.map +0 -1
  207. package/esm/packages/herald/src/drivers/rabbitmq/rabbitmq-driver.mjs +0 -303
  208. package/esm/packages/herald/src/drivers/rabbitmq/rabbitmq-driver.mjs.map +0 -1
  209. package/esm/packages/herald/src/index.mjs +0 -16
  210. package/esm/packages/herald/src/message-managers/event-consumer.mjs +0 -76
  211. package/esm/packages/herald/src/message-managers/event-consumer.mjs.map +0 -1
  212. package/esm/packages/herald/src/message-managers/event-message.mjs +0 -85
  213. package/esm/packages/herald/src/message-managers/event-message.mjs.map +0 -1
  214. package/esm/packages/herald/src/message-managers/index.mjs +0 -4
  215. package/esm/packages/herald/src/message-managers/prepare-consumer-subscription.mjs +0 -42
  216. package/esm/packages/herald/src/message-managers/prepare-consumer-subscription.mjs.map +0 -1
  217. package/esm/packages/herald/src/use-case-broadcast.mjs +0 -30
  218. package/esm/packages/herald/src/use-case-broadcast.mjs.map +0 -1
  219. package/esm/packages/herald/src/utils/connect-to-broker.mjs +0 -168
  220. package/esm/packages/herald/src/utils/connect-to-broker.mjs.map +0 -1
  221. package/esm/packages/herald/src/utils/index.mjs +0 -3
  222. package/esm/packages/seal/src/config.mjs +0 -15
  223. package/esm/packages/seal/src/config.mjs.map +0 -1
  224. package/esm/packages/seal/src/factory/index.mjs +0 -4
  225. package/esm/packages/seal/src/factory/validate.mjs +0 -42
  226. package/esm/packages/seal/src/factory/validate.mjs.map +0 -1
  227. package/esm/packages/seal/src/factory/validators.mjs +0 -133
  228. package/esm/packages/seal/src/factory/validators.mjs.map +0 -1
  229. package/esm/packages/seal/src/helpers/date-helpers.mjs +0 -24
  230. package/esm/packages/seal/src/helpers/date-helpers.mjs.map +0 -1
  231. package/esm/packages/seal/src/helpers/get-field-value.mjs +0 -46
  232. package/esm/packages/seal/src/helpers/get-field-value.mjs.map +0 -1
  233. package/esm/packages/seal/src/helpers/index.mjs +0 -6
  234. package/esm/packages/seal/src/helpers/is-empty-value.mjs +0 -10
  235. package/esm/packages/seal/src/helpers/is-empty-value.mjs.map +0 -1
  236. package/esm/packages/seal/src/helpers/path-helpers.mjs +0 -12
  237. package/esm/packages/seal/src/helpers/path-helpers.mjs.map +0 -1
  238. package/esm/packages/seal/src/helpers/validation-helpers.mjs +0 -78
  239. package/esm/packages/seal/src/helpers/validation-helpers.mjs.map +0 -1
  240. package/esm/packages/seal/src/index.mjs +0 -88
  241. package/esm/packages/seal/src/mutators/array-mutators.mjs +0 -32
  242. package/esm/packages/seal/src/mutators/array-mutators.mjs.map +0 -1
  243. package/esm/packages/seal/src/mutators/boolean-mutators.mjs +0 -40
  244. package/esm/packages/seal/src/mutators/boolean-mutators.mjs.map +0 -1
  245. package/esm/packages/seal/src/mutators/date-mutators.mjs +0 -94
  246. package/esm/packages/seal/src/mutators/date-mutators.mjs.map +0 -1
  247. package/esm/packages/seal/src/mutators/index.mjs +0 -9
  248. package/esm/packages/seal/src/mutators/number-mutators.mjs +0 -52
  249. package/esm/packages/seal/src/mutators/number-mutators.mjs.map +0 -1
  250. package/esm/packages/seal/src/mutators/object-mutators.mjs +0 -30
  251. package/esm/packages/seal/src/mutators/object-mutators.mjs.map +0 -1
  252. package/esm/packages/seal/src/mutators/scalar-mutators.mjs +0 -9
  253. package/esm/packages/seal/src/mutators/scalar-mutators.mjs.map +0 -1
  254. package/esm/packages/seal/src/mutators/string-mutators.mjs +0 -186
  255. package/esm/packages/seal/src/mutators/string-mutators.mjs.map +0 -1
  256. package/esm/packages/seal/src/object.mjs +0 -13
  257. package/esm/packages/seal/src/object.mjs.map +0 -1
  258. package/esm/packages/seal/src/rules/array/array-rules.mjs +0 -41
  259. package/esm/packages/seal/src/rules/array/array-rules.mjs.map +0 -1
  260. package/esm/packages/seal/src/rules/array/index.mjs +0 -3
  261. package/esm/packages/seal/src/rules/color/color-rules.mjs +0 -104
  262. package/esm/packages/seal/src/rules/color/color-rules.mjs.map +0 -1
  263. package/esm/packages/seal/src/rules/color/index.mjs +0 -3
  264. package/esm/packages/seal/src/rules/common/enum.mjs +0 -77
  265. package/esm/packages/seal/src/rules/common/enum.mjs.map +0 -1
  266. package/esm/packages/seal/src/rules/common/equals-field-rules.mjs +0 -42
  267. package/esm/packages/seal/src/rules/common/equals-field-rules.mjs.map +0 -1
  268. package/esm/packages/seal/src/rules/common/index.mjs +0 -8
  269. package/esm/packages/seal/src/rules/common/instanceof.mjs +0 -23
  270. package/esm/packages/seal/src/rules/common/instanceof.mjs.map +0 -1
  271. package/esm/packages/seal/src/rules/common/literal.mjs +0 -31
  272. package/esm/packages/seal/src/rules/common/literal.mjs.map +0 -1
  273. package/esm/packages/seal/src/rules/common/type-rules.mjs +0 -97
  274. package/esm/packages/seal/src/rules/common/type-rules.mjs.map +0 -1
  275. package/esm/packages/seal/src/rules/common/unknown-key.mjs +0 -25
  276. package/esm/packages/seal/src/rules/common/unknown-key.mjs.map +0 -1
  277. package/esm/packages/seal/src/rules/conditional/forbidden-if-rules.mjs +0 -116
  278. package/esm/packages/seal/src/rules/conditional/forbidden-if-rules.mjs.map +0 -1
  279. package/esm/packages/seal/src/rules/conditional/index.mjs +0 -12
  280. package/esm/packages/seal/src/rules/conditional/present-if-rules.mjs +0 -97
  281. package/esm/packages/seal/src/rules/conditional/present-if-rules.mjs.map +0 -1
  282. package/esm/packages/seal/src/rules/conditional/present-unless-rules.mjs +0 -30
  283. package/esm/packages/seal/src/rules/conditional/present-unless-rules.mjs.map +0 -1
  284. package/esm/packages/seal/src/rules/conditional/present-with-rules.mjs +0 -76
  285. package/esm/packages/seal/src/rules/conditional/present-with-rules.mjs.map +0 -1
  286. package/esm/packages/seal/src/rules/conditional/present-without-rules.mjs +0 -76
  287. package/esm/packages/seal/src/rules/conditional/present-without-rules.mjs.map +0 -1
  288. package/esm/packages/seal/src/rules/conditional/required-if-rules.mjs +0 -204
  289. package/esm/packages/seal/src/rules/conditional/required-if-rules.mjs.map +0 -1
  290. package/esm/packages/seal/src/rules/conditional/required-unless-rules.mjs +0 -31
  291. package/esm/packages/seal/src/rules/conditional/required-unless-rules.mjs.map +0 -1
  292. package/esm/packages/seal/src/rules/conditional/required-when-rule.mjs +0 -32
  293. package/esm/packages/seal/src/rules/conditional/required-when-rule.mjs.map +0 -1
  294. package/esm/packages/seal/src/rules/conditional/required-with-rules.mjs +0 -67
  295. package/esm/packages/seal/src/rules/conditional/required-with-rules.mjs.map +0 -1
  296. package/esm/packages/seal/src/rules/conditional/required-without-rules.mjs +0 -67
  297. package/esm/packages/seal/src/rules/conditional/required-without-rules.mjs.map +0 -1
  298. package/esm/packages/seal/src/rules/core/equal.mjs +0 -22
  299. package/esm/packages/seal/src/rules/core/equal.mjs.map +0 -1
  300. package/esm/packages/seal/src/rules/core/forbidden.mjs +0 -20
  301. package/esm/packages/seal/src/rules/core/forbidden.mjs.map +0 -1
  302. package/esm/packages/seal/src/rules/core/index.mjs +0 -7
  303. package/esm/packages/seal/src/rules/core/required.mjs +0 -36
  304. package/esm/packages/seal/src/rules/core/required.mjs.map +0 -1
  305. package/esm/packages/seal/src/rules/core/union.mjs +0 -32
  306. package/esm/packages/seal/src/rules/core/union.mjs.map +0 -1
  307. package/esm/packages/seal/src/rules/core/when.mjs +0 -37
  308. package/esm/packages/seal/src/rules/core/when.mjs.map +0 -1
  309. package/esm/packages/seal/src/rules/date/date-comparison-rules.mjs +0 -78
  310. package/esm/packages/seal/src/rules/date/date-comparison-rules.mjs.map +0 -1
  311. package/esm/packages/seal/src/rules/date/date-day-rules.mjs +0 -49
  312. package/esm/packages/seal/src/rules/date/date-day-rules.mjs.map +0 -1
  313. package/esm/packages/seal/src/rules/date/date-field-comparison-rules.mjs +0 -82
  314. package/esm/packages/seal/src/rules/date/date-field-comparison-rules.mjs.map +0 -1
  315. package/esm/packages/seal/src/rules/date/date-period-rules.mjs +0 -401
  316. package/esm/packages/seal/src/rules/date/date-period-rules.mjs.map +0 -1
  317. package/esm/packages/seal/src/rules/date/date-relative-rules.mjs +0 -55
  318. package/esm/packages/seal/src/rules/date/date-relative-rules.mjs.map +0 -1
  319. package/esm/packages/seal/src/rules/date/date-special-rules.mjs +0 -58
  320. package/esm/packages/seal/src/rules/date/date-special-rules.mjs.map +0 -1
  321. package/esm/packages/seal/src/rules/date/date.mjs +0 -235
  322. package/esm/packages/seal/src/rules/date/date.mjs.map +0 -1
  323. package/esm/packages/seal/src/rules/date/index.mjs +0 -9
  324. package/esm/packages/seal/src/rules/file/dimensions.mjs +0 -3
  325. package/esm/packages/seal/src/rules/file/file-size.mjs +0 -3
  326. package/esm/packages/seal/src/rules/file/index.mjs +0 -4
  327. package/esm/packages/seal/src/rules/index.mjs +0 -54
  328. package/esm/packages/seal/src/rules/length/index.mjs +0 -3
  329. package/esm/packages/seal/src/rules/length/length-rules.mjs +0 -98
  330. package/esm/packages/seal/src/rules/length/length-rules.mjs.map +0 -1
  331. package/esm/packages/seal/src/rules/number/index.mjs +0 -3
  332. package/esm/packages/seal/src/rules/number/number-rules.mjs +0 -197
  333. package/esm/packages/seal/src/rules/number/number-rules.mjs.map +0 -1
  334. package/esm/packages/seal/src/rules/scalar/accepted-rule.mjs +0 -123
  335. package/esm/packages/seal/src/rules/scalar/accepted-rule.mjs.map +0 -1
  336. package/esm/packages/seal/src/rules/scalar/declined-rule.mjs +0 -123
  337. package/esm/packages/seal/src/rules/scalar/declined-rule.mjs.map +0 -1
  338. package/esm/packages/seal/src/rules/scalar/index.mjs +0 -4
  339. package/esm/packages/seal/src/rules/string/alpha.mjs +0 -41
  340. package/esm/packages/seal/src/rules/string/alpha.mjs.map +0 -1
  341. package/esm/packages/seal/src/rules/string/credit-card.mjs +0 -32
  342. package/esm/packages/seal/src/rules/string/credit-card.mjs.map +0 -1
  343. package/esm/packages/seal/src/rules/string/email.mjs +0 -20
  344. package/esm/packages/seal/src/rules/string/email.mjs.map +0 -1
  345. package/esm/packages/seal/src/rules/string/id-formats.mjs +0 -104
  346. package/esm/packages/seal/src/rules/string/id-formats.mjs.map +0 -1
  347. package/esm/packages/seal/src/rules/string/index.mjs +0 -13
  348. package/esm/packages/seal/src/rules/string/ip.mjs +0 -66
  349. package/esm/packages/seal/src/rules/string/ip.mjs.map +0 -1
  350. package/esm/packages/seal/src/rules/string/matches.mjs +0 -4
  351. package/esm/packages/seal/src/rules/string/pattern.mjs +0 -20
  352. package/esm/packages/seal/src/rules/string/pattern.mjs.map +0 -1
  353. package/esm/packages/seal/src/rules/string/string-comparison.mjs +0 -56
  354. package/esm/packages/seal/src/rules/string/string-comparison.mjs.map +0 -1
  355. package/esm/packages/seal/src/rules/string/strong-password-rule.mjs +0 -31
  356. package/esm/packages/seal/src/rules/string/strong-password-rule.mjs.map +0 -1
  357. package/esm/packages/seal/src/rules/string/url.mjs +0 -23
  358. package/esm/packages/seal/src/rules/string/url.mjs.map +0 -1
  359. package/esm/packages/seal/src/rules/string/without-whitespace.mjs +0 -19
  360. package/esm/packages/seal/src/rules/string/without-whitespace.mjs.map +0 -1
  361. package/esm/packages/seal/src/standard-schema/json-schema.mjs +0 -81
  362. package/esm/packages/seal/src/standard-schema/json-schema.mjs.map +0 -1
  363. package/esm/packages/seal/src/standard-schema/map-result.mjs +0 -26
  364. package/esm/packages/seal/src/standard-schema/map-result.mjs.map +0 -1
  365. package/esm/packages/seal/src/string.mjs +0 -13
  366. package/esm/packages/seal/src/string.mjs.map +0 -1
  367. package/esm/packages/seal/src/types/date-types.mjs +0 -17
  368. package/esm/packages/seal/src/types/date-types.mjs.map +0 -1
  369. package/esm/packages/seal/src/validators/any-validator.mjs +0 -38
  370. package/esm/packages/seal/src/validators/any-validator.mjs.map +0 -1
  371. package/esm/packages/seal/src/validators/array-validator.mjs +0 -186
  372. package/esm/packages/seal/src/validators/array-validator.mjs.map +0 -1
  373. package/esm/packages/seal/src/validators/base-validator.mjs +0 -720
  374. package/esm/packages/seal/src/validators/base-validator.mjs.map +0 -1
  375. package/esm/packages/seal/src/validators/boolean-validator.mjs +0 -175
  376. package/esm/packages/seal/src/validators/boolean-validator.mjs.map +0 -1
  377. package/esm/packages/seal/src/validators/computed-validator.mjs +0 -118
  378. package/esm/packages/seal/src/validators/computed-validator.mjs.map +0 -1
  379. package/esm/packages/seal/src/validators/date-validator.mjs +0 -640
  380. package/esm/packages/seal/src/validators/date-validator.mjs.map +0 -1
  381. package/esm/packages/seal/src/validators/discriminated-union-validator.mjs +0 -138
  382. package/esm/packages/seal/src/validators/discriminated-union-validator.mjs.map +0 -1
  383. package/esm/packages/seal/src/validators/float-validator.mjs +0 -18
  384. package/esm/packages/seal/src/validators/float-validator.mjs.map +0 -1
  385. package/esm/packages/seal/src/validators/index.mjs +0 -28
  386. package/esm/packages/seal/src/validators/instanceof-validator.mjs +0 -64
  387. package/esm/packages/seal/src/validators/instanceof-validator.mjs.map +0 -1
  388. package/esm/packages/seal/src/validators/int-validator.mjs +0 -30
  389. package/esm/packages/seal/src/validators/int-validator.mjs.map +0 -1
  390. package/esm/packages/seal/src/validators/lazy-validator.mjs +0 -87
  391. package/esm/packages/seal/src/validators/lazy-validator.mjs.map +0 -1
  392. package/esm/packages/seal/src/validators/literal-validator.mjs +0 -72
  393. package/esm/packages/seal/src/validators/literal-validator.mjs.map +0 -1
  394. package/esm/packages/seal/src/validators/managed-validator.mjs +0 -39
  395. package/esm/packages/seal/src/validators/managed-validator.mjs.map +0 -1
  396. package/esm/packages/seal/src/validators/methods/equality-conditional-methods.mjs +0 -129
  397. package/esm/packages/seal/src/validators/methods/equality-conditional-methods.mjs.map +0 -1
  398. package/esm/packages/seal/src/validators/methods/forbidden-methods.mjs +0 -131
  399. package/esm/packages/seal/src/validators/methods/forbidden-methods.mjs.map +0 -1
  400. package/esm/packages/seal/src/validators/methods/present-methods.mjs +0 -235
  401. package/esm/packages/seal/src/validators/methods/present-methods.mjs.map +0 -1
  402. package/esm/packages/seal/src/validators/methods/required-methods.mjs +0 -347
  403. package/esm/packages/seal/src/validators/methods/required-methods.mjs.map +0 -1
  404. package/esm/packages/seal/src/validators/number-validator.mjs +0 -331
  405. package/esm/packages/seal/src/validators/number-validator.mjs.map +0 -1
  406. package/esm/packages/seal/src/validators/numeric-validator.mjs +0 -27
  407. package/esm/packages/seal/src/validators/numeric-validator.mjs.map +0 -1
  408. package/esm/packages/seal/src/validators/object-validator.mjs +0 -445
  409. package/esm/packages/seal/src/validators/object-validator.mjs.map +0 -1
  410. package/esm/packages/seal/src/validators/primitive-validator.mjs +0 -88
  411. package/esm/packages/seal/src/validators/primitive-validator.mjs.map +0 -1
  412. package/esm/packages/seal/src/validators/record-validator.mjs +0 -112
  413. package/esm/packages/seal/src/validators/record-validator.mjs.map +0 -1
  414. package/esm/packages/seal/src/validators/scalar-validator.mjs +0 -173
  415. package/esm/packages/seal/src/validators/scalar-validator.mjs.map +0 -1
  416. package/esm/packages/seal/src/validators/string-validator.mjs +0 -459
  417. package/esm/packages/seal/src/validators/string-validator.mjs.map +0 -1
  418. package/esm/packages/seal/src/validators/tuple-validator.mjs +0 -134
  419. package/esm/packages/seal/src/validators/tuple-validator.mjs.map +0 -1
  420. package/esm/packages/seal/src/validators/union-validator.mjs +0 -66
  421. package/esm/packages/seal/src/validators/union-validator.mjs.map +0 -1
package/llms-full.txt CHANGED
@@ -25,7 +25,7 @@ import { Notification } from "app/notifications/models/notification/notification
25
25
 
26
26
  const config: NotificationConfig = {
27
27
  channels: {
28
- mail: mailChannel({ from: "no-reply@store.com" }),
28
+ mail: mailChannel({ from: "no-reply@store.com" }),
29
29
  database: inApp.configure({ model: Notification }),
30
30
  },
31
31
  };
@@ -40,17 +40,17 @@ The `database` channel is returned by `inApp.configure({ model | repository })`
40
40
  ```ts
41
41
  const config: NotificationConfig = {
42
42
  channels: {
43
- mail: mailChannel({ from }),
43
+ mail: mailChannel({ from }),
44
44
  database: inApp.configure({ model: Notification }),
45
45
 
46
46
  // custom channels
47
- discord: discordChannel(), // defineChannel + declare module
47
+ discord: discordChannel(), // defineChannel + declare module
48
48
  },
49
49
 
50
50
  // optional gates — both app-owned; package ships no defaults
51
- preferences: userPreferences, // drops channels recipient muted
52
- rateLimit, // drops channels over budget
53
- queue: heraldQueue(), // backs `.queue()` (needs @warlock.js/herald)
51
+ preferences: userPreferences, // drops channels recipient muted
52
+ rateLimit, // drops channels over budget
53
+ queue: heraldQueue(), // backs `.queue()` (needs @warlock.js/herald)
54
54
  };
55
55
 
56
56
  export default config;
@@ -124,7 +124,7 @@ Dropped channels fire a `skipped` event with reason `"rate-limit"`. `force` does
124
124
  ```ts
125
125
  import { getNotificationConfig } from "@warlock.js/notifications";
126
126
 
127
- const cfg = getNotificationConfig(); // throws NotificationsNotConfiguredError if unset
127
+ const cfg = getNotificationConfig(); // throws NotificationsNotConfiguredError if unset
128
128
  ```
129
129
 
130
130
  ## Tests
@@ -200,12 +200,12 @@ Now `notify.discord(user, { content: "🎉" })` works, and `discord:` is a valid
200
200
 
201
201
  ## `route` resolution
202
202
 
203
- | What `route` returns | Effect |
204
- |---|---|
205
- | `string` | Used directly as the address (`"user@example.com"`, webhook URL). |
206
- | `{ id: Id }` | The recipient's storage id — for database/internal channels. |
207
- | `undefined` | Dispatcher falls back to `{ id: notifiable.id }`. |
208
- | `route` omitted | Same as returning `undefined` — `{ id }` fallback. |
203
+ | What `route` returns | Effect |
204
+ | -------------------- | ----------------------------------------------------------------- |
205
+ | `string` | Used directly as the address (`"user@example.com"`, webhook URL). |
206
+ | `{ id: Id }` | The recipient's storage id — for database/internal channels. |
207
+ | `undefined` | Dispatcher falls back to `{ id: notifiable.id }`. |
208
+ | `route` omitted | Same as returning `undefined` — `{ id }` fallback. |
209
209
 
210
210
  For raw-target ad-hoc sends (`notify.discord("https://hooks.../foo", payload)`), the raw string wins over `route()`.
211
211
 
@@ -233,7 +233,9 @@ import type { WebClient } from "@slack/web-api";
233
233
  let Slack: typeof import("@slack/web-api");
234
234
  let isModuleExists: boolean | null = null;
235
235
 
236
- async function loadSlack() { /* try/catch await import; set flag */ }
236
+ async function loadSlack() {
237
+ /* try/catch await import; set flag */
238
+ }
237
239
  loadSlack();
238
240
 
239
241
  export const slackChannel = (config: { token: string }) =>
@@ -282,11 +284,11 @@ defineNotification<Data>({
282
284
 
283
285
  Returns `{ send, queue, only }`:
284
286
 
285
- | Method | Signature | What it does |
286
- |---|---|---|
287
- | `.send` | `(to, data, options?)` | Render + dispatch synchronously. |
288
- | `.queue` | `(to, data, options?)` | Render + enqueue. Throws if no queue dispatcher is configured. |
289
- | `.only(...channels)` | returns `{send, queue, only}` | Restrict dispatch to a subset of channels. |
287
+ | Method | Signature | What it does |
288
+ | -------------------- | ----------------------------- | -------------------------------------------------------------- |
289
+ | `.send` | `(to, data, options?)` | Render + dispatch synchronously. |
290
+ | `.queue` | `(to, data, options?)` | Render + enqueue. Throws if no queue dispatcher is configured. |
291
+ | `.only(...channels)` | returns `{send, queue, only}` | Restrict dispatch to a subset of channels. |
290
292
 
291
293
  `to` accepts a `Notifiable` OR a `Notifiable[]`. Fan-out emits one render+dispatch per recipient with per-recipient + per-channel `Promise.allSettled` (one failure does not abort the others).
292
294
 
@@ -308,9 +310,7 @@ await welcome.send(user, { name: "Hasan" });
308
310
  export const orderShipped = defineNotification<{ order: Order }>({
309
311
  type: "order.shipped",
310
312
  via: (_data, to) =>
311
- to.get("telegram_chat_id")
312
- ? ["database", "telegram"]
313
- : ["database", "mail"],
313
+ to.get("telegram_chat_id") ? ["database", "telegram"] : ["database", "mail"],
314
314
  database: ({ order }) => ({ title: `Order #${order.number} shipped` }),
315
315
  mail: ({ order }, to) => ({
316
316
  subject: `Order #${order.number} shipped`,
@@ -323,16 +323,15 @@ export const orderShipped = defineNotification<{ order: Order }>({
323
323
  ## The renderer's 3rd arg — `RenderContext`
324
324
 
325
325
  ```ts
326
- mail: ({ campaignId }, to, { locale = "en", meta }) => ({
326
+ mail: (({ campaignId }, to, { locale = "en", meta }) => ({
327
327
  subject: subjectsByLocale[locale],
328
- html: htmlByLocale[locale],
328
+ html: htmlByLocale[locale],
329
329
  }),
330
-
331
- // usage:
332
- await marketing.queue(user, payload, {
333
- locale: user.get("locale"),
334
- meta: { campaignId, source: "blast" },
335
- });
330
+ // usage:
331
+ await marketing.queue(user, payload, {
332
+ locale: user.get("locale"),
333
+ meta: { campaignId, source: "blast" },
334
+ }));
336
335
  ```
337
336
 
338
337
  `ctx` carries `locale` + `meta` from `SendOptions`. `meta` flows through to every observability event too.
@@ -343,7 +342,7 @@ The `database` renderer may OMIT `type` — the dispatcher injects `def.type` au
343
342
 
344
343
  ```ts
345
344
  defineNotification({
346
- type: "order.shipped", // ← single source of truth
345
+ type: "order.shipped", // ← single source of truth
347
346
  via: ["database"],
348
347
  database: () => ({ title: "Shipped" }), // type omitted; dispatcher injects "order.shipped"
349
348
  });
@@ -373,14 +372,14 @@ await orderShipped.queue(user, { order }, { delay: "10m" });
373
372
 
374
373
  ## SendOptions
375
374
 
376
- | Field | Effect |
377
- |---|---|
378
- | `delay` | Reserved — `"10m"` / `"3d"` / `600` (seconds). NOT honored yet: both `.send()` and the current `.queue()` worker dispatch immediately; delay-aware delivery is a follow-up. |
379
- | `locale` | Passed to renderers via `RenderContext.locale`. |
380
- | `meta` | Passed to renderers + included in every observability event. |
381
- | `idempotencyKey` | Injected into the database payload (dedupe via unique index). |
382
- | `force` | Bypass `PreferenceProvider`. Does NOT bypass `RateLimiter`. |
383
- | `type` | Ignored by `defineNotification` — see `send-ad-hoc` for ad-hoc gating. |
375
+ | Field | Effect |
376
+ | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
377
+ | `delay` | Reserved — `"10m"` / `"3d"` / `600` (seconds). NOT honored yet: both `.send()` and the current `.queue()` worker dispatch immediately; delay-aware delivery is a follow-up. |
378
+ | `locale` | Passed to renderers via `RenderContext.locale`. |
379
+ | `meta` | Passed to renderers + included in every observability event. |
380
+ | `idempotencyKey` | Injected into the database payload (dedupe via unique index). |
381
+ | `force` | Bypass `PreferenceProvider`. Does NOT bypass `RateLimiter`. |
382
+ | `type` | Ignored by `defineNotification` — see `send-ad-hoc` for ad-hoc gating. |
384
383
 
385
384
  ## Failure isolation
386
385
 
@@ -409,7 +408,7 @@ Multi-channel notifications for Warlock.js. **Define once, fire anywhere.**
409
408
 
410
409
  You have an event (`order.shipped`, `comment.mentioned`, `password.changed`) and one or more recipients. You want to address them through any combination of channels (mail, in-app, push, ...) with one render. That's what this package is.
411
410
 
412
- It is NOT a queue, a template engine, a transport library, or an analytics pipeline — it orchestrates *over* the transports cascade / core / herald / bridges already provide.
411
+ It is NOT a queue, a template engine, a transport library, or an analytics pipeline — it orchestrates _over_ the transports cascade / core / herald / bridges already provide.
413
412
 
414
413
  ## Server-only package
415
414
 
@@ -432,7 +431,7 @@ import { Notification } from "app/notifications/models/notification/notification
432
431
 
433
432
  const config: NotificationConfig = {
434
433
  channels: {
435
- mail: mailChannel({ from: "no-reply@store.com" }),
434
+ mail: mailChannel({ from: "no-reply@store.com" }),
436
435
  database: inApp.configure({ model: Notification }),
437
436
  },
438
437
  };
@@ -465,7 +464,7 @@ await orderShipped.send(user, { orderId: order.id, number: order.number });
465
464
  await notify.mail(user, { subject: "Welcome", html: "<p>Hi!</p>" });
466
465
 
467
466
  const unread = await inApp.listUnread(user);
468
- const badge = await inApp.countUnread(user);
467
+ const badge = await inApp.countUnread(user);
469
468
  await inApp.markAsRead(user, "ntf_123");
470
469
  ```
471
470
 
@@ -475,15 +474,15 @@ await inApp.markAsRead(user, "ntf_123");
475
474
 
476
475
  ## Phase 1 vs Phase 2
477
476
 
478
- | Channel | Phase | How |
479
- |---|---|---|
480
- | `mail` | 1 ✅ | core `sendMail` |
481
- | `database` | 1 ✅ | cascade repo (recipient-scoped reads) |
482
- | `whatsapp` | 2 | bridges `MessageProvider` |
483
- | `telegram` | 2 | bridges `MessageProvider` |
484
- | `slack` | 2 | bridges `MessageProvider` |
485
- | `push` | 2 | bridges `PushProvider` |
486
- | your own | 1 ✅ | `defineChannel` + 3-line `declare module` |
477
+ | Channel | Phase | How |
478
+ | ---------- | ----- | ----------------------------------------- |
479
+ | `mail` | 1 ✅ | core `sendMail` |
480
+ | `database` | 1 ✅ | cascade repo (recipient-scoped reads) |
481
+ | `whatsapp` | 2 | bridges `MessageProvider` |
482
+ | `telegram` | 2 | bridges `MessageProvider` |
483
+ | `slack` | 2 | bridges `MessageProvider` |
484
+ | `push` | 2 | bridges `PushProvider` |
485
+ | your own | 1 ✅ | `defineChannel` + 3-line `declare module` |
487
486
 
488
487
  ## See also
489
488
 
@@ -512,27 +511,31 @@ import { notifications } from "@warlock.js/notifications";
512
511
 
513
512
  // latency + delivery, keyed by recipient
514
513
  notifications.on("sent", ({ channel, notifiable, durationMs, options }) =>
515
- metrics.timing(`notif.${channel}.sent`, durationMs, { userId: notifiable?.id, ...options.meta }));
514
+ metrics.timing(`notif.${channel}.sent`, durationMs, { userId: notifiable?.id, ...options.meta }),
515
+ );
516
516
 
517
517
  notifications.on("failed", ({ channel, notifiable, error }) =>
518
- log.error(`notif.${channel}`, error, { userId: notifiable?.id }));
518
+ log.error(`notif.${channel}`, error, { userId: notifiable?.id }),
519
+ );
519
520
 
520
521
  notifications.on("skipped", ({ channel, reason }) =>
521
- metrics.inc(`notif.${channel}.skipped.${reason}`));
522
+ metrics.inc(`notif.${channel}.skipped.${reason}`),
523
+ );
522
524
 
523
525
  // pair `sending` → terminal by dispatchId — open a span / arm a hung-send watchdog
524
526
  notifications.on("sending", ({ dispatchId, channel, notifiable }) =>
525
- tracer.open(dispatchId, { channel, userId: notifiable?.id }));
527
+ tracer.open(dispatchId, { channel, userId: notifiable?.id }),
528
+ );
526
529
  ```
527
530
 
528
531
  ## Events
529
532
 
530
- | Event | Fires when | Payload |
531
- |---|---|---|
532
- | `sending` | Gates passed; about to hit the transport (sync) / enqueue (queue) | `{ dispatchId, channel, notifiable?, payload, options }` |
533
- | `sent` | Channel dispatched OR job enqueued | `{ dispatchId, channel, notifiable?, payload, options, durationMs }` |
534
- | `failed` | `channel.send` (or `queue.dispatch`) threw | `{ dispatchId, channel, notifiable?, payload, error, options, durationMs }` |
535
- | `skipped` | A pre-send gate dropped this channel | `{ dispatchId, channel, notifiable?, reason, options }` — `reason: "preference" \| "rate-limit"` |
533
+ | Event | Fires when | Payload |
534
+ | --------- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
535
+ | `sending` | Gates passed; about to hit the transport (sync) / enqueue (queue) | `{ dispatchId, channel, notifiable?, payload, options }` |
536
+ | `sent` | Channel dispatched OR job enqueued | `{ dispatchId, channel, notifiable?, payload, options, durationMs }` |
537
+ | `failed` | `channel.send` (or `queue.dispatch`) threw | `{ dispatchId, channel, notifiable?, payload, error, options, durationMs }` |
538
+ | `skipped` | A pre-send gate dropped this channel | `{ dispatchId, channel, notifiable?, reason, options }` — `reason: "preference" \| "rate-limit"` |
536
539
 
537
540
  `notifiable` is the recipient **model** (undefined only for raw-target ad-hoc sends like `notify.mail("x@y.com", …)`) — read `notifiable?.id` / `notifiable?.get(...)` to key your metrics or logs.
538
541
 
@@ -716,7 +719,7 @@ Pass a string instead of a model to use the string as the route directly:
716
719
 
717
720
  ```ts
718
721
  await notify.mail("guest@example.com", { subject: "Receipt", html: "<p>…</p>" });
719
- await notify.whatsapp("+201234567890", { body: "Promo: 20% off!" }); // Phase 2
722
+ await notify.whatsapp("+201234567890", { body: "Promo: 20% off!" }); // Phase 2
720
723
  ```
721
724
 
722
725
  When the recipient isn't a model, `PreferenceProvider` and `RateLimiter` are skipped — there's no `Notifiable` to consult.
@@ -758,14 +761,14 @@ await notify.slack(staff, { text: "Deploy starting" });
758
761
 
759
762
  ## SendOptions (3rd arg)
760
763
 
761
- | Field | Effect |
762
- |---|---|
763
- | `delay` | Reserved for `.queue` paths; not used by `notify.<channel>` (sync). |
764
- | `locale` | Forwarded to the channel's `send({ options })`. |
765
- | `meta` | Forwarded to the channel + included in every observability event. |
766
- | `idempotencyKey` | Injected into the database payload (dedupe). |
767
- | `force` | Bypass `PreferenceProvider`. Does NOT bypass `RateLimiter`. |
768
- | `type` | Notification type for gating (ad-hoc only). |
764
+ | Field | Effect |
765
+ | ---------------- | ------------------------------------------------------------------- |
766
+ | `delay` | Reserved for `.queue` paths; not used by `notify.<channel>` (sync). |
767
+ | `locale` | Forwarded to the channel's `send({ options })`. |
768
+ | `meta` | Forwarded to the channel + included in every observability event. |
769
+ | `idempotencyKey` | Injected into the database payload (dedupe). |
770
+ | `force` | Bypass `PreferenceProvider`. Does NOT bypass `RateLimiter`. |
771
+ | `type` | Notification type for gating (ad-hoc only). |
769
772
 
770
773
  ## Failure surfaces
771
774
 
@@ -864,7 +867,9 @@ abstract class DatabaseNotification extends Model implements NotificationContrac
864
867
  class BaseNotificationsRepository extends RepositoryManager {
865
868
  // constructor resolves the model's columnMap → builds `filterBy` +
866
869
  // createFor / markRead / markUnread / deleteFor from it.
867
- public createFor(recipientId, input, tenantId?) { /* one insert, starts unread */ }
870
+ public createFor(recipientId, input, tenantId?) {
871
+ /* one insert, starts unread */
872
+ }
868
873
  }
869
874
  ```
870
875
 
@@ -877,9 +882,9 @@ class BaseNotificationsRepository extends RepositoryManager {
877
882
  ```ts
878
883
  export type NotificationColumnMap = {
879
884
  recipient?: string; // recipient FK. Default "user_id"
880
- tenant?: string; // multi-tenant scope, written from the recipient. Omit → single-tenant
881
- readAt?: string; // read-timestamp column
882
- isRead?: string; // read-flag column (indexed)
885
+ tenant?: string; // multi-tenant scope, written from the recipient. Omit → single-tenant
886
+ readAt?: string; // read-timestamp column
887
+ isRead?: string; // read-flag column (indexed)
883
888
  };
884
889
  ```
885
890
 
@@ -981,12 +986,12 @@ export default Migration.create(Notification, notificationColumns(Notification))
981
986
  `notificationColumns(Notification)` reads the model's `columnMap` and returns the
982
987
  matching columns:
983
988
 
984
- | columnMap | Columns |
985
- |---|---|
986
- | _(none / default)_ | `user_id`, `type`, `title`, `body`, `payload`, `read_at`, `idempotency_key` |
987
- | `{ tenant: "organization_id", readAt: "read_at" }` | adds `organization_id`; read_at-only |
988
- | `{ isRead: "is_read" }` | swaps `read_at` for `is_read` (indexed boolean) |
989
- | `{ isRead: "is_read", readAt: "read_at" }` | both read-state columns |
989
+ | columnMap | Columns |
990
+ | -------------------------------------------------- | --------------------------------------------------------------------------- |
991
+ | _(none / default)_ | `user_id`, `type`, `title`, `body`, `payload`, `read_at`, `idempotency_key` |
992
+ | `{ tenant: "organization_id", readAt: "read_at" }` | adds `organization_id`; read_at-only |
993
+ | `{ isRead: "is_read" }` | swaps `read_at` for `is_read` (indexed boolean) |
994
+ | `{ isRead: "is_read", readAt: "read_at" }` | both read-state columns |
990
995
 
991
996
  The recipient / tenant / read-state column NAMES come from `columnMap`; `type` /
992
997
  `title` / `body` / `payload` / `idempotency_key` are fixed. `id` / `createdAt` /
@@ -999,7 +1004,10 @@ are `bigint`, `integer`, or strings, pass `idType`; it is applied to every
999
1004
  identifier column the factory creates:
1000
1005
 
1001
1006
  ```ts
1002
- export default Migration.create(Notification, notificationColumns(Notification, { idType: "bigint" }));
1007
+ export default Migration.create(
1008
+ Notification,
1009
+ notificationColumns(Notification, { idType: "bigint" }),
1010
+ );
1003
1011
  ```
1004
1012
 
1005
1013
  ## With extras — spread + extend
package/package.json CHANGED
@@ -5,18 +5,19 @@
5
5
  "environment": "server"
6
6
  },
7
7
  "dependencies": {
8
- "@warlock.js/cache": "5.30.0",
9
- "@warlock.js/cascade": "5.30.0",
10
- "@warlock.js/core": "5.30.0",
11
- "@warlock.js/logger": "5.30.0"
12
- },
13
- "optionalDependencies": {
14
- "@warlock.js/herald": "5.30.0"
8
+ "@warlock.js/cache": "5.32.0",
9
+ "@warlock.js/cascade": "5.32.0",
10
+ "@warlock.js/core": "5.32.0",
11
+ "@warlock.js/logger": "5.32.0"
15
12
  },
16
13
  "peerDependencies": {
17
- "@warlock.js/queue": "5.30.0"
14
+ "@warlock.js/herald": "5.32.0",
15
+ "@warlock.js/queue": "5.32.0"
18
16
  },
19
17
  "peerDependenciesMeta": {
18
+ "@warlock.js/herald": {
19
+ "optional": true
20
+ },
20
21
  "@warlock.js/queue": {
21
22
  "optional": true
22
23
  }
@@ -36,7 +37,7 @@
36
37
  ],
37
38
  "author": "hassanzohdy",
38
39
  "license": "MIT",
39
- "version": "5.30.0",
40
+ "version": "5.32.0",
40
41
  "main": "./cjs/index.cjs",
41
42
  "module": "./esm/index.mjs",
42
43
  "types": "./esm/index.d.mts",
@@ -17,7 +17,7 @@ import { Notification } from "app/notifications/models/notification/notification
17
17
 
18
18
  const config: NotificationConfig = {
19
19
  channels: {
20
- mail: mailChannel({ from: "no-reply@store.com" }),
20
+ mail: mailChannel({ from: "no-reply@store.com" }),
21
21
  database: inApp.configure({ model: Notification }),
22
22
  },
23
23
  };
@@ -32,17 +32,17 @@ The `database` channel is returned by `inApp.configure({ model | repository })`
32
32
  ```ts
33
33
  const config: NotificationConfig = {
34
34
  channels: {
35
- mail: mailChannel({ from }),
35
+ mail: mailChannel({ from }),
36
36
  database: inApp.configure({ model: Notification }),
37
37
 
38
38
  // custom channels
39
- discord: discordChannel(), // defineChannel + declare module
39
+ discord: discordChannel(), // defineChannel + declare module
40
40
  },
41
41
 
42
42
  // optional gates — both app-owned; package ships no defaults
43
- preferences: userPreferences, // drops channels recipient muted
44
- rateLimit, // drops channels over budget
45
- queue: heraldQueue(), // backs `.queue()` (needs @warlock.js/herald)
43
+ preferences: userPreferences, // drops channels recipient muted
44
+ rateLimit, // drops channels over budget
45
+ queue: heraldQueue(), // backs `.queue()` (needs @warlock.js/herald)
46
46
  };
47
47
 
48
48
  export default config;
@@ -116,7 +116,7 @@ Dropped channels fire a `skipped` event with reason `"rate-limit"`. `force` does
116
116
  ```ts
117
117
  import { getNotificationConfig } from "@warlock.js/notifications";
118
118
 
119
- const cfg = getNotificationConfig(); // throws NotificationsNotConfiguredError if unset
119
+ const cfg = getNotificationConfig(); // throws NotificationsNotConfiguredError if unset
120
120
  ```
121
121
 
122
122
  ## Tests
@@ -50,12 +50,12 @@ Now `notify.discord(user, { content: "🎉" })` works, and `discord:` is a valid
50
50
 
51
51
  ## `route` resolution
52
52
 
53
- | What `route` returns | Effect |
54
- |---|---|
55
- | `string` | Used directly as the address (`"user@example.com"`, webhook URL). |
56
- | `{ id: Id }` | The recipient's storage id — for database/internal channels. |
57
- | `undefined` | Dispatcher falls back to `{ id: notifiable.id }`. |
58
- | `route` omitted | Same as returning `undefined` — `{ id }` fallback. |
53
+ | What `route` returns | Effect |
54
+ | -------------------- | ----------------------------------------------------------------- |
55
+ | `string` | Used directly as the address (`"user@example.com"`, webhook URL). |
56
+ | `{ id: Id }` | The recipient's storage id — for database/internal channels. |
57
+ | `undefined` | Dispatcher falls back to `{ id: notifiable.id }`. |
58
+ | `route` omitted | Same as returning `undefined` — `{ id }` fallback. |
59
59
 
60
60
  For raw-target ad-hoc sends (`notify.discord("https://hooks.../foo", payload)`), the raw string wins over `route()`.
61
61
 
@@ -83,7 +83,9 @@ import type { WebClient } from "@slack/web-api";
83
83
  let Slack: typeof import("@slack/web-api");
84
84
  let isModuleExists: boolean | null = null;
85
85
 
86
- async function loadSlack() { /* try/catch await import; set flag */ }
86
+ async function loadSlack() {
87
+ /* try/catch await import; set flag */
88
+ }
87
89
  loadSlack();
88
90
 
89
91
  export const slackChannel = (config: { token: string }) =>
@@ -21,11 +21,11 @@ defineNotification<Data>({
21
21
 
22
22
  Returns `{ send, queue, only }`:
23
23
 
24
- | Method | Signature | What it does |
25
- |---|---|---|
26
- | `.send` | `(to, data, options?)` | Render + dispatch synchronously. |
27
- | `.queue` | `(to, data, options?)` | Render + enqueue. Throws if no queue dispatcher is configured. |
28
- | `.only(...channels)` | returns `{send, queue, only}` | Restrict dispatch to a subset of channels. |
24
+ | Method | Signature | What it does |
25
+ | -------------------- | ----------------------------- | -------------------------------------------------------------- |
26
+ | `.send` | `(to, data, options?)` | Render + dispatch synchronously. |
27
+ | `.queue` | `(to, data, options?)` | Render + enqueue. Throws if no queue dispatcher is configured. |
28
+ | `.only(...channels)` | returns `{send, queue, only}` | Restrict dispatch to a subset of channels. |
29
29
 
30
30
  `to` accepts a `Notifiable` OR a `Notifiable[]`. Fan-out emits one render+dispatch per recipient with per-recipient + per-channel `Promise.allSettled` (one failure does not abort the others).
31
31
 
@@ -47,9 +47,7 @@ await welcome.send(user, { name: "Hasan" });
47
47
  export const orderShipped = defineNotification<{ order: Order }>({
48
48
  type: "order.shipped",
49
49
  via: (_data, to) =>
50
- to.get("telegram_chat_id")
51
- ? ["database", "telegram"]
52
- : ["database", "mail"],
50
+ to.get("telegram_chat_id") ? ["database", "telegram"] : ["database", "mail"],
53
51
  database: ({ order }) => ({ title: `Order #${order.number} shipped` }),
54
52
  mail: ({ order }, to) => ({
55
53
  subject: `Order #${order.number} shipped`,
@@ -62,16 +60,15 @@ export const orderShipped = defineNotification<{ order: Order }>({
62
60
  ## The renderer's 3rd arg — `RenderContext`
63
61
 
64
62
  ```ts
65
- mail: ({ campaignId }, to, { locale = "en", meta }) => ({
63
+ mail: (({ campaignId }, to, { locale = "en", meta }) => ({
66
64
  subject: subjectsByLocale[locale],
67
- html: htmlByLocale[locale],
65
+ html: htmlByLocale[locale],
68
66
  }),
69
-
70
- // usage:
71
- await marketing.queue(user, payload, {
72
- locale: user.get("locale"),
73
- meta: { campaignId, source: "blast" },
74
- });
67
+ // usage:
68
+ await marketing.queue(user, payload, {
69
+ locale: user.get("locale"),
70
+ meta: { campaignId, source: "blast" },
71
+ }));
75
72
  ```
76
73
 
77
74
  `ctx` carries `locale` + `meta` from `SendOptions`. `meta` flows through to every observability event too.
@@ -82,7 +79,7 @@ The `database` renderer may OMIT `type` — the dispatcher injects `def.type` au
82
79
 
83
80
  ```ts
84
81
  defineNotification({
85
- type: "order.shipped", // ← single source of truth
82
+ type: "order.shipped", // ← single source of truth
86
83
  via: ["database"],
87
84
  database: () => ({ title: "Shipped" }), // type omitted; dispatcher injects "order.shipped"
88
85
  });
@@ -112,14 +109,14 @@ await orderShipped.queue(user, { order }, { delay: "10m" });
112
109
 
113
110
  ## SendOptions
114
111
 
115
- | Field | Effect |
116
- |---|---|
117
- | `delay` | Reserved — `"10m"` / `"3d"` / `600` (seconds). NOT honored yet: both `.send()` and the current `.queue()` worker dispatch immediately; delay-aware delivery is a follow-up. |
118
- | `locale` | Passed to renderers via `RenderContext.locale`. |
119
- | `meta` | Passed to renderers + included in every observability event. |
120
- | `idempotencyKey` | Injected into the database payload (dedupe via unique index). |
121
- | `force` | Bypass `PreferenceProvider`. Does NOT bypass `RateLimiter`. |
122
- | `type` | Ignored by `defineNotification` — see `send-ad-hoc` for ad-hoc gating. |
112
+ | Field | Effect |
113
+ | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
114
+ | `delay` | Reserved — `"10m"` / `"3d"` / `600` (seconds). NOT honored yet: both `.send()` and the current `.queue()` worker dispatch immediately; delay-aware delivery is a follow-up. |
115
+ | `locale` | Passed to renderers via `RenderContext.locale`. |
116
+ | `meta` | Passed to renderers + included in every observability event. |
117
+ | `idempotencyKey` | Injected into the database payload (dedupe via unique index). |
118
+ | `force` | Bypass `PreferenceProvider`. Does NOT bypass `RateLimiter`. |
119
+ | `type` | Ignored by `defineNotification` — see `send-ad-hoc` for ad-hoc gating. |
123
120
 
124
121
  ## Failure isolation
125
122
 
package/skills/index.md CHANGED
@@ -1,11 +1,13 @@
1
1
  ---
2
- description: "Multi-channel notifications for Warlock: define once, send by mail, in-app database, or custom channels. Exports `defineNotification`, `notify`, `defineChannel`, `mailChannel`, `inApp`, `notificationColumns`, `notifications`, `bullmqQueue`, `heraldQueue`, `NotificationConfig`. Use for: \"notify a user\", \"send order shipped by email and in-app\", \"unread notifications\", \"add a Slack or webhook channel\", \"queue notification delivery\". Not this package: sending a plain email or mail templates → @warlock.js/core sendMail; background jobs → @warlock.js/queue."
2
+ description: 'Multi-channel notifications for Warlock: define once, send by mail, in-app database, or custom channels. Exports `defineNotification`, `notify`, `defineChannel`, `mailChannel`, `inApp`, `notificationColumns`, `notifications`, `bullmqQueue`, `heraldQueue`, `NotificationConfig`. Use for: "notify a user", "send order shipped by email and in-app", "unread notifications", "add a Slack or webhook channel", "queue notification delivery". Not this package: sending a plain email or mail templates → @warlock.js/core sendMail; background jobs → @warlock.js/queue.'
3
3
  ---
4
+
4
5
  # @warlock.js/notifications
5
6
 
6
7
  An orchestrator over transports that already exist: one event, many recipients, any mix of channels, one render per channel. It is not a queue, template engine, or transport. `defineNotification` builds a reusable notification (`send`, `queue`, `only`); `notify.<channel>` does ad-hoc single-channel sends; `inApp` is the read side of the database channel. Server-only.
7
8
 
8
9
  ## The 80% path
10
+
9
11
  1. Orient with `notifications-basics.md`.
10
12
  2. Configure channels in `src/config/notifications.ts`: `configure-notifications.md`; create the table: `write-notification-migration.md`.
11
13
  3. Define the notification with `via` and a renderer per channel: `define-notification.md`; one-off sends: `send-ad-hoc.md`.
@@ -13,6 +15,7 @@ An orchestrator over transports that already exist: one event, many recipients,
13
15
  5. Custom channel: `define-channel.md`; deferred delivery: `queue-notifications.md`; sent/failed/skipped hooks: `observe-notifications.md`.
14
16
 
15
17
  ## Conventions and pitfalls
18
+
16
19
  - The config is declarative; the connector registers its default export, so never call `setNotificationConfig` yourself.
17
20
  - Channel names are typed through `NotificationChannels` declaration merging.
18
21
  - `mailChannel` wraps core `sendMail`; use core directly for non-notification mail.
@@ -11,7 +11,7 @@ Multi-channel notifications for Warlock.js. **Define once, fire anywhere.**
11
11
 
12
12
  You have an event (`order.shipped`, `comment.mentioned`, `password.changed`) and one or more recipients. You want to address them through any combination of channels (mail, in-app, push, ...) with one render. That's what this package is.
13
13
 
14
- It is NOT a queue, a template engine, a transport library, or an analytics pipeline — it orchestrates *over* the transports cascade / core / herald / bridges already provide.
14
+ It is NOT a queue, a template engine, a transport library, or an analytics pipeline — it orchestrates _over_ the transports cascade / core / herald / bridges already provide.
15
15
 
16
16
  ## Server-only package
17
17
 
@@ -34,7 +34,7 @@ import { Notification } from "app/notifications/models/notification/notification
34
34
 
35
35
  const config: NotificationConfig = {
36
36
  channels: {
37
- mail: mailChannel({ from: "no-reply@store.com" }),
37
+ mail: mailChannel({ from: "no-reply@store.com" }),
38
38
  database: inApp.configure({ model: Notification }),
39
39
  },
40
40
  };
@@ -67,7 +67,7 @@ await orderShipped.send(user, { orderId: order.id, number: order.number });
67
67
  await notify.mail(user, { subject: "Welcome", html: "<p>Hi!</p>" });
68
68
 
69
69
  const unread = await inApp.listUnread(user);
70
- const badge = await inApp.countUnread(user);
70
+ const badge = await inApp.countUnread(user);
71
71
  await inApp.markAsRead(user, "ntf_123");
72
72
  ```
73
73
 
@@ -77,15 +77,15 @@ await inApp.markAsRead(user, "ntf_123");
77
77
 
78
78
  ## Phase 1 vs Phase 2
79
79
 
80
- | Channel | Phase | How |
81
- |---|---|---|
82
- | `mail` | 1 ✅ | core `sendMail` |
83
- | `database` | 1 ✅ | cascade repo (recipient-scoped reads) |
84
- | `whatsapp` | 2 | bridges `MessageProvider` |
85
- | `telegram` | 2 | bridges `MessageProvider` |
86
- | `slack` | 2 | bridges `MessageProvider` |
87
- | `push` | 2 | bridges `PushProvider` |
88
- | your own | 1 ✅ | `defineChannel` + 3-line `declare module` |
80
+ | Channel | Phase | How |
81
+ | ---------- | ----- | ----------------------------------------- |
82
+ | `mail` | 1 ✅ | core `sendMail` |
83
+ | `database` | 1 ✅ | cascade repo (recipient-scoped reads) |
84
+ | `whatsapp` | 2 | bridges `MessageProvider` |
85
+ | `telegram` | 2 | bridges `MessageProvider` |
86
+ | `slack` | 2 | bridges `MessageProvider` |
87
+ | `push` | 2 | bridges `PushProvider` |
88
+ | your own | 1 ✅ | `defineChannel` + 3-line `declare module` |
89
89
 
90
90
  ## See also
91
91