@brightchain/brightchain-api-lib 0.24.1 → 0.26.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 (244) hide show
  1. package/package.json +4 -3
  2. package/src/lib/application.d.ts +3 -14
  3. package/src/lib/application.d.ts.map +1 -1
  4. package/src/lib/application.js +121 -44
  5. package/src/lib/application.js.map +1 -1
  6. package/src/lib/auth/aclDocumentStore.d.ts +90 -0
  7. package/src/lib/auth/aclDocumentStore.d.ts.map +1 -0
  8. package/src/lib/auth/aclDocumentStore.js +155 -0
  9. package/src/lib/auth/aclDocumentStore.js.map +1 -0
  10. package/src/lib/auth/index.d.ts +4 -0
  11. package/src/lib/auth/index.d.ts.map +1 -1
  12. package/src/lib/auth/index.js +4 -0
  13. package/src/lib/auth/index.js.map +1 -1
  14. package/src/lib/auth/writeAclApiRouter.d.ts +32 -0
  15. package/src/lib/auth/writeAclApiRouter.d.ts.map +1 -0
  16. package/src/lib/auth/writeAclApiRouter.js +348 -0
  17. package/src/lib/auth/writeAclApiRouter.js.map +1 -0
  18. package/src/lib/auth/writeAclAuditLogger.d.ts +94 -0
  19. package/src/lib/auth/writeAclAuditLogger.d.ts.map +1 -0
  20. package/src/lib/auth/writeAclAuditLogger.js +143 -0
  21. package/src/lib/auth/writeAclAuditLogger.js.map +1 -0
  22. package/src/lib/auth/writeProofMiddleware.d.ts +39 -0
  23. package/src/lib/auth/writeProofMiddleware.d.ts.map +1 -0
  24. package/src/lib/auth/writeProofMiddleware.js +56 -0
  25. package/src/lib/auth/writeProofMiddleware.js.map +1 -0
  26. package/src/lib/availability/aclDocumentSyncHandler.d.ts +39 -0
  27. package/src/lib/availability/aclDocumentSyncHandler.d.ts.map +1 -0
  28. package/src/lib/availability/aclDocumentSyncHandler.js +81 -0
  29. package/src/lib/availability/aclDocumentSyncHandler.js.map +1 -0
  30. package/src/lib/availability/gossipService.d.ts +4 -1
  31. package/src/lib/availability/gossipService.d.ts.map +1 -1
  32. package/src/lib/availability/gossipService.js +15 -1
  33. package/src/lib/availability/gossipService.js.map +1 -1
  34. package/src/lib/availability/headUpdateSyncHandler.d.ts +32 -0
  35. package/src/lib/availability/headUpdateSyncHandler.d.ts.map +1 -0
  36. package/src/lib/availability/headUpdateSyncHandler.js +78 -0
  37. package/src/lib/availability/headUpdateSyncHandler.js.map +1 -0
  38. package/src/lib/availability/index.d.ts +2 -0
  39. package/src/lib/availability/index.d.ts.map +1 -1
  40. package/src/lib/availability/index.js +2 -0
  41. package/src/lib/availability/index.js.map +1 -1
  42. package/src/lib/constants.d.ts.map +1 -1
  43. package/src/lib/constants.js +2 -0
  44. package/src/lib/constants.js.map +1 -1
  45. package/src/lib/controllers/api/brighthub/connectionController.d.ts +6 -0
  46. package/src/lib/controllers/api/brighthub/connectionController.d.ts.map +1 -1
  47. package/src/lib/controllers/api/brighthub/connectionController.js +158 -11
  48. package/src/lib/controllers/api/brighthub/connectionController.js.map +1 -1
  49. package/src/lib/controllers/api/brighthub/messagingController.d.ts +6 -0
  50. package/src/lib/controllers/api/brighthub/messagingController.d.ts.map +1 -1
  51. package/src/lib/controllers/api/brighthub/messagingController.js +190 -58
  52. package/src/lib/controllers/api/brighthub/messagingController.js.map +1 -1
  53. package/src/lib/controllers/api/brighthub/postController.d.ts +12 -3
  54. package/src/lib/controllers/api/brighthub/postController.d.ts.map +1 -1
  55. package/src/lib/controllers/api/brighthub/postController.js +60 -0
  56. package/src/lib/controllers/api/brighthub/postController.js.map +1 -1
  57. package/src/lib/controllers/api/brighthub/timelineController.d.ts +19 -0
  58. package/src/lib/controllers/api/brighthub/timelineController.d.ts.map +1 -1
  59. package/src/lib/controllers/api/brighthub/timelineController.js +133 -0
  60. package/src/lib/controllers/api/brighthub/timelineController.js.map +1 -1
  61. package/src/lib/controllers/api/emails.d.ts +4 -1
  62. package/src/lib/controllers/api/emails.d.ts.map +1 -1
  63. package/src/lib/controllers/api/emails.js +28 -1
  64. package/src/lib/controllers/api/emails.js.map +1 -1
  65. package/src/lib/controllers/api/user.d.ts.map +1 -1
  66. package/src/lib/controllers/api/user.js +10 -0
  67. package/src/lib/controllers/api/user.js.map +1 -1
  68. package/src/lib/databaseInit.d.ts +7 -11
  69. package/src/lib/databaseInit.d.ts.map +1 -1
  70. package/src/lib/databaseInit.js +41 -97
  71. package/src/lib/databaseInit.js.map +1 -1
  72. package/src/lib/datastore/block-document-store-factory.d.ts +3 -0
  73. package/src/lib/datastore/block-document-store-factory.d.ts.map +1 -1
  74. package/src/lib/datastore/block-document-store-factory.js +15 -18
  75. package/src/lib/datastore/block-document-store-factory.js.map +1 -1
  76. package/src/lib/datastore/block-document-store.d.ts +2 -191
  77. package/src/lib/datastore/block-document-store.d.ts.map +1 -1
  78. package/src/lib/datastore/block-document-store.js +4 -628
  79. package/src/lib/datastore/block-document-store.js.map +1 -1
  80. package/src/lib/datastore/document-store.d.ts +1 -62
  81. package/src/lib/datastore/document-store.d.ts.map +1 -1
  82. package/src/lib/datastore/memory-document-store.d.ts +1 -8
  83. package/src/lib/datastore/memory-document-store.d.ts.map +1 -1
  84. package/src/lib/datastore/memory-document-store.js +3 -214
  85. package/src/lib/datastore/memory-document-store.js.map +1 -1
  86. package/src/lib/environment.d.ts +3 -20
  87. package/src/lib/environment.d.ts.map +1 -1
  88. package/src/lib/environment.js +2 -45
  89. package/src/lib/environment.js.map +1 -1
  90. package/src/lib/factories/blockStoreFactory.d.ts.map +1 -1
  91. package/src/lib/factories/blockStoreFactory.js +4 -1
  92. package/src/lib/factories/blockStoreFactory.js.map +1 -1
  93. package/src/lib/interfaces/environment.d.ts +23 -2
  94. package/src/lib/interfaces/environment.d.ts.map +1 -1
  95. package/src/lib/interfaces/responses/brighthub/api-post-response.d.ts +8 -1
  96. package/src/lib/interfaces/responses/brighthub/api-post-response.d.ts.map +1 -1
  97. package/src/lib/middleware/index.d.ts +1 -1
  98. package/src/lib/middleware/index.d.ts.map +1 -1
  99. package/src/lib/middleware/index.js +3 -2
  100. package/src/lib/middleware/index.js.map +1 -1
  101. package/src/lib/middleware/validateBody.d.ts +1 -12
  102. package/src/lib/middleware/validateBody.d.ts.map +1 -1
  103. package/src/lib/middleware/validateBody.js +4 -32
  104. package/src/lib/middleware/validateBody.js.map +1 -1
  105. package/src/lib/middlewares.d.ts.map +1 -1
  106. package/src/lib/middlewares.js +7 -1
  107. package/src/lib/middlewares.js.map +1 -1
  108. package/src/lib/plugins/brightchain-database-plugin.d.ts +27 -79
  109. package/src/lib/plugins/brightchain-database-plugin.d.ts.map +1 -1
  110. package/src/lib/plugins/brightchain-database-plugin.js +27 -97
  111. package/src/lib/plugins/brightchain-database-plugin.js.map +1 -1
  112. package/src/lib/routers/api.d.ts +18 -1
  113. package/src/lib/routers/api.d.ts.map +1 -1
  114. package/src/lib/routers/api.js +24 -1
  115. package/src/lib/routers/api.js.map +1 -1
  116. package/src/lib/routers/app.d.ts.map +1 -1
  117. package/src/lib/routers/app.js +5 -2
  118. package/src/lib/routers/app.js.map +1 -1
  119. package/src/lib/services/auth.d.ts.map +1 -1
  120. package/src/lib/services/auth.js +37 -3
  121. package/src/lib/services/auth.js.map +1 -1
  122. package/src/lib/services/blockStore.d.ts +8 -1
  123. package/src/lib/services/blockStore.d.ts.map +1 -1
  124. package/src/lib/services/blockStore.js +19 -7
  125. package/src/lib/services/blockStore.js.map +1 -1
  126. package/src/lib/services/brightChainBackupCodeService.d.ts +42 -39
  127. package/src/lib/services/brightChainBackupCodeService.d.ts.map +1 -1
  128. package/src/lib/services/brightChainBackupCodeService.js +86 -61
  129. package/src/lib/services/brightChainBackupCodeService.js.map +1 -1
  130. package/src/lib/services/brighthub/collectionAdapter.d.ts +81 -0
  131. package/src/lib/services/brighthub/collectionAdapter.d.ts.map +1 -0
  132. package/src/lib/services/brighthub/collectionAdapter.js +127 -0
  133. package/src/lib/services/brighthub/collectionAdapter.js.map +1 -0
  134. package/src/lib/services/brighthub/connectionService.d.ts.map +1 -1
  135. package/src/lib/services/brighthub/connectionService.js +3 -0
  136. package/src/lib/services/brighthub/connectionService.js.map +1 -1
  137. package/src/lib/services/brighthub/messagingService.d.ts +4 -0
  138. package/src/lib/services/brighthub/messagingService.d.ts.map +1 -1
  139. package/src/lib/services/brighthub/messagingService.js +25 -4
  140. package/src/lib/services/brighthub/messagingService.js.map +1 -1
  141. package/src/lib/services/brighthub/notificationService.d.ts.map +1 -1
  142. package/src/lib/services/brighthub/notificationService.js +35 -20
  143. package/src/lib/services/brighthub/notificationService.js.map +1 -1
  144. package/src/lib/services/brighthub/postService.d.ts +7 -1
  145. package/src/lib/services/brighthub/postService.d.ts.map +1 -1
  146. package/src/lib/services/brighthub/postService.js +22 -1
  147. package/src/lib/services/brighthub/postService.js.map +1 -1
  148. package/src/lib/services/brighthub/userProfileService.d.ts +19 -1
  149. package/src/lib/services/brighthub/userProfileService.d.ts.map +1 -1
  150. package/src/lib/services/brighthub/userProfileService.js +74 -0
  151. package/src/lib/services/brighthub/userProfileService.js.map +1 -1
  152. package/src/lib/services/emailGateway/antiSpamFilter.d.ts +229 -0
  153. package/src/lib/services/emailGateway/antiSpamFilter.d.ts.map +1 -0
  154. package/src/lib/services/emailGateway/antiSpamFilter.js +325 -0
  155. package/src/lib/services/emailGateway/antiSpamFilter.js.map +1 -0
  156. package/src/lib/services/emailGateway/bounceProcessor.d.ts +171 -0
  157. package/src/lib/services/emailGateway/bounceProcessor.d.ts.map +1 -0
  158. package/src/lib/services/emailGateway/bounceProcessor.js +378 -0
  159. package/src/lib/services/emailGateway/bounceProcessor.js.map +1 -0
  160. package/src/lib/services/emailGateway/emailAuthVerifier.d.ts +99 -0
  161. package/src/lib/services/emailGateway/emailAuthVerifier.d.ts.map +1 -0
  162. package/src/lib/services/emailGateway/emailAuthVerifier.js +202 -0
  163. package/src/lib/services/emailGateway/emailAuthVerifier.js.map +1 -0
  164. package/src/lib/services/emailGateway/emailGatewayConfig.d.ts +73 -0
  165. package/src/lib/services/emailGateway/emailGatewayConfig.d.ts.map +1 -0
  166. package/src/lib/services/emailGateway/emailGatewayConfig.js +107 -0
  167. package/src/lib/services/emailGateway/emailGatewayConfig.js.map +1 -0
  168. package/src/lib/services/emailGateway/emailGatewayService.d.ts +152 -0
  169. package/src/lib/services/emailGateway/emailGatewayService.d.ts.map +1 -0
  170. package/src/lib/services/emailGateway/emailGatewayService.js +201 -0
  171. package/src/lib/services/emailGateway/emailGatewayService.js.map +1 -0
  172. package/src/lib/services/emailGateway/gatewayObservability.d.ts +123 -0
  173. package/src/lib/services/emailGateway/gatewayObservability.d.ts.map +1 -0
  174. package/src/lib/services/emailGateway/gatewayObservability.js +186 -0
  175. package/src/lib/services/emailGateway/gatewayObservability.js.map +1 -0
  176. package/src/lib/services/emailGateway/inboundProcessor.d.ts +113 -0
  177. package/src/lib/services/emailGateway/inboundProcessor.d.ts.map +1 -0
  178. package/src/lib/services/emailGateway/inboundProcessor.js +298 -0
  179. package/src/lib/services/emailGateway/inboundProcessor.js.map +1 -0
  180. package/src/lib/services/emailGateway/index.d.ts +23 -0
  181. package/src/lib/services/emailGateway/index.d.ts.map +1 -0
  182. package/src/lib/services/emailGateway/index.js +26 -0
  183. package/src/lib/services/emailGateway/index.js.map +1 -0
  184. package/src/lib/services/emailGateway/outboundDeliveryWorker.d.ts +111 -0
  185. package/src/lib/services/emailGateway/outboundDeliveryWorker.d.ts.map +1 -0
  186. package/src/lib/services/emailGateway/outboundDeliveryWorker.js +97 -0
  187. package/src/lib/services/emailGateway/outboundDeliveryWorker.js.map +1 -0
  188. package/src/lib/services/emailGateway/outboundQueue.d.ts +135 -0
  189. package/src/lib/services/emailGateway/outboundQueue.d.ts.map +1 -0
  190. package/src/lib/services/emailGateway/outboundQueue.js +227 -0
  191. package/src/lib/services/emailGateway/outboundQueue.js.map +1 -0
  192. package/src/lib/services/emailGateway/outboundQueueStore.d.ts +110 -0
  193. package/src/lib/services/emailGateway/outboundQueueStore.d.ts.map +1 -0
  194. package/src/lib/services/emailGateway/outboundQueueStore.js +131 -0
  195. package/src/lib/services/emailGateway/outboundQueueStore.js.map +1 -0
  196. package/src/lib/services/emailGateway/recipientLookupService.d.ts +135 -0
  197. package/src/lib/services/emailGateway/recipientLookupService.d.ts.map +1 -0
  198. package/src/lib/services/emailGateway/recipientLookupService.js +294 -0
  199. package/src/lib/services/emailGateway/recipientLookupService.js.map +1 -0
  200. package/src/lib/services/emailGateway/retryBackoff.d.ts +79 -0
  201. package/src/lib/services/emailGateway/retryBackoff.d.ts.map +1 -0
  202. package/src/lib/services/emailGateway/retryBackoff.js +77 -0
  203. package/src/lib/services/emailGateway/retryBackoff.js.map +1 -0
  204. package/src/lib/services/eventNotificationSystem.d.ts.map +1 -1
  205. package/src/lib/services/eventNotificationSystem.js.map +1 -1
  206. package/src/lib/services/index.d.ts +2 -1
  207. package/src/lib/services/index.d.ts.map +1 -1
  208. package/src/lib/services/index.js +2 -1
  209. package/src/lib/services/index.js.map +1 -1
  210. package/src/lib/services/quorumDatabaseAdapter.d.ts +7 -1
  211. package/src/lib/services/quorumDatabaseAdapter.d.ts.map +1 -1
  212. package/src/lib/services/quorumDatabaseAdapter.js +83 -0
  213. package/src/lib/services/quorumDatabaseAdapter.js.map +1 -1
  214. package/src/lib/services/sessionAdapter.d.ts +2 -61
  215. package/src/lib/services/sessionAdapter.d.ts.map +1 -1
  216. package/src/lib/services/sessionAdapter.js +2 -102
  217. package/src/lib/services/sessionAdapter.js.map +1 -1
  218. package/src/lib/shared-types.d.ts +7 -15
  219. package/src/lib/shared-types.d.ts.map +1 -1
  220. package/src/lib/stores/availabilityAwareBlockStore.d.ts +4 -3
  221. package/src/lib/stores/availabilityAwareBlockStore.d.ts.map +1 -1
  222. package/src/lib/stores/availabilityAwareBlockStore.js +5 -2
  223. package/src/lib/stores/availabilityAwareBlockStore.js.map +1 -1
  224. package/src/lib/stores/cloudBlockStoreBase.d.ts +2 -1
  225. package/src/lib/stores/cloudBlockStoreBase.d.ts.map +1 -1
  226. package/src/lib/stores/cloudBlockStoreBase.js +34 -13
  227. package/src/lib/stores/cloudBlockStoreBase.js.map +1 -1
  228. package/src/lib/stores/diskBlockAsyncStore.d.ts +21 -1
  229. package/src/lib/stores/diskBlockAsyncStore.d.ts.map +1 -1
  230. package/src/lib/stores/diskBlockAsyncStore.js +48 -17
  231. package/src/lib/stores/diskBlockAsyncStore.js.map +1 -1
  232. package/src/lib/stores/diskBlockStore.d.ts +10 -2
  233. package/src/lib/stores/diskBlockStore.d.ts.map +1 -1
  234. package/src/lib/stores/diskBlockStore.js +43 -19
  235. package/src/lib/stores/diskBlockStore.js.map +1 -1
  236. package/src/lib/types/backend-id.d.ts +1 -2
  237. package/src/lib/types/backend-id.d.ts.map +1 -1
  238. package/src/lib/utils/emailValidation.d.ts.map +1 -1
  239. package/src/lib/utils/emailValidation.js +2 -1
  240. package/src/lib/utils/emailValidation.js.map +1 -1
  241. package/src/lib/validation/userValidation.d.ts +2 -43
  242. package/src/lib/validation/userValidation.d.ts.map +1 -1
  243. package/src/lib/validation/userValidation.js +6 -144
  244. package/src/lib/validation/userValidation.js.map +1 -1
@@ -0,0 +1,135 @@
1
+ /**
2
+ * OutboundQueue — persistent FIFO queue with concurrency control for
3
+ * outbound email delivery.
4
+ *
5
+ * Wraps an `IOutboundQueueStore` for persistence and enforces a configurable
6
+ * concurrency limit on simultaneous deliveries. The processing loop dequeues
7
+ * items and passes them to a handler callback.
8
+ *
9
+ * On `start()`, the queue resumes processing any previously queued messages
10
+ * that have not exceeded the maximum retry duration (Req 9.2).
11
+ *
12
+ * @see Requirements 9.1, 9.2, 9.3, 9.4, 9.5
13
+ * @module outboundQueue
14
+ */
15
+ import type { IEmailGatewayConfig } from './emailGatewayConfig';
16
+ import type { IOutboundQueue, IOutboundQueueItem } from './emailGatewayService';
17
+ import type { IOutboundQueueStore } from './outboundQueueStore';
18
+ /**
19
+ * Callback invoked for each dequeued item. The handler is responsible for
20
+ * performing the actual SMTP delivery (or delegating to a worker).
21
+ *
22
+ * @param item - The dequeued outbound queue item
23
+ * @returns Resolves when the handler has finished processing the item
24
+ */
25
+ export type OutboundQueueHandler = (item: IOutboundQueueItem) => Promise<void>;
26
+ /**
27
+ * Persistent FIFO outbound email queue with concurrency control.
28
+ *
29
+ * Implements `IOutboundQueue` so the `EmailGatewayService` orchestrator
30
+ * can enqueue messages without knowing about concurrency or persistence
31
+ * internals.
32
+ *
33
+ * @see Requirements 9.1, 9.2, 9.3, 9.4, 9.5
34
+ */
35
+ export declare class OutboundQueue implements IOutboundQueue {
36
+ private readonly store;
37
+ private readonly config;
38
+ private handler?;
39
+ /** Whether the processing loop is active. */
40
+ private running;
41
+ /** Number of items currently being processed by the handler. */
42
+ private activeCount;
43
+ /** Handle for the polling interval so we can clear it on stop(). */
44
+ private pollTimer;
45
+ /** Polling interval in milliseconds for the processing loop. */
46
+ private readonly pollIntervalMs;
47
+ /**
48
+ * @param store - Persistence backend for queue items
49
+ * @param config - Gateway configuration (concurrency, retry settings)
50
+ * @param handler - Callback invoked for each dequeued item
51
+ * @param pollIntervalMs - How often to poll the store for ready items (default: 1000ms)
52
+ */
53
+ constructor(store: IOutboundQueueStore, config: IEmailGatewayConfig, handler?: OutboundQueueHandler | undefined, pollIntervalMs?: number);
54
+ /**
55
+ * Set or replace the delivery handler callback.
56
+ */
57
+ setHandler(handler: OutboundQueueHandler): void;
58
+ /**
59
+ * Enqueue a message for outbound delivery.
60
+ *
61
+ * Persists the item to the store. Rejects with an error if the store
62
+ * is unavailable (Req 9.5).
63
+ *
64
+ * @param item - The outbound queue item to enqueue
65
+ * @throws Error if the store is unavailable
66
+ *
67
+ * @see Requirement 9.5
68
+ */
69
+ enqueue(item: IOutboundQueueItem): Promise<void>;
70
+ /**
71
+ * Start the processing loop.
72
+ *
73
+ * On startup, resumes processing any previously queued messages that
74
+ * have not exceeded the maximum retry duration (Req 9.2). Then begins
75
+ * polling the store for new items.
76
+ *
77
+ * @see Requirements 9.2, 9.4
78
+ */
79
+ start(): Promise<void>;
80
+ /**
81
+ * Stop the processing loop.
82
+ *
83
+ * Clears the polling timer. In-flight handler invocations are allowed
84
+ * to complete but no new items will be dequeued.
85
+ */
86
+ stop(): void;
87
+ /**
88
+ * Whether the queue processing loop is currently running.
89
+ */
90
+ isRunning(): boolean;
91
+ /**
92
+ * The number of items currently being processed (in-flight).
93
+ */
94
+ getActiveCount(): number;
95
+ /**
96
+ * The current queue depth (delegated to the store).
97
+ */
98
+ getQueueDepth(): Promise<number>;
99
+ /**
100
+ * Resume processing items that were queued before the last shutdown.
101
+ *
102
+ * Walks the store and expires any items that have exceeded the maximum
103
+ * retry duration, then triggers a processing pass for the rest.
104
+ *
105
+ * @see Requirement 9.2
106
+ */
107
+ private resumeExistingItems;
108
+ /**
109
+ * Dequeue and process items up to the concurrency limit.
110
+ *
111
+ * Each dequeued item is handed to the handler callback. The concurrency
112
+ * limit (Req 9.4) is enforced by tracking `activeCount`.
113
+ */
114
+ private processAvailable;
115
+ /**
116
+ * Process a single dequeued item by invoking the handler.
117
+ *
118
+ * If the handler throws, the item is checked against retry limits.
119
+ * If eligible for retry, it is requeued with an exponential back-off
120
+ * delay. If limits are exceeded, it is marked as permanently failed.
121
+ *
122
+ * @see Requirements 3.1, 3.3, 3.4
123
+ */
124
+ private processItem;
125
+ /**
126
+ * Determine whether a queue item has exceeded the maximum retry duration.
127
+ *
128
+ * @param item - The queue item to check
129
+ * @returns `true` if the item's age exceeds `config.retryMaxDurationMs`
130
+ *
131
+ * @see Requirement 9.2
132
+ */
133
+ private isExpired;
134
+ }
135
+ //# sourceMappingURL=outboundQueue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outboundQueue.d.ts","sourceRoot":"","sources":["../../../../../../brightchain-api-lib/src/lib/services/emailGateway/outboundQueue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAGhE;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,IAAI,EAAE,kBAAkB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAE/E;;;;;;;;GAQG;AACH,qBAAa,aAAc,YAAW,cAAc;IAoBhD,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,OAAO,CAAC;IArBlB,6CAA6C;IAC7C,OAAO,CAAC,OAAO,CAAS;IAExB,gEAAgE;IAChE,OAAO,CAAC,WAAW,CAAK;IAExB,oEAAoE;IACpE,OAAO,CAAC,SAAS,CAA+C;IAEhE,gEAAgE;IAChE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IAExC;;;;;OAKG;gBAEgB,KAAK,EAAE,mBAAmB,EAC1B,MAAM,EAAE,mBAAmB,EACpC,OAAO,CAAC,EAAE,oBAAoB,YAAA,EACtC,cAAc,CAAC,EAAE,MAAM;IAOzB;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI;IAI/C;;;;;;;;;;OAUG;IACG,OAAO,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAUtD;;;;;;;;OAQG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAe5B;;;;;OAKG;IACH,IAAI,IAAI,IAAI;IAWZ;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,cAAc,IAAI,MAAM;IAIxB;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAMtC;;;;;;;OAOG;YACW,mBAAmB;IAMjC;;;;;OAKG;YACW,gBAAgB;IA6B9B;;;;;;;;OAQG;YACW,WAAW;IAmCzB;;;;;;;OAOG;IACH,OAAO,CAAC,SAAS;CAIlB"}
@@ -0,0 +1,227 @@
1
+ "use strict";
2
+ /**
3
+ * OutboundQueue — persistent FIFO queue with concurrency control for
4
+ * outbound email delivery.
5
+ *
6
+ * Wraps an `IOutboundQueueStore` for persistence and enforces a configurable
7
+ * concurrency limit on simultaneous deliveries. The processing loop dequeues
8
+ * items and passes them to a handler callback.
9
+ *
10
+ * On `start()`, the queue resumes processing any previously queued messages
11
+ * that have not exceeded the maximum retry duration (Req 9.2).
12
+ *
13
+ * @see Requirements 9.1, 9.2, 9.3, 9.4, 9.5
14
+ * @module outboundQueue
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.OutboundQueue = void 0;
18
+ const brightchain_lib_1 = require("@brightchain/brightchain-lib");
19
+ const retryBackoff_1 = require("./retryBackoff");
20
+ /**
21
+ * Persistent FIFO outbound email queue with concurrency control.
22
+ *
23
+ * Implements `IOutboundQueue` so the `EmailGatewayService` orchestrator
24
+ * can enqueue messages without knowing about concurrency or persistence
25
+ * internals.
26
+ *
27
+ * @see Requirements 9.1, 9.2, 9.3, 9.4, 9.5
28
+ */
29
+ class OutboundQueue {
30
+ store;
31
+ config;
32
+ handler;
33
+ /** Whether the processing loop is active. */
34
+ running = false;
35
+ /** Number of items currently being processed by the handler. */
36
+ activeCount = 0;
37
+ /** Handle for the polling interval so we can clear it on stop(). */
38
+ pollTimer = null;
39
+ /** Polling interval in milliseconds for the processing loop. */
40
+ pollIntervalMs;
41
+ /**
42
+ * @param store - Persistence backend for queue items
43
+ * @param config - Gateway configuration (concurrency, retry settings)
44
+ * @param handler - Callback invoked for each dequeued item
45
+ * @param pollIntervalMs - How often to poll the store for ready items (default: 1000ms)
46
+ */
47
+ constructor(store, config, handler, pollIntervalMs) {
48
+ this.store = store;
49
+ this.config = config;
50
+ this.handler = handler;
51
+ this.pollIntervalMs = pollIntervalMs ?? 1000;
52
+ }
53
+ // ─── Public API ─────────────────────────────────────────────────────
54
+ /**
55
+ * Set or replace the delivery handler callback.
56
+ */
57
+ setHandler(handler) {
58
+ this.handler = handler;
59
+ }
60
+ /**
61
+ * Enqueue a message for outbound delivery.
62
+ *
63
+ * Persists the item to the store. Rejects with an error if the store
64
+ * is unavailable (Req 9.5).
65
+ *
66
+ * @param item - The outbound queue item to enqueue
67
+ * @throws Error if the store is unavailable
68
+ *
69
+ * @see Requirement 9.5
70
+ */
71
+ async enqueue(item) {
72
+ try {
73
+ await this.store.enqueue(item);
74
+ }
75
+ catch (err) {
76
+ throw new Error(`Outbound queue store unavailable: ${err instanceof Error ? err.message : String(err)}`);
77
+ }
78
+ }
79
+ /**
80
+ * Start the processing loop.
81
+ *
82
+ * On startup, resumes processing any previously queued messages that
83
+ * have not exceeded the maximum retry duration (Req 9.2). Then begins
84
+ * polling the store for new items.
85
+ *
86
+ * @see Requirements 9.2, 9.4
87
+ */
88
+ async start() {
89
+ if (this.running) {
90
+ return;
91
+ }
92
+ this.running = true;
93
+ // Resume: process any items already in the store that are still valid.
94
+ await this.resumeExistingItems();
95
+ // Start the polling loop.
96
+ this.pollTimer = setInterval(() => {
97
+ void this.processAvailable();
98
+ }, this.pollIntervalMs);
99
+ }
100
+ /**
101
+ * Stop the processing loop.
102
+ *
103
+ * Clears the polling timer. In-flight handler invocations are allowed
104
+ * to complete but no new items will be dequeued.
105
+ */
106
+ stop() {
107
+ if (!this.running) {
108
+ return;
109
+ }
110
+ this.running = false;
111
+ if (this.pollTimer !== null) {
112
+ clearInterval(this.pollTimer);
113
+ this.pollTimer = null;
114
+ }
115
+ }
116
+ /**
117
+ * Whether the queue processing loop is currently running.
118
+ */
119
+ isRunning() {
120
+ return this.running;
121
+ }
122
+ /**
123
+ * The number of items currently being processed (in-flight).
124
+ */
125
+ getActiveCount() {
126
+ return this.activeCount;
127
+ }
128
+ /**
129
+ * The current queue depth (delegated to the store).
130
+ */
131
+ async getQueueDepth() {
132
+ return this.store.getQueueDepth();
133
+ }
134
+ // ─── Internal Processing ────────────────────────────────────────────
135
+ /**
136
+ * Resume processing items that were queued before the last shutdown.
137
+ *
138
+ * Walks the store and expires any items that have exceeded the maximum
139
+ * retry duration, then triggers a processing pass for the rest.
140
+ *
141
+ * @see Requirement 9.2
142
+ */
143
+ async resumeExistingItems() {
144
+ // We process available items which will naturally skip expired ones
145
+ // via the dequeue + expiry check in processItem.
146
+ await this.processAvailable();
147
+ }
148
+ /**
149
+ * Dequeue and process items up to the concurrency limit.
150
+ *
151
+ * Each dequeued item is handed to the handler callback. The concurrency
152
+ * limit (Req 9.4) is enforced by tracking `activeCount`.
153
+ */
154
+ async processAvailable() {
155
+ if (!this.running || !this.handler) {
156
+ return;
157
+ }
158
+ while (this.activeCount < this.config.queueConcurrency && this.running) {
159
+ const item = await this.store.dequeue();
160
+ if (!item) {
161
+ // No more items ready for processing.
162
+ break;
163
+ }
164
+ // Check if the item has exceeded the max retry duration (Req 9.2).
165
+ if (this.isExpired(item)) {
166
+ await this.store.markFailed(item.messageId, 'Maximum retry duration exceeded');
167
+ continue;
168
+ }
169
+ // Process the item with concurrency tracking.
170
+ this.activeCount++;
171
+ void this.processItem(item).finally(() => {
172
+ this.activeCount--;
173
+ });
174
+ }
175
+ }
176
+ /**
177
+ * Process a single dequeued item by invoking the handler.
178
+ *
179
+ * If the handler throws, the item is checked against retry limits.
180
+ * If eligible for retry, it is requeued with an exponential back-off
181
+ * delay. If limits are exceeded, it is marked as permanently failed.
182
+ *
183
+ * @see Requirements 3.1, 3.3, 3.4
184
+ */
185
+ async processItem(item) {
186
+ if (!this.handler) {
187
+ return;
188
+ }
189
+ try {
190
+ await this.handler(item);
191
+ }
192
+ catch {
193
+ // Handler failed — check if the item is eligible for retry.
194
+ const nextRetryCount = item.retryCount + 1;
195
+ const retryCandidate = { retryCount: nextRetryCount, enqueuedAt: item.enqueuedAt };
196
+ if ((0, retryBackoff_1.shouldRetry)(retryCandidate, this.config)) {
197
+ // Eligible for retry — requeue with back-off delay.
198
+ const nextAttemptAt = (0, retryBackoff_1.computeNextAttemptAt)(this.config.retryBaseIntervalMs, item.retryCount);
199
+ const requeued = {
200
+ ...item,
201
+ status: brightchain_lib_1.OutboundDeliveryStatus.Queued,
202
+ retryCount: nextRetryCount,
203
+ nextAttemptAt,
204
+ };
205
+ await this.store.requeue(requeued);
206
+ }
207
+ else {
208
+ // Retry limits exceeded — mark permanently failed (Req 3.4).
209
+ await this.store.markFailed(item.messageId, `Retry limits exceeded (retryCount=${nextRetryCount}, maxCount=${this.config.retryMaxCount}, maxDuration=${this.config.retryMaxDurationMs}ms)`);
210
+ }
211
+ }
212
+ }
213
+ /**
214
+ * Determine whether a queue item has exceeded the maximum retry duration.
215
+ *
216
+ * @param item - The queue item to check
217
+ * @returns `true` if the item's age exceeds `config.retryMaxDurationMs`
218
+ *
219
+ * @see Requirement 9.2
220
+ */
221
+ isExpired(item) {
222
+ const age = Date.now() - item.enqueuedAt.getTime();
223
+ return age > this.config.retryMaxDurationMs;
224
+ }
225
+ }
226
+ exports.OutboundQueue = OutboundQueue;
227
+ //# sourceMappingURL=outboundQueue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outboundQueue.js","sourceRoot":"","sources":["../../../../../../brightchain-api-lib/src/lib/services/emailGateway/outboundQueue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Outbound Queue Store — persistence interface and in-memory implementation
3
+ * for the outbound email delivery queue.
4
+ *
5
+ * The `IOutboundQueueStore` interface defines the contract for queue persistence,
6
+ * allowing different backends (in-memory for testing, database/filesystem for
7
+ * production) to be swapped without changing the queue logic.
8
+ *
9
+ * The `InMemoryOutboundQueueStore` provides a FIFO-ordered, Map-backed
10
+ * implementation suitable for unit/integration testing.
11
+ *
12
+ * @see Requirements 9.1, 9.3, 9.4
13
+ * @module outboundQueueStore
14
+ */
15
+ import type { IOutboundQueueItem } from './emailGatewayService';
16
+ /**
17
+ * Persistence interface for the outbound email delivery queue.
18
+ *
19
+ * Implementations must maintain FIFO ordering (Req 9.3) and support
20
+ * concurrent access patterns (Req 9.4). The store is responsible only
21
+ * for persistence — concurrency limiting and processing loops are
22
+ * handled by the `OutboundQueue` class (task 4.2).
23
+ *
24
+ * @see Requirements 9.1, 9.3, 9.4
25
+ */
26
+ export interface IOutboundQueueStore {
27
+ /**
28
+ * Add a message to the end of the queue.
29
+ *
30
+ * @param item - The outbound queue item to enqueue
31
+ * @throws If the store is unavailable (Req 9.5)
32
+ */
33
+ enqueue(item: IOutboundQueueItem): Promise<void>;
34
+ /**
35
+ * Remove and return the next item from the front of the queue
36
+ * that is in `Queued` status and ready for delivery.
37
+ *
38
+ * @returns The next queue item, or `undefined` if the queue is empty
39
+ * or no items are ready
40
+ */
41
+ dequeue(): Promise<IOutboundQueueItem | undefined>;
42
+ /**
43
+ * Return the next item from the front of the queue without removing it.
44
+ *
45
+ * @returns The next queue item, or `undefined` if the queue is empty
46
+ */
47
+ peek(): Promise<IOutboundQueueItem | undefined>;
48
+ /**
49
+ * Mark a message as successfully delivered and remove it from the queue.
50
+ *
51
+ * @param messageId - The RFC 5322 Message-ID of the completed message
52
+ */
53
+ markCompleted(messageId: string): Promise<void>;
54
+ /**
55
+ * Mark a message as permanently failed and remove it from the active queue.
56
+ *
57
+ * @param messageId - The RFC 5322 Message-ID of the failed message
58
+ * @param reason - Human-readable failure reason
59
+ */
60
+ markFailed(messageId: string, reason: string): Promise<void>;
61
+ /**
62
+ * Re-enqueue a message for retry with updated retry count and status.
63
+ *
64
+ * The item is placed at the end of the queue to maintain FIFO fairness
65
+ * among messages at the same priority level (Req 9.3).
66
+ *
67
+ * @param item - The updated queue item with incremented retryCount
68
+ */
69
+ requeue(item: IOutboundQueueItem): Promise<void>;
70
+ /**
71
+ * Return the current number of items in the queue.
72
+ *
73
+ * @returns The queue depth (number of pending items)
74
+ */
75
+ getQueueDepth(): Promise<number>;
76
+ /**
77
+ * Retrieve a queue item by its Message-ID.
78
+ *
79
+ * @param messageId - The RFC 5322 Message-ID to look up
80
+ * @returns The queue item, or `undefined` if not found
81
+ */
82
+ getByMessageId(messageId: string): Promise<IOutboundQueueItem | undefined>;
83
+ }
84
+ /**
85
+ * In-memory implementation of `IOutboundQueueStore` for testing.
86
+ *
87
+ * Uses a `Map` keyed by messageId for O(1) lookups and an insertion-ordered
88
+ * array (`queue`) to maintain strict FIFO ordering (Req 9.3).
89
+ *
90
+ * This implementation is NOT suitable for production — it does not survive
91
+ * process restarts (Req 9.1 requires durable storage). Use a database-backed
92
+ * or filesystem-backed implementation for production deployments.
93
+ *
94
+ * @see Requirements 9.1, 9.3, 9.4
95
+ */
96
+ export declare class InMemoryOutboundQueueStore implements IOutboundQueueStore {
97
+ /** Ordered list of message IDs representing FIFO queue order. */
98
+ private readonly queue;
99
+ /** Map from messageId → queue item for O(1) lookups. */
100
+ private readonly items;
101
+ enqueue(item: IOutboundQueueItem): Promise<void>;
102
+ dequeue(): Promise<IOutboundQueueItem | undefined>;
103
+ peek(): Promise<IOutboundQueueItem | undefined>;
104
+ markCompleted(messageId: string): Promise<void>;
105
+ markFailed(messageId: string, _reason: string): Promise<void>;
106
+ requeue(item: IOutboundQueueItem): Promise<void>;
107
+ getQueueDepth(): Promise<number>;
108
+ getByMessageId(messageId: string): Promise<IOutboundQueueItem | undefined>;
109
+ }
110
+ //# sourceMappingURL=outboundQueueStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outboundQueueStore.d.ts","sourceRoot":"","sources":["../../../../../../brightchain-api-lib/src/lib/services/emailGateway/outboundQueueStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhE;;;;;;;;;GASG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,OAAO,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjD;;;;;;OAMG;IACH,OAAO,IAAI,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAAC;IAEnD;;;;OAIG;IACH,IAAI,IAAI,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAAC;IAEhD;;;;OAIG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhD;;;;;OAKG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7D;;;;;;;OAOG;IACH,OAAO,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjD;;;;OAIG;IACH,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAEjC;;;;;OAKG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAAC;CAC5E;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,0BAA2B,YAAW,mBAAmB;IACpE,iEAAiE;IACjE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IAEtC,wDAAwD;IACxD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA8C;IAE9D,OAAO,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAShD,OAAO,IAAI,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC;IAoClD,IAAI,IAAI,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC;IAW/C,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY/C,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY7D,OAAO,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAUhD,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAWhC,cAAc,CAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC;CAI3C"}
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ /**
3
+ * Outbound Queue Store — persistence interface and in-memory implementation
4
+ * for the outbound email delivery queue.
5
+ *
6
+ * The `IOutboundQueueStore` interface defines the contract for queue persistence,
7
+ * allowing different backends (in-memory for testing, database/filesystem for
8
+ * production) to be swapped without changing the queue logic.
9
+ *
10
+ * The `InMemoryOutboundQueueStore` provides a FIFO-ordered, Map-backed
11
+ * implementation suitable for unit/integration testing.
12
+ *
13
+ * @see Requirements 9.1, 9.3, 9.4
14
+ * @module outboundQueueStore
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.InMemoryOutboundQueueStore = void 0;
18
+ const brightchain_lib_1 = require("@brightchain/brightchain-lib");
19
+ /**
20
+ * In-memory implementation of `IOutboundQueueStore` for testing.
21
+ *
22
+ * Uses a `Map` keyed by messageId for O(1) lookups and an insertion-ordered
23
+ * array (`queue`) to maintain strict FIFO ordering (Req 9.3).
24
+ *
25
+ * This implementation is NOT suitable for production — it does not survive
26
+ * process restarts (Req 9.1 requires durable storage). Use a database-backed
27
+ * or filesystem-backed implementation for production deployments.
28
+ *
29
+ * @see Requirements 9.1, 9.3, 9.4
30
+ */
31
+ class InMemoryOutboundQueueStore {
32
+ /** Ordered list of message IDs representing FIFO queue order. */
33
+ queue = [];
34
+ /** Map from messageId → queue item for O(1) lookups. */
35
+ items = new Map();
36
+ async enqueue(item) {
37
+ // If an item with the same messageId already exists, replace it
38
+ // (this can happen on requeue after status update).
39
+ if (!this.items.has(item.messageId)) {
40
+ this.queue.push(item.messageId);
41
+ }
42
+ this.items.set(item.messageId, { ...item });
43
+ }
44
+ async dequeue() {
45
+ // Walk the queue front-to-back to find the first item in Queued status
46
+ // that is ready for processing (nextAttemptAt <= now or not set).
47
+ const now = Date.now();
48
+ for (let i = 0; i < this.queue.length; i++) {
49
+ const messageId = this.queue[i];
50
+ const item = this.items.get(messageId);
51
+ if (!item) {
52
+ // Stale entry — item was removed (markCompleted/markFailed).
53
+ this.queue.splice(i, 1);
54
+ i--;
55
+ continue;
56
+ }
57
+ if (item.status !== brightchain_lib_1.OutboundDeliveryStatus.Queued) {
58
+ // Item exists but is not in Queued status — remove stale entry.
59
+ this.queue.splice(i, 1);
60
+ i--;
61
+ continue;
62
+ }
63
+ // Respect nextAttemptAt: skip items that are not yet ready.
64
+ if (item.nextAttemptAt && item.nextAttemptAt.getTime() > now) {
65
+ continue;
66
+ }
67
+ // Item is ready — remove from queue and return.
68
+ this.queue.splice(i, 1);
69
+ this.items.delete(messageId);
70
+ return { ...item };
71
+ }
72
+ return undefined;
73
+ }
74
+ async peek() {
75
+ // Walk the queue front-to-back to find the first item in Queued status.
76
+ for (const messageId of this.queue) {
77
+ const item = this.items.get(messageId);
78
+ if (item && item.status === brightchain_lib_1.OutboundDeliveryStatus.Queued) {
79
+ return { ...item };
80
+ }
81
+ }
82
+ return undefined;
83
+ }
84
+ async markCompleted(messageId) {
85
+ const item = this.items.get(messageId);
86
+ if (item) {
87
+ item.status = brightchain_lib_1.OutboundDeliveryStatus.Delivered;
88
+ this.items.delete(messageId);
89
+ const idx = this.queue.indexOf(messageId);
90
+ if (idx !== -1) {
91
+ this.queue.splice(idx, 1);
92
+ }
93
+ }
94
+ }
95
+ async markFailed(messageId, _reason) {
96
+ const item = this.items.get(messageId);
97
+ if (item) {
98
+ item.status = brightchain_lib_1.OutboundDeliveryStatus.PermanentFailure;
99
+ this.items.delete(messageId);
100
+ const idx = this.queue.indexOf(messageId);
101
+ if (idx !== -1) {
102
+ this.queue.splice(idx, 1);
103
+ }
104
+ }
105
+ }
106
+ async requeue(item) {
107
+ // Remove old position if present, then append to end for FIFO fairness.
108
+ const existingIdx = this.queue.indexOf(item.messageId);
109
+ if (existingIdx !== -1) {
110
+ this.queue.splice(existingIdx, 1);
111
+ }
112
+ this.queue.push(item.messageId);
113
+ this.items.set(item.messageId, { ...item });
114
+ }
115
+ async getQueueDepth() {
116
+ // Count only items that are still in the items map (not stale references).
117
+ let count = 0;
118
+ for (const messageId of this.queue) {
119
+ if (this.items.has(messageId)) {
120
+ count++;
121
+ }
122
+ }
123
+ return count;
124
+ }
125
+ async getByMessageId(messageId) {
126
+ const item = this.items.get(messageId);
127
+ return item ? { ...item } : undefined;
128
+ }
129
+ }
130
+ exports.InMemoryOutboundQueueStore = InMemoryOutboundQueueStore;
131
+ //# sourceMappingURL=outboundQueueStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outboundQueueStore.js","sourceRoot":"","sources":["../../../../../../brightchain-api-lib/src/lib/services/emailGateway/outboundQueueStore.ts"],"names":[],"mappings":"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"}