hazo_notify 3.1.0 → 4.0.2

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 (244) hide show
  1. package/README.md +122 -17
  2. package/config/hazo_notify_config.ini +37 -0
  3. package/dist/components/notification_banner/index.d.ts +27 -0
  4. package/dist/components/notification_banner/index.d.ts.map +1 -0
  5. package/dist/components/notification_banner/index.js +42 -0
  6. package/dist/components/notification_banner/index.js.map +1 -0
  7. package/dist/components/notification_bell/index.d.ts +56 -0
  8. package/dist/components/notification_bell/index.d.ts.map +1 -0
  9. package/dist/components/notification_bell/index.js +73 -0
  10. package/dist/components/notification_bell/index.js.map +1 -0
  11. package/dist/components/template_manager/template_editor.js +3 -3
  12. package/dist/components/template_manager/template_editor.js.map +1 -1
  13. package/dist/components/template_manager/template_manager_admin.d.ts.map +1 -1
  14. package/dist/components/template_manager/template_manager_admin.js +3 -4
  15. package/dist/components/template_manager/template_manager_admin.js.map +1 -1
  16. package/dist/lib/adapters/email/adapter.d.ts +49 -0
  17. package/dist/lib/adapters/email/adapter.d.ts.map +1 -0
  18. package/dist/lib/adapters/email/adapter.js +87 -0
  19. package/dist/lib/adapters/email/adapter.js.map +1 -0
  20. package/dist/lib/adapters/email/config.d.ts +15 -0
  21. package/dist/lib/adapters/email/config.d.ts.map +1 -0
  22. package/dist/lib/{emailer/emailer.js → adapters/email/config.js} +7 -113
  23. package/dist/lib/adapters/email/config.js.map +1 -0
  24. package/dist/lib/adapters/email/envelope.d.ts +29 -0
  25. package/dist/lib/adapters/email/envelope.d.ts.map +1 -0
  26. package/dist/lib/adapters/email/envelope.js +46 -0
  27. package/dist/lib/adapters/email/envelope.js.map +1 -0
  28. package/dist/lib/adapters/email/index.d.ts +12 -0
  29. package/dist/lib/adapters/email/index.d.ts.map +1 -0
  30. package/dist/lib/adapters/email/index.js +11 -0
  31. package/dist/lib/adapters/email/index.js.map +1 -0
  32. package/dist/lib/adapters/email/providers/index.d.ts.map +1 -0
  33. package/dist/lib/adapters/email/providers/index.js.map +1 -0
  34. package/dist/lib/adapters/email/providers/pop3_provider.d.ts.map +1 -0
  35. package/dist/lib/adapters/email/providers/pop3_provider.js.map +1 -0
  36. package/dist/lib/adapters/email/providers/smtp_provider.d.ts.map +1 -0
  37. package/dist/lib/adapters/email/providers/smtp_provider.js.map +1 -0
  38. package/dist/lib/adapters/email/providers/zeptomail_provider.d.ts.map +1 -0
  39. package/dist/lib/adapters/email/providers/zeptomail_provider.js.map +1 -0
  40. package/dist/lib/{emailer/emailer.d.ts → adapters/email/send_email.d.ts} +9 -10
  41. package/dist/lib/adapters/email/send_email.d.ts.map +1 -0
  42. package/dist/lib/adapters/email/send_email.js +122 -0
  43. package/dist/lib/adapters/email/send_email.js.map +1 -0
  44. package/dist/lib/adapters/email/types.d.ts.map +1 -0
  45. package/dist/lib/adapters/email/types.js.map +1 -0
  46. package/dist/lib/adapters/email/utils/constants.d.ts.map +1 -0
  47. package/dist/lib/adapters/email/utils/constants.js.map +1 -0
  48. package/dist/lib/adapters/email/utils/index.d.ts.map +1 -0
  49. package/dist/lib/adapters/email/utils/index.js.map +1 -0
  50. package/dist/lib/adapters/email/utils/logger.d.ts.map +1 -0
  51. package/dist/lib/adapters/email/utils/logger.js.map +1 -0
  52. package/dist/lib/adapters/email/utils/validation.d.ts.map +1 -0
  53. package/dist/lib/adapters/email/utils/validation.js.map +1 -0
  54. package/dist/lib/adapters/telegram/adapter.d.ts +25 -0
  55. package/dist/lib/adapters/telegram/adapter.d.ts.map +1 -0
  56. package/dist/lib/adapters/telegram/adapter.js +75 -0
  57. package/dist/lib/adapters/telegram/adapter.js.map +1 -0
  58. package/dist/lib/adapters/telegram/config.d.ts +22 -0
  59. package/dist/lib/adapters/telegram/config.d.ts.map +1 -0
  60. package/dist/lib/adapters/telegram/config.js +60 -0
  61. package/dist/lib/adapters/telegram/config.js.map +1 -0
  62. package/dist/lib/adapters/telegram/index.d.ts +8 -0
  63. package/dist/lib/adapters/telegram/index.d.ts.map +1 -0
  64. package/dist/lib/adapters/telegram/index.js +5 -0
  65. package/dist/lib/adapters/telegram/index.js.map +1 -0
  66. package/dist/lib/adapters/telegram/splitter.d.ts +7 -0
  67. package/dist/lib/adapters/telegram/splitter.d.ts.map +1 -0
  68. package/dist/lib/adapters/telegram/splitter.js +47 -0
  69. package/dist/lib/adapters/telegram/splitter.js.map +1 -0
  70. package/dist/lib/adapters/telegram/transport.d.ts +31 -0
  71. package/dist/lib/adapters/telegram/transport.d.ts.map +1 -0
  72. package/dist/lib/adapters/telegram/transport.js +112 -0
  73. package/dist/lib/adapters/telegram/transport.js.map +1 -0
  74. package/dist/lib/api/banner.d.ts +41 -0
  75. package/dist/lib/api/banner.d.ts.map +1 -0
  76. package/dist/lib/api/banner.js +53 -0
  77. package/dist/lib/api/banner.js.map +1 -0
  78. package/dist/lib/api/inbox.d.ts +33 -0
  79. package/dist/lib/api/inbox.d.ts.map +1 -0
  80. package/dist/lib/api/inbox.js +52 -0
  81. package/dist/lib/api/inbox.js.map +1 -0
  82. package/dist/lib/channels/index.d.ts +3 -0
  83. package/dist/lib/channels/index.d.ts.map +1 -0
  84. package/dist/lib/channels/index.js +3 -0
  85. package/dist/lib/channels/index.js.map +1 -0
  86. package/dist/lib/channels/registry.d.ts +7 -0
  87. package/dist/lib/channels/registry.d.ts.map +1 -0
  88. package/dist/lib/channels/registry.js +24 -0
  89. package/dist/lib/channels/registry.js.map +1 -0
  90. package/dist/lib/channels/types.d.ts +82 -0
  91. package/dist/lib/channels/types.d.ts.map +1 -0
  92. package/dist/lib/channels/types.js +8 -0
  93. package/dist/lib/channels/types.js.map +1 -0
  94. package/dist/lib/dispatcher/batch-key.d.ts +15 -0
  95. package/dist/lib/dispatcher/batch-key.d.ts.map +1 -0
  96. package/dist/lib/dispatcher/batch-key.js +19 -0
  97. package/dist/lib/dispatcher/batch-key.js.map +1 -0
  98. package/dist/lib/dispatcher/index.d.ts +4 -0
  99. package/dist/lib/dispatcher/index.d.ts.map +1 -0
  100. package/dist/lib/dispatcher/index.js +73 -0
  101. package/dist/lib/dispatcher/index.js.map +1 -0
  102. package/dist/lib/inbox/connection.d.ts +19 -0
  103. package/dist/lib/inbox/connection.d.ts.map +1 -0
  104. package/dist/lib/inbox/connection.js +34 -0
  105. package/dist/lib/inbox/connection.js.map +1 -0
  106. package/dist/lib/inbox/dialects/index.d.ts +10 -0
  107. package/dist/lib/inbox/dialects/index.d.ts.map +1 -0
  108. package/dist/lib/inbox/dialects/index.js +13 -0
  109. package/dist/lib/inbox/dialects/index.js.map +1 -0
  110. package/dist/lib/inbox/dialects/postgres.d.ts +3 -0
  111. package/dist/lib/inbox/dialects/postgres.d.ts.map +1 -0
  112. package/dist/lib/inbox/dialects/postgres.js +110 -0
  113. package/dist/lib/inbox/dialects/postgres.js.map +1 -0
  114. package/dist/lib/inbox/dialects/sqlite.d.ts +3 -0
  115. package/dist/lib/inbox/dialects/sqlite.d.ts.map +1 -0
  116. package/dist/lib/inbox/dialects/sqlite.js +120 -0
  117. package/dist/lib/inbox/dialects/sqlite.js.map +1 -0
  118. package/dist/lib/inbox/dialects/types.d.ts +53 -0
  119. package/dist/lib/inbox/dialects/types.d.ts.map +1 -0
  120. package/dist/lib/inbox/dialects/types.js +2 -0
  121. package/dist/lib/inbox/dialects/types.js.map +1 -0
  122. package/dist/lib/inbox/index.d.ts +9 -0
  123. package/dist/lib/inbox/index.d.ts.map +1 -0
  124. package/dist/lib/inbox/index.js +6 -0
  125. package/dist/lib/inbox/index.js.map +1 -0
  126. package/dist/lib/inbox/storage.d.ts +21 -0
  127. package/dist/lib/inbox/storage.d.ts.map +1 -0
  128. package/dist/lib/inbox/storage.js +94 -0
  129. package/dist/lib/inbox/storage.js.map +1 -0
  130. package/dist/lib/inbox/types.d.ts +57 -0
  131. package/dist/lib/inbox/types.d.ts.map +1 -0
  132. package/dist/lib/inbox/types.js +2 -0
  133. package/dist/lib/inbox/types.js.map +1 -0
  134. package/dist/lib/inbox/worker/cleanup.d.ts +14 -0
  135. package/dist/lib/inbox/worker/cleanup.d.ts.map +1 -0
  136. package/dist/lib/inbox/worker/cleanup.js +37 -0
  137. package/dist/lib/inbox/worker/cleanup.js.map +1 -0
  138. package/dist/lib/inbox/worker/flush.d.ts +31 -0
  139. package/dist/lib/inbox/worker/flush.d.ts.map +1 -0
  140. package/dist/lib/inbox/worker/flush.js +97 -0
  141. package/dist/lib/inbox/worker/flush.js.map +1 -0
  142. package/dist/lib/inbox/worker/render.d.ts +23 -0
  143. package/dist/lib/inbox/worker/render.d.ts.map +1 -0
  144. package/dist/lib/inbox/worker/render.js +42 -0
  145. package/dist/lib/inbox/worker/render.js.map +1 -0
  146. package/dist/lib/inbox/worker/start.d.ts +29 -0
  147. package/dist/lib/inbox/worker/start.d.ts.map +1 -0
  148. package/dist/lib/inbox/worker/start.js +100 -0
  149. package/dist/lib/inbox/worker/start.js.map +1 -0
  150. package/dist/lib/index.d.ts +1 -6
  151. package/dist/lib/index.d.ts.map +1 -1
  152. package/dist/lib/index.js +4 -6
  153. package/dist/lib/index.js.map +1 -1
  154. package/dist/lib/jobs/handler.d.ts +25 -0
  155. package/dist/lib/jobs/handler.d.ts.map +1 -0
  156. package/dist/lib/jobs/handler.js +36 -0
  157. package/dist/lib/jobs/handler.js.map +1 -0
  158. package/dist/lib/jobs/index.d.ts +16 -0
  159. package/dist/lib/jobs/index.d.ts.map +1 -0
  160. package/dist/lib/jobs/index.js +13 -0
  161. package/dist/lib/jobs/index.js.map +1 -0
  162. package/dist/lib/jobs/submit.d.ts +20 -0
  163. package/dist/lib/jobs/submit.d.ts.map +1 -0
  164. package/dist/lib/jobs/submit.js +25 -0
  165. package/dist/lib/jobs/submit.js.map +1 -0
  166. package/dist/lib/jobs/types.d.ts +42 -0
  167. package/dist/lib/jobs/types.d.ts.map +1 -0
  168. package/dist/lib/jobs/types.js +12 -0
  169. package/dist/lib/jobs/types.js.map +1 -0
  170. package/dist/lib/template_manager/db/template_repository.d.ts.map +1 -1
  171. package/dist/lib/template_manager/db/template_repository.js +16 -31
  172. package/dist/lib/template_manager/db/template_repository.js.map +1 -1
  173. package/dist/lib/template_manager/engine/variable_resolver.js +4 -4
  174. package/dist/lib/template_manager/engine/variable_resolver.js.map +1 -1
  175. package/dist/lib/template_manager/handlers/index.d.ts.map +1 -1
  176. package/dist/lib/template_manager/handlers/index.js +2 -4
  177. package/dist/lib/template_manager/handlers/index.js.map +1 -1
  178. package/dist/lib/template_manager/seed/sync.d.ts.map +1 -1
  179. package/dist/lib/template_manager/seed/sync.js +20 -4
  180. package/dist/lib/template_manager/seed/sync.js.map +1 -1
  181. package/dist/lib/template_manager/template_manager.d.ts.map +1 -1
  182. package/dist/lib/template_manager/template_manager.js +67 -26
  183. package/dist/lib/template_manager/template_manager.js.map +1 -1
  184. package/dist/lib/template_manager/types.d.ts +35 -9
  185. package/dist/lib/template_manager/types.d.ts.map +1 -1
  186. package/dist/lib/template_manager/utils/index.d.ts +1 -1
  187. package/dist/lib/template_manager/utils/index.d.ts.map +1 -1
  188. package/dist/lib/template_manager/utils/index.js +1 -1
  189. package/dist/lib/template_manager/utils/index.js.map +1 -1
  190. package/dist/lib/template_manager/utils/validation.d.ts +12 -11
  191. package/dist/lib/template_manager/utils/validation.d.ts.map +1 -1
  192. package/dist/lib/template_manager/utils/validation.js +15 -22
  193. package/dist/lib/template_manager/utils/validation.js.map +1 -1
  194. package/migrations/003_create_notifications_table.sql +48 -0
  195. package/migrations/004_inbox_upsert_rpc.sql +63 -0
  196. package/migrations/005_inbox_v4_refactor.pg.sql +53 -0
  197. package/migrations/005_inbox_v4_refactor.sqlite.sql +30 -0
  198. package/migrations/006_channel_deliveries.pg.sql +61 -0
  199. package/migrations/006_channel_deliveries.sqlite.sql +26 -0
  200. package/migrations/007_templates_bodies_jsonb.pg.sql +17 -0
  201. package/migrations/007_templates_bodies_jsonb.sqlite.sql +18 -0
  202. package/package.json +55 -14
  203. package/dist/lib/emailer/emailer.d.ts.map +0 -1
  204. package/dist/lib/emailer/emailer.js.map +0 -1
  205. package/dist/lib/emailer/index.d.ts +0 -12
  206. package/dist/lib/emailer/index.d.ts.map +0 -1
  207. package/dist/lib/emailer/index.js +0 -13
  208. package/dist/lib/emailer/index.js.map +0 -1
  209. package/dist/lib/emailer/providers/index.d.ts.map +0 -1
  210. package/dist/lib/emailer/providers/index.js.map +0 -1
  211. package/dist/lib/emailer/providers/pop3_provider.d.ts.map +0 -1
  212. package/dist/lib/emailer/providers/pop3_provider.js.map +0 -1
  213. package/dist/lib/emailer/providers/smtp_provider.d.ts.map +0 -1
  214. package/dist/lib/emailer/providers/smtp_provider.js.map +0 -1
  215. package/dist/lib/emailer/providers/zeptomail_provider.d.ts.map +0 -1
  216. package/dist/lib/emailer/providers/zeptomail_provider.js.map +0 -1
  217. package/dist/lib/emailer/types.d.ts.map +0 -1
  218. package/dist/lib/emailer/types.js.map +0 -1
  219. package/dist/lib/emailer/utils/constants.d.ts.map +0 -1
  220. package/dist/lib/emailer/utils/constants.js.map +0 -1
  221. package/dist/lib/emailer/utils/index.d.ts.map +0 -1
  222. package/dist/lib/emailer/utils/index.js.map +0 -1
  223. package/dist/lib/emailer/utils/logger.d.ts.map +0 -1
  224. package/dist/lib/emailer/utils/logger.js.map +0 -1
  225. package/dist/lib/emailer/utils/validation.d.ts.map +0 -1
  226. package/dist/lib/emailer/utils/validation.js.map +0 -1
  227. /package/dist/lib/{emailer → adapters/email}/providers/index.d.ts +0 -0
  228. /package/dist/lib/{emailer → adapters/email}/providers/index.js +0 -0
  229. /package/dist/lib/{emailer → adapters/email}/providers/pop3_provider.d.ts +0 -0
  230. /package/dist/lib/{emailer → adapters/email}/providers/pop3_provider.js +0 -0
  231. /package/dist/lib/{emailer → adapters/email}/providers/smtp_provider.d.ts +0 -0
  232. /package/dist/lib/{emailer → adapters/email}/providers/smtp_provider.js +0 -0
  233. /package/dist/lib/{emailer → adapters/email}/providers/zeptomail_provider.d.ts +0 -0
  234. /package/dist/lib/{emailer → adapters/email}/providers/zeptomail_provider.js +0 -0
  235. /package/dist/lib/{emailer → adapters/email}/types.d.ts +0 -0
  236. /package/dist/lib/{emailer → adapters/email}/types.js +0 -0
  237. /package/dist/lib/{emailer → adapters/email}/utils/constants.d.ts +0 -0
  238. /package/dist/lib/{emailer → adapters/email}/utils/constants.js +0 -0
  239. /package/dist/lib/{emailer → adapters/email}/utils/index.d.ts +0 -0
  240. /package/dist/lib/{emailer → adapters/email}/utils/index.js +0 -0
  241. /package/dist/lib/{emailer → adapters/email}/utils/logger.d.ts +0 -0
  242. /package/dist/lib/{emailer → adapters/email}/utils/logger.js +0 -0
  243. /package/dist/lib/{emailer → adapters/email}/utils/validation.d.ts +0 -0
  244. /package/dist/lib/{emailer → adapters/email}/utils/validation.js +0 -0
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Route factories for the office portal's in-app bell.
3
+ *
4
+ * Consumer mounts these under `app/api/notifications/` in their Next.js
5
+ * routes. Auth is injected — package never trusts path params for identity.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ import { listUnreadForUser, unreadCount, markRead, markAllRead, } from "../inbox/storage.js";
10
+ function json(body, status = 200) {
11
+ return { status, json: async () => body };
12
+ }
13
+ export function createInboxRoutes(opts) {
14
+ return {
15
+ async listHandler(req) {
16
+ const auth = await opts.getAuth(req);
17
+ if (!auth)
18
+ return json({ error: "Unauthorized" }, 401);
19
+ const url = new URL(req.url);
20
+ const limit = Math.min(Number(url.searchParams.get("limit") ?? 20), 100);
21
+ const cursor = url.searchParams.get("cursor") ?? undefined;
22
+ const [items, unread] = await Promise.all([
23
+ listUnreadForUser(auth.user_id, auth.scope_id, { limit, cursor }),
24
+ unreadCount(auth.user_id, auth.scope_id),
25
+ ]);
26
+ const next_cursor = items.length === limit ? items[items.length - 1]?.created_at : null;
27
+ return json({ items, unread_count: unread, next_cursor });
28
+ },
29
+ async unreadCountHandler(req) {
30
+ const auth = await opts.getAuth(req);
31
+ if (!auth)
32
+ return json({ error: "Unauthorized" }, 401);
33
+ const n = await unreadCount(auth.user_id, auth.scope_id);
34
+ return json({ unread_count: n });
35
+ },
36
+ async markReadHandler(req, ctx) {
37
+ const auth = await opts.getAuth(req);
38
+ if (!auth)
39
+ return json({ error: "Unauthorized" }, 401);
40
+ const ok = await markRead(ctx.params.id, auth.user_id);
41
+ return ok ? json({ ok: true }) : json({ error: "Not found" }, 404);
42
+ },
43
+ async markAllReadHandler(req) {
44
+ const auth = await opts.getAuth(req);
45
+ if (!auth)
46
+ return json({ error: "Unauthorized" }, 401);
47
+ const n = await markAllRead(auth.user_id, auth.scope_id);
48
+ return json({ count: n });
49
+ },
50
+ };
51
+ }
52
+ //# sourceMappingURL=inbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbox.js","sourceRoot":"","sources":["../../../src/lib/api/inbox.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * from "./types.js";
2
+ export { registerChannel, getChannel, getRegisteredChannels, __resetChannelRegistry, } from "./registry.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/channels/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,OAAO,EACL,eAAe,EACf,UAAU,EACV,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from "./types.js";
2
+ export { registerChannel, getChannel, getRegisteredChannels, __resetChannelRegistry, } from "./registry.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/channels/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,OAAO,EACL,eAAe,EACf,UAAU,EACV,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { ChannelAdapter } from "./types.js";
2
+ export declare function registerChannel(adapter: ChannelAdapter): void;
3
+ export declare function getChannel(id: string): ChannelAdapter | null;
4
+ export declare function getRegisteredChannels(): ChannelAdapter[];
5
+ /** Test-only. */
6
+ export declare function __resetChannelRegistry(): void;
7
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/lib/channels/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAYjD,wBAAgB,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAM7D;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAE5D;AAED,wBAAgB,qBAAqB,IAAI,cAAc,EAAE,CAExD;AAED,iBAAiB;AACjB,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C"}
@@ -0,0 +1,24 @@
1
+ // Stash the registry on globalThis so it survives Next.js dev-mode module
2
+ // duplication — multiple route bundles each import this file, and without
3
+ // the global reference each evaluation gets its own copy of the Map.
4
+ const REGISTRY_KEY = "__hazo_notify_channel_registry__";
5
+ const g = globalThis;
6
+ const adapters = g[REGISTRY_KEY] ?? (g[REGISTRY_KEY] = new Map());
7
+ export function registerChannel(adapter) {
8
+ const id = adapter.capabilities.channel_id;
9
+ if (adapters.has(id)) {
10
+ throw new Error(`channel already registered: ${id}`);
11
+ }
12
+ adapters.set(id, adapter);
13
+ }
14
+ export function getChannel(id) {
15
+ return adapters.get(id) ?? null;
16
+ }
17
+ export function getRegisteredChannels() {
18
+ return [...adapters.values()];
19
+ }
20
+ /** Test-only. */
21
+ export function __resetChannelRegistry() {
22
+ adapters.clear();
23
+ }
24
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/lib/channels/registry.ts"],"names":[],"mappings":"AAEA,0EAA0E;AAC1E,0EAA0E;AAC1E,qEAAqE;AACrE,MAAM,YAAY,GAAG,kCAAkC,CAAC;AACxD,MAAM,CAAC,GAAG,UAET,CAAC;AACF,MAAM,QAAQ,GACZ,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,IAAI,GAAG,EAA0B,CAAC,CAAC;AAE3E,MAAM,UAAU,eAAe,CAAC,OAAuB;IACrD,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC;IAC3C,IAAI,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,+BAA+B,EAAE,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAU;IACnC,OAAO,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,iBAAiB;AACjB,MAAM,UAAU,sBAAsB;IACpC,QAAQ,CAAC,KAAK,EAAE,CAAC;AACnB,CAAC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Channel registry types. Adapters implement ChannelAdapter; consumers
3
+ * register them at boot via registerChannel() (see ./registry.ts).
4
+ *
5
+ * @packageDocumentation
6
+ */
7
+ /** A logger shape compatible with hazo_logs and the console fallback. */
8
+ export interface ChannelLogger {
9
+ info: (msg: string, meta?: unknown) => void;
10
+ error: (msg: string, meta?: unknown) => void;
11
+ }
12
+ /** Scope-level branding used by adapters that render envelopes (email today). */
13
+ export interface ScopeBranding {
14
+ brand_name: string | null;
15
+ logo_url: string | null;
16
+ }
17
+ /** What the adapter declares about itself. Used by validators + worker. */
18
+ export interface ChannelCapabilities {
19
+ /** Stable id used as the discriminator everywhere. */
20
+ channel_id: string;
21
+ /** Human label for admin UIs. */
22
+ display_name: string;
23
+ /** Which template body keys this channel consumes, nearest-fit first. */
24
+ template_body_keys: string[];
25
+ /** Hard text length cap. null = unbounded. */
26
+ max_text_length: number | null;
27
+ /** Adapter handles long-message splitting internally. */
28
+ splits_long_messages: boolean;
29
+ /** Whether this channel supports per-call recipient override. */
30
+ supports_explicit_recipient: boolean;
31
+ /** Retry policy. */
32
+ retry: {
33
+ max_attempts: number;
34
+ /** (attempt_count, retry_after_hint_ms?) => delay_ms */
35
+ backoff_ms: (attempt: number, hint?: number) => number;
36
+ };
37
+ }
38
+ /** Per-send context the worker hands the adapter. */
39
+ export interface ChannelSendContext {
40
+ inbox_id: string;
41
+ scope_id: string;
42
+ user_id: string;
43
+ /** Post-claim attempt counter (1 on first attempt). */
44
+ attempt_count: number;
45
+ recipient: string;
46
+ /** Pre-rendered template bodies keyed by body key. Empty if no template. */
47
+ rendered_bodies: Record<string, string>;
48
+ branding: ScopeBranding | null;
49
+ logger: ChannelLogger;
50
+ }
51
+ /** Result returned to the worker. */
52
+ export interface ChannelSendResult {
53
+ ok: boolean;
54
+ message_id?: string;
55
+ error?: string;
56
+ retryable?: boolean;
57
+ /** Optional Retry-After hint forwarded to retry.backoff_ms. */
58
+ retry_after_ms?: number;
59
+ }
60
+ /** Validation result returned from validate() before insert. */
61
+ export interface ChannelValidationResult {
62
+ ok: boolean;
63
+ errors?: string[];
64
+ }
65
+ /** Adapter contract. Pure outbound function. No DB, no template_manager. */
66
+ export interface ChannelAdapter<TPayload = Record<string, unknown>> {
67
+ readonly capabilities: ChannelCapabilities;
68
+ validate(payload: TPayload): ChannelValidationResult;
69
+ send(payload: TPayload, ctx: ChannelSendContext): Promise<ChannelSendResult>;
70
+ }
71
+ /**
72
+ * Augmented by adapter packages via module declaration merging:
73
+ * declare module 'hazo_notify/channels' {
74
+ * interface ChannelPayloadMap {
75
+ * email: EmailPayload;
76
+ * telegram: TelegramPayload;
77
+ * }
78
+ * }
79
+ */
80
+ export interface ChannelPayloadMap {
81
+ }
82
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/channels/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,yEAAyE;AACzE,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5C,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9C;AAED,iFAAiF;AACjF,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,2EAA2E;AAC3E,MAAM,WAAW,mBAAmB;IAClC,sDAAsD;IACtD,UAAU,EAAE,MAAM,CAAC;IACnB,iCAAiC;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,8CAA8C;IAC9C,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,yDAAyD;IACzD,oBAAoB,EAAE,OAAO,CAAC;IAC9B,iEAAiE;IACjE,2BAA2B,EAAE,OAAO,CAAC;IACrC,oBAAoB;IACpB,KAAK,EAAE;QACL,YAAY,EAAE,MAAM,CAAC;QACrB,wDAAwD;QACxD,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;KACxD,CAAC;CACH;AAED,qDAAqD;AACrD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IAC/B,MAAM,EAAE,aAAa,CAAC;CACvB;AAED,qCAAqC;AACrC,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,+DAA+D;IAC/D,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,gEAAgE;AAChE,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,4EAA4E;AAC5E,MAAM,WAAW,cAAc,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAChE,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,QAAQ,GAAG,uBAAuB,CAAC;IACrD,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAC9E;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;CAAG"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Channel registry types. Adapters implement ChannelAdapter; consumers
3
+ * register them at boot via registerChannel() (see ./registry.ts).
4
+ *
5
+ * @packageDocumentation
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/lib/channels/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Build a deterministic batch_key.
3
+ *
4
+ * - For windowed dispatches (batch_window_ms > 0): "{event}:{subject ?? _}:{user}".
5
+ * Two dispatches with the same key within the open window aggregate.
6
+ * - For immediate dispatches (batch_window_ms = 0): append ":imm:{uuid}" so the
7
+ * row is unique-per-call and never aggregates with anything.
8
+ *
9
+ * @param event_type - Caller-defined event name (e.g. "client.survey_submitted")
10
+ * @param subject_id - Grouping anchor; `null` for global events
11
+ * @param user_id - Recipient
12
+ * @param batch_window_ms - Aggregation window in ms; 0 means send-now (immediate mode)
13
+ */
14
+ export declare function buildBatchKey(event_type: string, subject_id: string | null, user_id: string, batch_window_ms: number): string;
15
+ //# sourceMappingURL=batch-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch-key.d.ts","sourceRoot":"","sources":["../../../src/lib/dispatcher/batch-key.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,MAAM,GACtB,MAAM,CAGR"}
@@ -0,0 +1,19 @@
1
+ import { randomUUID } from "crypto";
2
+ /**
3
+ * Build a deterministic batch_key.
4
+ *
5
+ * - For windowed dispatches (batch_window_ms > 0): "{event}:{subject ?? _}:{user}".
6
+ * Two dispatches with the same key within the open window aggregate.
7
+ * - For immediate dispatches (batch_window_ms = 0): append ":imm:{uuid}" so the
8
+ * row is unique-per-call and never aggregates with anything.
9
+ *
10
+ * @param event_type - Caller-defined event name (e.g. "client.survey_submitted")
11
+ * @param subject_id - Grouping anchor; `null` for global events
12
+ * @param user_id - Recipient
13
+ * @param batch_window_ms - Aggregation window in ms; 0 means send-now (immediate mode)
14
+ */
15
+ export function buildBatchKey(event_type, subject_id, user_id, batch_window_ms) {
16
+ const base = `${event_type}:${subject_id ?? "_"}:${user_id}`;
17
+ return batch_window_ms === 0 ? `${base}:imm:${randomUUID()}` : base;
18
+ }
19
+ //# sourceMappingURL=batch-key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch-key.js","sourceRoot":"","sources":["../../../src/lib/dispatcher/batch-key.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,aAAa,CAC3B,UAAkB,EAClB,UAAyB,EACzB,OAAe,EACf,eAAuB;IAEvB,MAAM,IAAI,GAAG,GAAG,UAAU,IAAI,UAAU,IAAI,GAAG,IAAI,OAAO,EAAE,CAAC;IAC7D,OAAO,eAAe,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,QAAQ,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACtE,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { DispatchInput, DispatchResult } from "../inbox/types.js";
2
+ export type { DispatchInput, DispatchResult } from "../inbox/types.js";
3
+ export declare function dispatch(input: DispatchInput): Promise<DispatchResult>;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/dispatcher/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEvE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAIvE,wBAAsB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAkE5E"}
@@ -0,0 +1,73 @@
1
+ import { getChannel } from "../channels/registry.js";
2
+ import { upsertInboxRow, upsertDelivery } from "../inbox/storage.js";
3
+ import { buildBatchKey } from "./batch-key.js";
4
+ const DEFAULT_BATCH_WINDOW_MS = 5 * 60000;
5
+ export async function dispatch(input) {
6
+ const enabled = Object.entries(input.channels)
7
+ .filter(([, on]) => on === true)
8
+ .map(([id]) => id);
9
+ // Validate against registry + adapter
10
+ for (const id of enabled) {
11
+ const adapter = getChannel(id);
12
+ if (!adapter)
13
+ throw new Error(`dispatch: no adapter registered for channel "${id}"`);
14
+ const payload = input.channel_payloads?.[id];
15
+ if (!payload)
16
+ throw new Error(`dispatch: channel_payloads.${id} required`);
17
+ const v = adapter.validate(payload);
18
+ if (!v.ok)
19
+ throw new Error(`dispatch: validation failed for ${id}: ${(v.errors ?? []).join("; ")}`);
20
+ }
21
+ if (input.recipient_user_ids.length === 0 || enabled.length === 0) {
22
+ return {
23
+ inbox_rows_upserted: 0, inbox_rows_inserted: 0, inbox_rows_aggregated: 0,
24
+ deliveries_created: 0, deliveries_refreshed: 0,
25
+ channels_dispatched: enabled,
26
+ };
27
+ }
28
+ const window_ms = input.batch_window_ms ?? DEFAULT_BATCH_WINDOW_MS;
29
+ const now = Date.now();
30
+ const batch_closed_at = window_ms === 0 ? new Date(now).toISOString() : null;
31
+ const flush_after = new Date(now + window_ms).toISOString();
32
+ let inserted = 0, aggregated = 0, deliveries_created = 0, deliveries_refreshed = 0;
33
+ for (const user_id of input.recipient_user_ids) {
34
+ const batch_key = buildBatchKey(input.event_type, input.subject_id, user_id, window_ms);
35
+ const inbox = await upsertInboxRow({
36
+ scope_id: input.scope_id,
37
+ user_id,
38
+ event_type: input.event_type,
39
+ subject_id: input.subject_id,
40
+ batch_key,
41
+ in_app_text: input.in_app_text,
42
+ deep_link: input.deep_link,
43
+ payload: input.payload ?? {},
44
+ surfaces: input.surfaces,
45
+ batch_closed_at,
46
+ });
47
+ if (inbox.inserted)
48
+ inserted++;
49
+ else
50
+ aggregated++;
51
+ for (const channel_id of enabled) {
52
+ const d = await upsertDelivery({
53
+ inbox_id: inbox.id,
54
+ channel_id,
55
+ payload: input.channel_payloads[channel_id],
56
+ flush_after,
57
+ });
58
+ if (d.inserted)
59
+ deliveries_created++;
60
+ else
61
+ deliveries_refreshed++;
62
+ }
63
+ }
64
+ return {
65
+ inbox_rows_upserted: inserted + aggregated,
66
+ inbox_rows_inserted: inserted,
67
+ inbox_rows_aggregated: aggregated,
68
+ deliveries_created,
69
+ deliveries_refreshed,
70
+ channels_dispatched: enabled,
71
+ };
72
+ }
73
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/dispatcher/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Inbox connection holder. Mirrors template_manager's pattern: caller
3
+ * provides a hazo_connect factory at boot via `initInbox()`; subsequent
4
+ * storage calls read the resolved instance from this module.
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+ import type { HazoConnectInstance } from "../template_manager/types.js";
9
+ export interface InitInboxOptions {
10
+ /** Factory returning (or resolving to) a hazo_connect instance. */
11
+ hazo_connect_factory: () => Promise<HazoConnectInstance> | HazoConnectInstance;
12
+ }
13
+ /** Boot-time init. Must be called before any dispatch() / worker call. */
14
+ export declare function initInbox(opts: InitInboxOptions): Promise<HazoConnectInstance>;
15
+ /** Internal: get the resolved instance. Throws if not initialised. */
16
+ export declare function getInboxConnection(): HazoConnectInstance;
17
+ /** Test-only: reset the holder. */
18
+ export declare function __resetInboxConnection(): void;
19
+ //# sourceMappingURL=connection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../../src/lib/inbox/connection.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAUxE,MAAM,WAAW,gBAAgB;IAC/B,mEAAmE;IACnE,oBAAoB,EAAE,MAAM,OAAO,CAAC,mBAAmB,CAAC,GAAG,mBAAmB,CAAC;CAChF;AAED,0EAA0E;AAC1E,wBAAsB,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CASpF;AAED,sEAAsE;AACtE,wBAAgB,kBAAkB,IAAI,mBAAmB,CAMxD;AAED,mCAAmC;AACnC,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Inbox connection holder. Mirrors template_manager's pattern: caller
3
+ * provides a hazo_connect factory at boot via `initInbox()`; subsequent
4
+ * storage calls read the resolved instance from this module.
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+ // Stash on globalThis so the resolved connection survives Next.js dev-mode
9
+ // module duplication. Each route bundle imports this file separately; the
10
+ // global reference unifies them.
11
+ const CONN_KEY = "__hazo_notify_inbox_connection__";
12
+ const g = globalThis;
13
+ /** Boot-time init. Must be called before any dispatch() / worker call. */
14
+ export async function initInbox(opts) {
15
+ const conn = await opts.hazo_connect_factory();
16
+ if (!conn.raw) {
17
+ throw new Error("initInbox: hazo_connect_factory must return an instance supporting raw SQL");
18
+ }
19
+ g[CONN_KEY] = conn;
20
+ return conn;
21
+ }
22
+ /** Internal: get the resolved instance. Throws if not initialised. */
23
+ export function getInboxConnection() {
24
+ const conn = g[CONN_KEY];
25
+ if (!conn) {
26
+ throw new Error("inbox: initInbox() must be called before storage access");
27
+ }
28
+ return conn;
29
+ }
30
+ /** Test-only: reset the holder. */
31
+ export function __resetInboxConnection() {
32
+ g[CONN_KEY] = null;
33
+ }
34
+ //# sourceMappingURL=connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../../src/lib/inbox/connection.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,2EAA2E;AAC3E,0EAA0E;AAC1E,iCAAiC;AACjC,MAAM,QAAQ,GAAG,kCAAkC,CAAC;AACpD,MAAM,CAAC,GAAG,UAET,CAAC;AAOF,0EAA0E;AAC1E,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAsB;IACpD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,oBAAoB,EAAE,CAAC;IAC/C,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACb,4EAA4E,CAC7E,CAAC;IACJ,CAAC;IACD,CAAC,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;IACnB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,kBAAkB;IAChC,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;IACzB,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,mCAAmC;AACnC,MAAM,UAAU,sBAAsB;IACpC,CAAC,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;AACrB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { PostgresDialect } from "./postgres.js";
2
+ import { SqliteDialect } from "./sqlite.js";
3
+ import type { InboxDialect } from "./types.js";
4
+ import type { HazoConnectInstance } from "../../template_manager/types.js";
5
+ export type DialectId = "postgres" | "sqlite";
6
+ export declare function pickDialect(conn: HazoConnectInstance): InboxDialect;
7
+ export { PostgresDialect, SqliteDialect };
8
+ export type { InboxDialect } from "./types.js";
9
+ export * from "./types.js";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/inbox/dialects/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAE3E,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAC;AAE9C,wBAAgB,WAAW,CAAC,IAAI,EAAE,mBAAmB,GAAG,YAAY,CAMnE;AAED,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,CAAC;AAC1C,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,cAAc,YAAY,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { PostgresDialect } from "./postgres.js";
2
+ import { SqliteDialect } from "./sqlite.js";
3
+ export function pickDialect(conn) {
4
+ // hazo_connect instances expose .type (added in hazo_connect v2.x).
5
+ // Fall back to Postgres if missing (legacy instances).
6
+ const t = conn.type;
7
+ if (t === "sqlite")
8
+ return SqliteDialect;
9
+ return PostgresDialect;
10
+ }
11
+ export { PostgresDialect, SqliteDialect };
12
+ export * from "./types.js";
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/lib/inbox/dialects/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAM5C,MAAM,UAAU,WAAW,CAAC,IAAyB;IACnD,oEAAoE;IACpE,uDAAuD;IACvD,MAAM,CAAC,GAAI,IAAwC,CAAC,IAAI,CAAC;IACzD,IAAI,CAAC,KAAK,QAAQ;QAAE,OAAO,aAAa,CAAC;IACzC,OAAO,eAAe,CAAC;AACzB,CAAC;AAED,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,CAAC;AAE1C,cAAc,YAAY,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { InboxDialect } from "./types.js";
2
+ export declare const PostgresDialect: InboxDialect;
3
+ //# sourceMappingURL=postgres.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../../../src/lib/inbox/dialects/postgres.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EAMb,MAAM,YAAY,CAAC;AAyDpB,eAAO,MAAM,eAAe,EAAE,YAsF7B,CAAC"}
@@ -0,0 +1,110 @@
1
+ const UPSERT_INBOX_SQL = `
2
+ INSERT INTO hazo_notify_inbox (
3
+ scope_id, user_id, event_type, subject_id, batch_key,
4
+ in_app_text, deep_link, payload, surfaces, batch_closed_at
5
+ ) VALUES (
6
+ $1, $2, $3, $4, $5,
7
+ $6, $7, $8::jsonb, $9::jsonb, $10
8
+ )
9
+ ON CONFLICT (batch_key) WHERE batch_closed_at IS NULL DO UPDATE SET
10
+ aggregate_count = hazo_notify_inbox.aggregate_count + 1,
11
+ in_app_text = EXCLUDED.in_app_text,
12
+ payload = EXCLUDED.payload,
13
+ updated_at = now()
14
+ RETURNING id, (xmax = 0) AS inserted
15
+ `;
16
+ const UPSERT_DELIVERY_SQL = `
17
+ INSERT INTO hazo_notify_channel_deliveries (
18
+ inbox_id, channel_id, payload, flush_after
19
+ ) VALUES (
20
+ $1, $2, $3::jsonb, $4
21
+ )
22
+ ON CONFLICT (inbox_id, channel_id) DO UPDATE SET
23
+ payload = EXCLUDED.payload,
24
+ flush_after = CASE WHEN hazo_notify_channel_deliveries.attempt_count = 0
25
+ THEN EXCLUDED.flush_after
26
+ ELSE hazo_notify_channel_deliveries.flush_after END,
27
+ updated_at = now()
28
+ RETURNING id, (xmax = 0) AS inserted, (attempt_count > 0) AS attempt_in_flight
29
+ `;
30
+ const CLAIM_SQL = `
31
+ WITH claimed AS (
32
+ SELECT id FROM hazo_notify_channel_deliveries
33
+ WHERE channel_id = $1 AND status = 'pending' AND flush_after <= now()
34
+ ORDER BY flush_after ASC
35
+ LIMIT $2
36
+ FOR UPDATE SKIP LOCKED
37
+ )
38
+ UPDATE hazo_notify_channel_deliveries d
39
+ SET attempt_count = d.attempt_count + 1,
40
+ updated_at = now()
41
+ FROM claimed
42
+ WHERE d.id = claimed.id
43
+ RETURNING
44
+ d.id AS delivery_id,
45
+ d.inbox_id,
46
+ d.channel_id,
47
+ d.payload,
48
+ d.attempt_count,
49
+ (SELECT user_id FROM hazo_notify_inbox WHERE id = d.inbox_id) AS user_id,
50
+ (SELECT scope_id FROM hazo_notify_inbox WHERE id = d.inbox_id) AS scope_id
51
+ `;
52
+ export const PostgresDialect = {
53
+ async upsertInboxRow(conn, i) {
54
+ const rows = await conn.raw(UPSERT_INBOX_SQL, [
55
+ i.scope_id, i.user_id, i.event_type, i.subject_id, i.batch_key,
56
+ i.in_app_text, i.deep_link,
57
+ JSON.stringify(i.payload),
58
+ JSON.stringify(i.surfaces),
59
+ i.batch_closed_at,
60
+ ]);
61
+ return { id: rows[0].id, inserted: rows[0].inserted === true };
62
+ },
63
+ async upsertDelivery(conn, i) {
64
+ const rows = await conn.raw(UPSERT_DELIVERY_SQL, [i.inbox_id, i.channel_id, JSON.stringify(i.payload), i.flush_after]);
65
+ return {
66
+ id: rows[0].id,
67
+ inserted: rows[0].inserted === true,
68
+ attempt_in_flight: rows[0].attempt_in_flight === true,
69
+ };
70
+ },
71
+ async claimDueDeliveries(conn, channel_id, batch_size) {
72
+ return await conn.raw(CLAIM_SQL, [channel_id, batch_size]);
73
+ },
74
+ async markDeliverySent(conn, id, message_id) {
75
+ await conn.raw(`UPDATE hazo_notify_channel_deliveries
76
+ SET status='sent', message_id=$2, finalized_at=now(), updated_at=now()
77
+ WHERE id=$1`, [id, message_id]);
78
+ },
79
+ async markDeliveryFailed(conn, id, error) {
80
+ await conn.raw(`UPDATE hazo_notify_channel_deliveries
81
+ SET status='failed', last_error=$2, finalized_at=now(), updated_at=now()
82
+ WHERE id=$1`, [id, error.slice(0, 1000)]);
83
+ },
84
+ async rescheduleDelivery(conn, id, flush_after, error) {
85
+ await conn.raw(`UPDATE hazo_notify_channel_deliveries
86
+ SET flush_after=$2, last_error=$3, updated_at=now()
87
+ WHERE id=$1`, [id, flush_after, error.slice(0, 1000)]);
88
+ },
89
+ async closeStaleBatches(conn, window_ms) {
90
+ const rows = await conn.raw(`UPDATE hazo_notify_inbox
91
+ SET batch_closed_at = now()
92
+ WHERE batch_closed_at IS NULL
93
+ AND created_at + interval '1 millisecond' * $1 < now()
94
+ RETURNING id`, [window_ms]);
95
+ return rows.length;
96
+ },
97
+ async purgeReadInbox(conn, older_than) {
98
+ const rows = await conn.raw(`DELETE FROM hazo_notify_inbox
99
+ WHERE read_at IS NOT NULL AND read_at < $1
100
+ RETURNING id`, [older_than]);
101
+ return rows.length;
102
+ },
103
+ async purgeFinalizedDeliveries(conn, older_than) {
104
+ const rows = await conn.raw(`DELETE FROM hazo_notify_channel_deliveries
105
+ WHERE finalized_at IS NOT NULL AND finalized_at < $1
106
+ RETURNING id`, [older_than]);
107
+ return rows.length;
108
+ },
109
+ };
110
+ //# sourceMappingURL=postgres.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres.js","sourceRoot":"","sources":["../../../../src/lib/inbox/dialects/postgres.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { InboxDialect } from "./types.js";
2
+ export declare const SqliteDialect: InboxDialect;
3
+ //# sourceMappingURL=sqlite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../../../src/lib/inbox/dialects/sqlite.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,YAAY,EAMb,MAAM,YAAY,CAAC;AAGpB,eAAO,MAAM,aAAa,EAAE,YAqI3B,CAAC"}