@brightchain/brightchain-api-lib 0.23.25 → 0.24.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 (438) hide show
  1. package/package.json +5 -5
  2. package/src/lib/__tests__/fixtures/mock-backend-brightchain-member.d.ts.map +1 -1
  3. package/src/lib/__tests__/fixtures/mock-backend-brightchain-member.js +11 -0
  4. package/src/lib/__tests__/fixtures/mock-backend-brightchain-member.js.map +1 -1
  5. package/src/lib/__tests__/fixtures/mocked-model.js +63 -60
  6. package/src/lib/__tests__/fixtures/mocked-model.js.map +1 -1
  7. package/src/lib/application.d.ts +1 -1
  8. package/src/lib/application.d.ts.map +1 -1
  9. package/src/lib/application.js +103 -34
  10. package/src/lib/application.js.map +1 -1
  11. package/src/lib/auth/aclEnforcedAvailability.js +4 -0
  12. package/src/lib/auth/aclEnforcedAvailability.js.map +1 -1
  13. package/src/lib/auth/aclEnforcedBlockStore.js +7 -0
  14. package/src/lib/auth/aclEnforcedBlockStore.js.map +1 -1
  15. package/src/lib/auth/ecdsaNodeAuthenticator.js +1 -0
  16. package/src/lib/auth/ecdsaNodeAuthenticator.js.map +1 -1
  17. package/src/lib/auth/poolAclBootstrap.js +2 -0
  18. package/src/lib/auth/poolAclBootstrap.js.map +1 -1
  19. package/src/lib/auth/poolAclStore.js +2 -1
  20. package/src/lib/auth/poolAclStore.js.map +1 -1
  21. package/src/lib/auth/poolAclUpdater.js +4 -0
  22. package/src/lib/auth/poolAclUpdater.js.map +1 -1
  23. package/src/lib/availability/availabilityMetrics.js +43 -45
  24. package/src/lib/availability/availabilityMetrics.js.map +1 -1
  25. package/src/lib/availability/availabilityService.js +26 -20
  26. package/src/lib/availability/availabilityService.js.map +1 -1
  27. package/src/lib/availability/blockRegistry.js +46 -25
  28. package/src/lib/availability/blockRegistry.js.map +1 -1
  29. package/src/lib/availability/discoveryProtocol.js +10 -8
  30. package/src/lib/availability/discoveryProtocol.js.map +1 -1
  31. package/src/lib/availability/gossipService.js +56 -45
  32. package/src/lib/availability/gossipService.js.map +1 -1
  33. package/src/lib/availability/heartbeatMonitor.js +22 -20
  34. package/src/lib/availability/heartbeatMonitor.js.map +1 -1
  35. package/src/lib/availability/poolDiscoveryService.js +7 -1
  36. package/src/lib/availability/poolDiscoveryService.js.map +1 -1
  37. package/src/lib/availability/quorumGossipHandler.js +13 -6
  38. package/src/lib/availability/quorumGossipHandler.js.map +1 -1
  39. package/src/lib/availability/reconciliationService.js +18 -12
  40. package/src/lib/availability/reconciliationService.js.map +1 -1
  41. package/src/lib/blockFetch/blockFetcher.js +14 -8
  42. package/src/lib/blockFetch/blockFetcher.js.map +1 -1
  43. package/src/lib/blockFetch/fetchQueue.js +9 -7
  44. package/src/lib/blockFetch/fetchQueue.js.map +1 -1
  45. package/src/lib/blockFetch/httpBlockFetchTransport.js +2 -0
  46. package/src/lib/blockFetch/httpBlockFetchTransport.js.map +1 -1
  47. package/src/lib/browserKeyring.js +5 -2
  48. package/src/lib/browserKeyring.js.map +1 -1
  49. package/src/lib/controllers/api/blocks.d.ts.map +1 -1
  50. package/src/lib/controllers/api/blocks.js +9 -3
  51. package/src/lib/controllers/api/blocks.js.map +1 -1
  52. package/src/lib/controllers/api/brighthub/connectionController.d.ts +80 -0
  53. package/src/lib/controllers/api/brighthub/connectionController.d.ts.map +1 -0
  54. package/src/lib/controllers/api/brighthub/connectionController.js +890 -0
  55. package/src/lib/controllers/api/brighthub/connectionController.js.map +1 -0
  56. package/src/lib/controllers/api/brighthub/index.d.ts +9 -0
  57. package/src/lib/controllers/api/brighthub/index.d.ts.map +1 -0
  58. package/src/lib/controllers/api/brighthub/index.js +12 -0
  59. package/src/lib/controllers/api/brighthub/index.js.map +1 -0
  60. package/src/lib/controllers/api/brighthub/messagingController.d.ts +84 -0
  61. package/src/lib/controllers/api/brighthub/messagingController.d.ts.map +1 -0
  62. package/src/lib/controllers/api/brighthub/messagingController.js +1077 -0
  63. package/src/lib/controllers/api/brighthub/messagingController.js.map +1 -0
  64. package/src/lib/controllers/api/brighthub/notificationController.d.ts +89 -0
  65. package/src/lib/controllers/api/brighthub/notificationController.d.ts.map +1 -0
  66. package/src/lib/controllers/api/brighthub/notificationController.js +444 -0
  67. package/src/lib/controllers/api/brighthub/notificationController.js.map +1 -0
  68. package/src/lib/controllers/api/brighthub/postController.d.ts +75 -0
  69. package/src/lib/controllers/api/brighthub/postController.d.ts.map +1 -0
  70. package/src/lib/controllers/api/brighthub/postController.js +388 -0
  71. package/src/lib/controllers/api/brighthub/postController.js.map +1 -0
  72. package/src/lib/controllers/api/brighthub/timelineController.d.ts +74 -0
  73. package/src/lib/controllers/api/brighthub/timelineController.d.ts.map +1 -0
  74. package/src/lib/controllers/api/brighthub/timelineController.js +418 -0
  75. package/src/lib/controllers/api/brighthub/timelineController.js.map +1 -0
  76. package/src/lib/controllers/api/brightpass.d.ts.map +1 -1
  77. package/src/lib/controllers/api/brightpass.js +46 -4
  78. package/src/lib/controllers/api/brightpass.js.map +1 -1
  79. package/src/lib/controllers/api/cbl.js +1 -0
  80. package/src/lib/controllers/api/cbl.js.map +1 -1
  81. package/src/lib/controllers/api/channels.js +2 -2
  82. package/src/lib/controllers/api/channels.js.map +1 -1
  83. package/src/lib/controllers/api/conversations.js +1 -1
  84. package/src/lib/controllers/api/conversations.js.map +1 -1
  85. package/src/lib/controllers/api/docs.js +2 -1
  86. package/src/lib/controllers/api/docs.js.map +1 -1
  87. package/src/lib/controllers/api/emails.d.ts.map +1 -1
  88. package/src/lib/controllers/api/emails.js +16 -2
  89. package/src/lib/controllers/api/emails.js.map +1 -1
  90. package/src/lib/controllers/api/explodingMessages.js +2 -4
  91. package/src/lib/controllers/api/explodingMessages.js.map +1 -1
  92. package/src/lib/controllers/api/groups.js +2 -2
  93. package/src/lib/controllers/api/groups.js.map +1 -1
  94. package/src/lib/controllers/api/health.d.ts +9 -2
  95. package/src/lib/controllers/api/health.d.ts.map +1 -1
  96. package/src/lib/controllers/api/health.js +48 -6
  97. package/src/lib/controllers/api/health.js.map +1 -1
  98. package/src/lib/controllers/api/index.d.ts +1 -0
  99. package/src/lib/controllers/api/index.d.ts.map +1 -1
  100. package/src/lib/controllers/api/index.js +1 -0
  101. package/src/lib/controllers/api/index.js.map +1 -1
  102. package/src/lib/controllers/api/introspection.js +2 -0
  103. package/src/lib/controllers/api/introspection.js.map +1 -1
  104. package/src/lib/controllers/api/messages.js +1 -1
  105. package/src/lib/controllers/api/messages.js.map +1 -1
  106. package/src/lib/controllers/api/nodes.js +6 -6
  107. package/src/lib/controllers/api/nodes.js.map +1 -1
  108. package/src/lib/controllers/api/quorum.d.ts +1 -1
  109. package/src/lib/controllers/api/quorum.d.ts.map +1 -1
  110. package/src/lib/controllers/api/quorum.js +3 -2
  111. package/src/lib/controllers/api/quorum.js.map +1 -1
  112. package/src/lib/controllers/api/scbl.js +3 -0
  113. package/src/lib/controllers/api/scbl.js.map +1 -1
  114. package/src/lib/controllers/api/sessions.d.ts +18 -2
  115. package/src/lib/controllers/api/sessions.d.ts.map +1 -1
  116. package/src/lib/controllers/api/sessions.js +60 -3
  117. package/src/lib/controllers/api/sessions.js.map +1 -1
  118. package/src/lib/controllers/api/sync.js +4 -4
  119. package/src/lib/controllers/api/sync.js.map +1 -1
  120. package/src/lib/controllers/api/user.d.ts +2 -0
  121. package/src/lib/controllers/api/user.d.ts.map +1 -1
  122. package/src/lib/controllers/api/user.js +95 -3
  123. package/src/lib/controllers/api/user.js.map +1 -1
  124. package/src/lib/controllers/identity/deviceController.js +2 -2
  125. package/src/lib/controllers/identity/deviceController.js.map +1 -1
  126. package/src/lib/controllers/identity/directoryController.js +1 -1
  127. package/src/lib/controllers/identity/directoryController.js.map +1 -1
  128. package/src/lib/controllers/identity/identityProofController.js +4 -6
  129. package/src/lib/controllers/identity/identityProofController.js.map +1 -1
  130. package/src/lib/databaseInit.d.ts +3 -3
  131. package/src/lib/databaseInit.js +5 -5
  132. package/src/lib/databaseInit.js.map +1 -1
  133. package/src/lib/datastore/block-document-store.d.ts.map +1 -1
  134. package/src/lib/datastore/block-document-store.js +18 -6
  135. package/src/lib/datastore/block-document-store.js.map +1 -1
  136. package/src/lib/datastore/document-store.d.ts.map +1 -1
  137. package/src/lib/datastore/memory-document-store.js +5 -2
  138. package/src/lib/datastore/memory-document-store.js.map +1 -1
  139. package/src/lib/encryption/encryptedMetadataService.js +2 -0
  140. package/src/lib/encryption/encryptedMetadataService.js.map +1 -1
  141. package/src/lib/encryption/encryptionAwareReplication.js +3 -0
  142. package/src/lib/encryption/encryptionAwareReplication.js.map +1 -1
  143. package/src/lib/encryption/errors.d.ts.map +1 -1
  144. package/src/lib/encryption/errors.js +8 -0
  145. package/src/lib/encryption/errors.js.map +1 -1
  146. package/src/lib/encryption/poolKeyManager.js +2 -0
  147. package/src/lib/encryption/poolKeyManager.js.map +1 -1
  148. package/src/lib/environment.js +10 -0
  149. package/src/lib/environment.js.map +1 -1
  150. package/src/lib/errors/express-validation.js +1 -0
  151. package/src/lib/errors/express-validation.js.map +1 -1
  152. package/src/lib/errors/invalid-backup-code-version.js +1 -0
  153. package/src/lib/errors/invalid-backup-code-version.js.map +1 -1
  154. package/src/lib/errors/memberIndexSchemaValidationError.js +1 -0
  155. package/src/lib/errors/memberIndexSchemaValidationError.js.map +1 -1
  156. package/src/lib/errors/missing-validated-data.js +2 -0
  157. package/src/lib/errors/missing-validated-data.js.map +1 -1
  158. package/src/lib/errors/token-not-found.js +1 -0
  159. package/src/lib/errors/token-not-found.js.map +1 -1
  160. package/src/lib/errors/typed-error-local.js +3 -0
  161. package/src/lib/errors/typed-error-local.js.map +1 -1
  162. package/src/lib/interfaces/brightpass/index.d.ts +1 -1
  163. package/src/lib/interfaces/brightpass/index.d.ts.map +1 -1
  164. package/src/lib/interfaces/environment.d.ts +1 -1
  165. package/src/lib/interfaces/environment.d.ts.map +1 -1
  166. package/src/lib/interfaces/member/memberProfileResponse.d.ts.map +1 -1
  167. package/src/lib/interfaces/member/operational.d.ts.map +1 -1
  168. package/src/lib/interfaces/member-init-config.d.ts +1 -1
  169. package/src/lib/interfaces/member-init-config.d.ts.map +1 -1
  170. package/src/lib/interfaces/responses/api-backup-codes-response.d.ts.map +1 -1
  171. package/src/lib/interfaces/responses/api-challenge-response.d.ts.map +1 -1
  172. package/src/lib/interfaces/responses/api-code-count-response.d.ts.map +1 -1
  173. package/src/lib/interfaces/responses/api-detailed-health-response.d.ts.map +1 -1
  174. package/src/lib/interfaces/responses/api-discover-block-response.d.ts.map +1 -1
  175. package/src/lib/interfaces/responses/api-express-validation-error.d.ts.map +1 -1
  176. package/src/lib/interfaces/responses/api-get-block-response.d.ts.map +1 -1
  177. package/src/lib/interfaces/responses/api-get-node-response.d.ts.map +1 -1
  178. package/src/lib/interfaces/responses/api-health-response.d.ts.map +1 -1
  179. package/src/lib/interfaces/responses/api-list-nodes-response.d.ts.map +1 -1
  180. package/src/lib/interfaces/responses/api-login-response.d.ts.map +1 -1
  181. package/src/lib/interfaces/responses/api-members-response.d.ts.map +1 -1
  182. package/src/lib/interfaces/responses/api-mnemonic-response.d.ts.map +1 -1
  183. package/src/lib/interfaces/responses/api-reconcile-response.d.ts.map +1 -1
  184. package/src/lib/interfaces/responses/api-register-node-response.d.ts.map +1 -1
  185. package/src/lib/interfaces/responses/api-registration-response.d.ts.map +1 -1
  186. package/src/lib/interfaces/responses/api-replicate-block-response.d.ts.map +1 -1
  187. package/src/lib/interfaces/responses/api-request-user-response.d.ts.map +1 -1
  188. package/src/lib/interfaces/responses/api-store-block-response.d.ts.map +1 -1
  189. package/src/lib/interfaces/responses/api-store-cbl-response.d.ts.map +1 -1
  190. package/src/lib/interfaces/responses/api-sync-request-response.d.ts.map +1 -1
  191. package/src/lib/interfaces/responses/brighthub/api-connection-response.d.ts +21 -0
  192. package/src/lib/interfaces/responses/brighthub/api-connection-response.d.ts.map +1 -0
  193. package/src/lib/interfaces/responses/brighthub/api-connection-response.js +3 -0
  194. package/src/lib/interfaces/responses/brighthub/api-connection-response.js.map +1 -0
  195. package/src/lib/interfaces/responses/brighthub/api-messaging-response.d.ts +39 -0
  196. package/src/lib/interfaces/responses/brighthub/api-messaging-response.d.ts.map +1 -0
  197. package/src/lib/interfaces/responses/brighthub/api-messaging-response.js +3 -0
  198. package/src/lib/interfaces/responses/brighthub/api-messaging-response.js.map +1 -0
  199. package/src/lib/interfaces/responses/brighthub/api-notification-response.d.ts +30 -0
  200. package/src/lib/interfaces/responses/brighthub/api-notification-response.d.ts.map +1 -0
  201. package/src/lib/interfaces/responses/brighthub/api-notification-response.js +3 -0
  202. package/src/lib/interfaces/responses/brighthub/api-notification-response.js.map +1 -0
  203. package/src/lib/interfaces/responses/brighthub/api-post-response.d.ts +21 -0
  204. package/src/lib/interfaces/responses/brighthub/api-post-response.d.ts.map +1 -0
  205. package/src/lib/interfaces/responses/brighthub/api-post-response.js +3 -0
  206. package/src/lib/interfaces/responses/brighthub/api-post-response.js.map +1 -0
  207. package/src/lib/interfaces/responses/brighthub/api-timeline-response.d.ts +14 -0
  208. package/src/lib/interfaces/responses/brighthub/api-timeline-response.d.ts.map +1 -0
  209. package/src/lib/interfaces/responses/brighthub/api-timeline-response.js +3 -0
  210. package/src/lib/interfaces/responses/brighthub/api-timeline-response.js.map +1 -0
  211. package/src/lib/interfaces/responses/brighthub/api-user-profile-response.d.ts +10 -0
  212. package/src/lib/interfaces/responses/brighthub/api-user-profile-response.d.ts.map +1 -0
  213. package/src/lib/interfaces/responses/brighthub/api-user-profile-response.js +3 -0
  214. package/src/lib/interfaces/responses/brighthub/api-user-profile-response.js.map +1 -0
  215. package/src/lib/interfaces/responses/brighthub/index.d.ts +13 -0
  216. package/src/lib/interfaces/responses/brighthub/index.d.ts.map +1 -0
  217. package/src/lib/interfaces/responses/brighthub/index.js +9 -0
  218. package/src/lib/interfaces/responses/brighthub/index.js.map +1 -0
  219. package/src/lib/interfaces/responses/index.d.ts +1 -0
  220. package/src/lib/interfaces/responses/index.d.ts.map +1 -1
  221. package/src/lib/interfaces/storage/storedDocumentTypes.d.ts +1 -1
  222. package/src/lib/interfaces/storage/storedDocumentTypes.js +1 -1
  223. package/src/lib/interfaces/storage/userRoleSchema.d.ts.map +1 -1
  224. package/src/lib/interfaces/storage/userRoleSchema.js +1 -3
  225. package/src/lib/interfaces/storage/userRoleSchema.js.map +1 -1
  226. package/src/lib/middlewares.js +31 -31
  227. package/src/lib/middlewares.js.map +1 -1
  228. package/src/lib/nodeKeyring.js +2 -0
  229. package/src/lib/nodeKeyring.js.map +1 -1
  230. package/src/lib/plugins/brightchain-database-plugin.d.ts +14 -14
  231. package/src/lib/plugins/brightchain-database-plugin.d.ts.map +1 -1
  232. package/src/lib/plugins/brightchain-database-plugin.js +36 -34
  233. package/src/lib/plugins/brightchain-database-plugin.js.map +1 -1
  234. package/src/lib/routers/api.d.ts +62 -1
  235. package/src/lib/routers/api.d.ts.map +1 -1
  236. package/src/lib/routers/api.js +123 -2
  237. package/src/lib/routers/api.js.map +1 -1
  238. package/src/lib/routers/app.d.ts.map +1 -1
  239. package/src/lib/routers/app.js +10 -1
  240. package/src/lib/routers/app.js.map +1 -1
  241. package/src/lib/routers/base.js +2 -0
  242. package/src/lib/routers/base.js.map +1 -1
  243. package/src/lib/secureEnclaveKeyring.js +4 -2
  244. package/src/lib/secureEnclaveKeyring.js.map +1 -1
  245. package/src/lib/services/auth.d.ts.map +1 -1
  246. package/src/lib/services/auth.js +11 -2
  247. package/src/lib/services/auth.js.map +1 -1
  248. package/src/lib/services/base.js +1 -0
  249. package/src/lib/services/base.js.map +1 -1
  250. package/src/lib/services/blockServiceFactory.js +2 -0
  251. package/src/lib/services/blockServiceFactory.js.map +1 -1
  252. package/src/lib/services/blockStore.js +3 -2
  253. package/src/lib/services/blockStore.js.map +1 -1
  254. package/src/lib/services/blocks.js +1 -0
  255. package/src/lib/services/blocks.js.map +1 -1
  256. package/src/lib/services/brightChainBackupCodeService.d.ts +114 -0
  257. package/src/lib/services/brightChainBackupCodeService.d.ts.map +1 -0
  258. package/src/lib/services/brightChainBackupCodeService.js +303 -0
  259. package/src/lib/services/brightChainBackupCodeService.js.map +1 -0
  260. package/src/lib/services/brightchain-authentication-provider.d.ts.map +1 -1
  261. package/src/lib/services/brightchain-authentication-provider.js +40 -9
  262. package/src/lib/services/brightchain-authentication-provider.js.map +1 -1
  263. package/src/lib/services/brightchain-member-init.service.d.ts +17 -17
  264. package/src/lib/services/brightchain-member-init.service.d.ts.map +1 -1
  265. package/src/lib/services/brightchain-member-init.service.js +12 -9
  266. package/src/lib/services/brightchain-member-init.service.js.map +1 -1
  267. package/src/lib/services/brighthub/connectionService.d.ts +286 -0
  268. package/src/lib/services/brighthub/connectionService.d.ts.map +1 -0
  269. package/src/lib/services/brighthub/connectionService.js +1887 -0
  270. package/src/lib/services/brighthub/connectionService.js.map +1 -0
  271. package/src/lib/services/brighthub/discoveryService.d.ts +110 -0
  272. package/src/lib/services/brighthub/discoveryService.d.ts.map +1 -0
  273. package/src/lib/services/brighthub/discoveryService.js +528 -0
  274. package/src/lib/services/brighthub/discoveryService.js.map +1 -0
  275. package/src/lib/services/brighthub/feedService.d.ts +141 -0
  276. package/src/lib/services/brighthub/feedService.d.ts.map +1 -0
  277. package/src/lib/services/brighthub/feedService.js +418 -0
  278. package/src/lib/services/brighthub/feedService.js.map +1 -0
  279. package/src/lib/services/brighthub/index.d.ts +11 -0
  280. package/src/lib/services/brighthub/index.d.ts.map +1 -0
  281. package/src/lib/services/brighthub/index.js +14 -0
  282. package/src/lib/services/brighthub/index.js.map +1 -0
  283. package/src/lib/services/brighthub/messagingService.d.ts +109 -0
  284. package/src/lib/services/brighthub/messagingService.d.ts.map +1 -0
  285. package/src/lib/services/brighthub/messagingService.js +947 -0
  286. package/src/lib/services/brighthub/messagingService.js.map +1 -0
  287. package/src/lib/services/brighthub/messagingService.test-helpers.d.ts +75 -0
  288. package/src/lib/services/brighthub/messagingService.test-helpers.d.ts.map +1 -0
  289. package/src/lib/services/brighthub/messagingService.test-helpers.js +237 -0
  290. package/src/lib/services/brighthub/messagingService.test-helpers.js.map +1 -0
  291. package/src/lib/services/brighthub/notificationService.d.ts +172 -0
  292. package/src/lib/services/brighthub/notificationService.d.ts.map +1 -0
  293. package/src/lib/services/brighthub/notificationService.js +768 -0
  294. package/src/lib/services/brighthub/notificationService.js.map +1 -0
  295. package/src/lib/services/brighthub/notificationService.test-helpers.d.ts +75 -0
  296. package/src/lib/services/brighthub/notificationService.test-helpers.d.ts.map +1 -0
  297. package/src/lib/services/brighthub/notificationService.test-helpers.js +230 -0
  298. package/src/lib/services/brighthub/notificationService.test-helpers.js.map +1 -0
  299. package/src/lib/services/brighthub/postService.d.ts +129 -0
  300. package/src/lib/services/brighthub/postService.d.ts.map +1 -0
  301. package/src/lib/services/brighthub/postService.js +470 -0
  302. package/src/lib/services/brighthub/postService.js.map +1 -0
  303. package/src/lib/services/brighthub/postService.test-helpers.d.ts +40 -0
  304. package/src/lib/services/brighthub/postService.test-helpers.d.ts.map +1 -0
  305. package/src/lib/services/brighthub/postService.test-helpers.js +84 -0
  306. package/src/lib/services/brighthub/postService.test-helpers.js.map +1 -0
  307. package/src/lib/services/brighthub/textFormatter.d.ts +64 -0
  308. package/src/lib/services/brighthub/textFormatter.d.ts.map +1 -0
  309. package/src/lib/services/brighthub/textFormatter.js +256 -0
  310. package/src/lib/services/brighthub/textFormatter.js.map +1 -0
  311. package/src/lib/services/brighthub/threadService.d.ts +79 -0
  312. package/src/lib/services/brighthub/threadService.d.ts.map +1 -0
  313. package/src/lib/services/brighthub/threadService.js +246 -0
  314. package/src/lib/services/brighthub/threadService.js.map +1 -0
  315. package/src/lib/services/brighthub/userProfileService.d.ts +203 -0
  316. package/src/lib/services/brighthub/userProfileService.d.ts.map +1 -0
  317. package/src/lib/services/brighthub/userProfileService.js +868 -0
  318. package/src/lib/services/brighthub/userProfileService.js.map +1 -0
  319. package/src/lib/services/brighthub/userProfileService.test-helpers.d.ts +86 -0
  320. package/src/lib/services/brighthub/userProfileService.test-helpers.d.ts.map +1 -0
  321. package/src/lib/services/brighthub/userProfileService.test-helpers.js +169 -0
  322. package/src/lib/services/brighthub/userProfileService.test-helpers.js.map +1 -0
  323. package/src/lib/services/brighthub/webSocketServer.d.ts +68 -0
  324. package/src/lib/services/brighthub/webSocketServer.d.ts.map +1 -0
  325. package/src/lib/services/brighthub/webSocketServer.js +194 -0
  326. package/src/lib/services/brighthub/webSocketServer.js.map +1 -0
  327. package/src/lib/services/brightpass/auditLogger.js +10 -5
  328. package/src/lib/services/brightpass/auditLogger.js.map +1 -1
  329. package/src/lib/services/brightpass/vaultEncryption.js +8 -8
  330. package/src/lib/services/brightpass/vaultEncryption.js.map +1 -1
  331. package/src/lib/services/brightpass.js +16 -8
  332. package/src/lib/services/brightpass.js.map +1 -1
  333. package/src/lib/services/cliOperatorPrompt.js +5 -2
  334. package/src/lib/services/cliOperatorPrompt.js.map +1 -1
  335. package/src/lib/services/clientWebSocketServer.d.ts +69 -4
  336. package/src/lib/services/clientWebSocketServer.d.ts.map +1 -1
  337. package/src/lib/services/clientWebSocketServer.js +188 -10
  338. package/src/lib/services/clientWebSocketServer.js.map +1 -1
  339. package/src/lib/services/contentAwareBlocksService.js +2 -0
  340. package/src/lib/services/contentAwareBlocksService.js.map +1 -1
  341. package/src/lib/services/contentIngestionService.d.ts.map +1 -1
  342. package/src/lib/services/contentIngestionService.js +2 -0
  343. package/src/lib/services/contentIngestionService.js.map +1 -1
  344. package/src/lib/services/diskQuorumService.js +3 -0
  345. package/src/lib/services/diskQuorumService.js.map +1 -1
  346. package/src/lib/services/email.js +5 -0
  347. package/src/lib/services/email.js.map +1 -1
  348. package/src/lib/services/eventNotificationSystem.d.ts +51 -10
  349. package/src/lib/services/eventNotificationSystem.d.ts.map +1 -1
  350. package/src/lib/services/eventNotificationSystem.js +76 -23
  351. package/src/lib/services/eventNotificationSystem.js.map +1 -1
  352. package/src/lib/services/expirationScheduler.js +6 -3
  353. package/src/lib/services/expirationScheduler.js.map +1 -1
  354. package/src/lib/services/fakeEmailService.js +3 -4
  355. package/src/lib/services/fakeEmailService.js.map +1 -1
  356. package/src/lib/services/fec.js +1 -3
  357. package/src/lib/services/fec.js.map +1 -1
  358. package/src/lib/services/fecServiceFactory.js +2 -2
  359. package/src/lib/services/fecServiceFactory.js.map +1 -1
  360. package/src/lib/services/fecUsageExample.js +1 -3
  361. package/src/lib/services/fecUsageExample.js.map +1 -1
  362. package/src/lib/services/identityExpirationScheduler.d.ts.map +1 -1
  363. package/src/lib/services/identityExpirationScheduler.js +7 -2
  364. package/src/lib/services/identityExpirationScheduler.js.map +1 -1
  365. package/src/lib/services/index.d.ts +3 -2
  366. package/src/lib/services/index.d.ts.map +1 -1
  367. package/src/lib/services/index.js +3 -2
  368. package/src/lib/services/index.js.map +1 -1
  369. package/src/lib/services/messageEventsWebSocketHandler.js +1 -0
  370. package/src/lib/services/messageEventsWebSocketHandler.js.map +1 -1
  371. package/src/lib/services/messagePassingService.js +5 -0
  372. package/src/lib/services/messagePassingService.js.map +1 -1
  373. package/src/lib/services/nativeRsFecService.js +3 -5
  374. package/src/lib/services/nativeRsFecService.js.map +1 -1
  375. package/src/lib/services/presenceService.js +5 -4
  376. package/src/lib/services/presenceService.js.map +1 -1
  377. package/src/lib/services/quorum.js +3 -2
  378. package/src/lib/services/quorum.js.map +1 -1
  379. package/src/lib/services/quorumDatabaseAdapter.d.ts +5 -5
  380. package/src/lib/services/quorumDatabaseAdapter.d.ts.map +1 -1
  381. package/src/lib/services/quorumDatabaseAdapter.js +5 -3
  382. package/src/lib/services/quorumDatabaseAdapter.js.map +1 -1
  383. package/src/lib/services/rbac-input-builder.js +5 -0
  384. package/src/lib/services/rbac-input-builder.js.map +1 -1
  385. package/src/lib/services/secureKeyStorage.js +3 -0
  386. package/src/lib/services/secureKeyStorage.js.map +1 -1
  387. package/src/lib/services/sessionAdapter.d.ts +4 -4
  388. package/src/lib/services/sessionAdapter.d.ts.map +1 -1
  389. package/src/lib/services/sessionAdapter.js +3 -2
  390. package/src/lib/services/sessionAdapter.js.map +1 -1
  391. package/src/lib/services/webSocketMessageServer.js +7 -4
  392. package/src/lib/services/webSocketMessageServer.js.map +1 -1
  393. package/src/lib/services/webSocketPeerProvider.js +2 -1
  394. package/src/lib/services/webSocketPeerProvider.js.map +1 -1
  395. package/src/lib/services/websocketHandler.js +9 -1
  396. package/src/lib/services/websocketHandler.js.map +1 -1
  397. package/src/lib/shared-types.d.ts +1 -2
  398. package/src/lib/shared-types.d.ts.map +1 -1
  399. package/src/lib/stores/__tests__/helpers/mockCloudBlockStore.d.ts +63 -0
  400. package/src/lib/stores/__tests__/helpers/mockCloudBlockStore.d.ts.map +1 -0
  401. package/src/lib/stores/__tests__/helpers/mockCloudBlockStore.js +160 -0
  402. package/src/lib/stores/__tests__/helpers/mockCloudBlockStore.js.map +1 -0
  403. package/src/lib/stores/availabilityAwareBlockStore.js +34 -5
  404. package/src/lib/stores/availabilityAwareBlockStore.js.map +1 -1
  405. package/src/lib/stores/cloudBlockStoreBase.d.ts +121 -0
  406. package/src/lib/stores/cloudBlockStoreBase.d.ts.map +1 -0
  407. package/src/lib/stores/cloudBlockStoreBase.js +1165 -0
  408. package/src/lib/stores/cloudBlockStoreBase.js.map +1 -0
  409. package/src/lib/stores/diskBlockAsyncStore.js +9 -5
  410. package/src/lib/stores/diskBlockAsyncStore.js.map +1 -1
  411. package/src/lib/stores/diskBlockMetadataStore.js +2 -0
  412. package/src/lib/stores/diskBlockMetadataStore.js.map +1 -1
  413. package/src/lib/stores/diskBlockStore.js +10 -8
  414. package/src/lib/stores/diskBlockStore.js.map +1 -1
  415. package/src/lib/stores/diskCBLStore.d.ts.map +1 -1
  416. package/src/lib/stores/diskCBLStore.js +8 -0
  417. package/src/lib/stores/diskCBLStore.js.map +1 -1
  418. package/src/lib/stores/index.d.ts +1 -0
  419. package/src/lib/stores/index.d.ts.map +1 -1
  420. package/src/lib/stores/index.js +1 -0
  421. package/src/lib/stores/index.js.map +1 -1
  422. package/src/lib/systemKeyring.d.ts.map +1 -1
  423. package/src/lib/systemKeyring.js +5 -4
  424. package/src/lib/systemKeyring.js.map +1 -1
  425. package/src/lib/transforms/checksumTransform.js +1 -0
  426. package/src/lib/transforms/checksumTransform.js.map +1 -1
  427. package/src/lib/transforms/memoryWritableStream.js +1 -0
  428. package/src/lib/transforms/memoryWritableStream.js.map +1 -1
  429. package/src/lib/transforms/xorMultipleTransform.js +3 -0
  430. package/src/lib/transforms/xorMultipleTransform.js.map +1 -1
  431. package/src/lib/utils/rehydration.d.ts +1 -1
  432. package/src/lib/utils/rehydration.js +1 -1
  433. package/src/lib/utils/serialization.d.ts +1 -1
  434. package/src/lib/utils/serialization.js +1 -1
  435. package/src/lib/services/backupCodeService.d.ts +0 -35
  436. package/src/lib/services/backupCodeService.d.ts.map +0 -1
  437. package/src/lib/services/backupCodeService.js +0 -109
  438. package/src/lib/services/backupCodeService.js.map +0 -1
@@ -0,0 +1,768 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NotificationService = void 0;
4
+ exports.createNotificationService = createNotificationService;
5
+ const brighthub_lib_1 = require("@brightchain/brighthub-lib");
6
+ const crypto_1 = require("crypto");
7
+ // ═══════════════════════════════════════════════════════
8
+ // Notification type → category mapping
9
+ // ═══════════════════════════════════════════════════════
10
+ /**
11
+ * Maps each NotificationType to its NotificationCategory.
12
+ *
13
+ * Req 55.2 – Social: likes, reposts, quotes, replies, mentions
14
+ * Req 55.3 – Messages: new messages, message requests, message reactions
15
+ * Req 55.4 – Connections: new followers, follow requests, reconnect reminders
16
+ * Req 55.5 – System: account alerts, security notifications, feature announcements
17
+ */
18
+ const NOTIFICATION_TYPE_CATEGORY_MAP = {
19
+ // Social (Req 55.2)
20
+ [brighthub_lib_1.NotificationType.Like]: brighthub_lib_1.NotificationCategory.Social,
21
+ [brighthub_lib_1.NotificationType.Reply]: brighthub_lib_1.NotificationCategory.Social,
22
+ [brighthub_lib_1.NotificationType.Mention]: brighthub_lib_1.NotificationCategory.Social,
23
+ [brighthub_lib_1.NotificationType.Repost]: brighthub_lib_1.NotificationCategory.Social,
24
+ [brighthub_lib_1.NotificationType.Quote]: brighthub_lib_1.NotificationCategory.Social,
25
+ // Connections (Req 55.4)
26
+ [brighthub_lib_1.NotificationType.Follow]: brighthub_lib_1.NotificationCategory.Connections,
27
+ [brighthub_lib_1.NotificationType.FollowRequest]: brighthub_lib_1.NotificationCategory.Connections,
28
+ [brighthub_lib_1.NotificationType.ReconnectReminder]: brighthub_lib_1.NotificationCategory.Connections,
29
+ // Messages (Req 55.3)
30
+ [brighthub_lib_1.NotificationType.NewMessage]: brighthub_lib_1.NotificationCategory.Messages,
31
+ [brighthub_lib_1.NotificationType.MessageRequest]: brighthub_lib_1.NotificationCategory.Messages,
32
+ [brighthub_lib_1.NotificationType.MessageReaction]: brighthub_lib_1.NotificationCategory.Messages,
33
+ // System (Req 55.5)
34
+ [brighthub_lib_1.NotificationType.SystemAlert]: brighthub_lib_1.NotificationCategory.System,
35
+ [brighthub_lib_1.NotificationType.SecurityAlert]: brighthub_lib_1.NotificationCategory.System,
36
+ [brighthub_lib_1.NotificationType.FeatureAnnouncement]: brighthub_lib_1.NotificationCategory.System,
37
+ };
38
+ // ═══════════════════════════════════════════════════════
39
+ // NotificationService Implementation
40
+ // ═══════════════════════════════════════════════════════
41
+ /**
42
+ * Notification_Service implementation
43
+ * Handles notification CRUD, preferences, grouping, and real-time delivery
44
+ * @see Requirements: 9.1-9.7, 54.1-54.8
45
+ */
46
+ class NotificationService {
47
+ notificationsCollection;
48
+ preferencesCollection;
49
+ groupsCollection;
50
+ listMembersCollection;
51
+ connectionMetadataCollection;
52
+ categoryAssignmentsCollection;
53
+ connectionInteractionsCollection;
54
+ constructor(application) {
55
+ this.notificationsCollection = application.getModel('brighthub_notifications');
56
+ this.preferencesCollection =
57
+ application.getModel('brighthub_notification_preferences');
58
+ this.groupsCollection = application.getModel('brighthub_notification_groups');
59
+ this.listMembersCollection =
60
+ application.getModel('brighthub_connection_list_members');
61
+ this.connectionMetadataCollection =
62
+ application.getModel('brighthub_connection_metadata');
63
+ this.categoryAssignmentsCollection =
64
+ application.getModel('brighthub_connection_category_assignments');
65
+ this.connectionInteractionsCollection =
66
+ application.getModel('brighthub_connection_interactions');
67
+ }
68
+ // ═══════════════════════════════════════════════════════
69
+ // Private helpers
70
+ // ═══════════════════════════════════════════════════════
71
+ clampLimit(limit) {
72
+ const l = limit ?? brighthub_lib_1.DEFAULT_NOTIFICATION_PAGE_LIMIT;
73
+ return Math.min(Math.max(1, l), brighthub_lib_1.MAX_NOTIFICATION_PAGE_LIMIT);
74
+ }
75
+ recordToNotification(record) {
76
+ return {
77
+ _id: record._id,
78
+ recipientId: record.recipientId,
79
+ type: record.type,
80
+ category: record.category,
81
+ actorId: record.actorId,
82
+ targetId: record.targetId,
83
+ content: record.content,
84
+ clickThroughUrl: record.clickThroughUrl,
85
+ groupId: record.groupId,
86
+ isRead: record.isRead,
87
+ createdAt: record.createdAt,
88
+ };
89
+ }
90
+ getCategoryForType(type) {
91
+ return NOTIFICATION_TYPE_CATEGORY_MAP[type] ?? brighthub_lib_1.NotificationCategory.System;
92
+ }
93
+ /**
94
+ * Build default notification preferences for a user.
95
+ * All categories enabled, all channels enabled, no quiet hours, no DND, sound on.
96
+ */
97
+ buildDefaultPreferences(userId) {
98
+ const defaultChannels = {
99
+ [brighthub_lib_1.NotificationChannel.InApp]: true,
100
+ [brighthub_lib_1.NotificationChannel.Email]: true,
101
+ [brighthub_lib_1.NotificationChannel.Push]: true,
102
+ };
103
+ const defaultCategorySettings = {
104
+ [brighthub_lib_1.NotificationCategory.Social]: {
105
+ enabled: true,
106
+ channels: { ...defaultChannels },
107
+ },
108
+ [brighthub_lib_1.NotificationCategory.Messages]: {
109
+ enabled: true,
110
+ channels: { ...defaultChannels },
111
+ },
112
+ [brighthub_lib_1.NotificationCategory.Connections]: {
113
+ enabled: true,
114
+ channels: { ...defaultChannels },
115
+ },
116
+ [brighthub_lib_1.NotificationCategory.System]: {
117
+ enabled: true,
118
+ channels: { ...defaultChannels },
119
+ },
120
+ };
121
+ return {
122
+ userId,
123
+ categorySettings: defaultCategorySettings,
124
+ channelSettings: { ...defaultChannels },
125
+ soundEnabled: true,
126
+ };
127
+ }
128
+ /**
129
+ * Get existing preferences from DB or create and persist defaults.
130
+ * Req 56.11: Store preferences in user profile and sync across devices.
131
+ */
132
+ async getOrCreateDefaultPreferences(userId) {
133
+ const existing = await this.preferencesCollection
134
+ .findOne({ userId })
135
+ .exec();
136
+ if (existing) {
137
+ return this.recordToPreferences(existing);
138
+ }
139
+ // Create default preferences and persist
140
+ const defaults = this.buildDefaultPreferences(userId);
141
+ const now = new Date().toISOString();
142
+ const record = {
143
+ _id: (0, crypto_1.randomUUID)(),
144
+ userId,
145
+ categorySettings: defaults.categorySettings,
146
+ channelSettings: defaults.channelSettings,
147
+ soundEnabled: defaults.soundEnabled,
148
+ updatedAt: now,
149
+ };
150
+ await this.preferencesCollection.create(record);
151
+ return defaults;
152
+ }
153
+ /**
154
+ * Convert a DB record to IBaseNotificationPreferences<string>.
155
+ */
156
+ recordToPreferences(record) {
157
+ const prefs = {
158
+ userId: record.userId,
159
+ categorySettings: record.categorySettings,
160
+ channelSettings: record.channelSettings,
161
+ soundEnabled: record.soundEnabled,
162
+ };
163
+ if (record.quietHours) {
164
+ prefs.quietHours = record.quietHours;
165
+ }
166
+ if (record.dndConfig) {
167
+ prefs.dndConfig = record.dndConfig;
168
+ }
169
+ return prefs;
170
+ }
171
+ /**
172
+ * Check if the current time falls within the quiet hours window.
173
+ * Req 56.5: Suppress in-app notifications during quiet hours.
174
+ * Req 56.6: Quiet hours with start/end times and timezone.
175
+ */
176
+ isWithinQuietHours(config) {
177
+ if (!config.enabled) {
178
+ return false;
179
+ }
180
+ // Parse HH:mm times
181
+ const parseTime = (timeStr) => {
182
+ const match = /^(\d{2}):(\d{2})$/.exec(timeStr);
183
+ if (!match)
184
+ return null;
185
+ return { hours: parseInt(match[1], 10), minutes: parseInt(match[2], 10) };
186
+ };
187
+ const start = parseTime(config.startTime);
188
+ const end = parseTime(config.endTime);
189
+ if (!start || !end)
190
+ return false;
191
+ // Get current time in the specified timezone
192
+ let nowHours;
193
+ let nowMinutes;
194
+ try {
195
+ const nowInTz = new Date().toLocaleString('en-US', {
196
+ timeZone: config.timezone,
197
+ hour12: false,
198
+ hour: '2-digit',
199
+ minute: '2-digit',
200
+ });
201
+ // Format: "HH:MM"
202
+ const parts = nowInTz.split(':');
203
+ nowHours = parseInt(parts[0], 10);
204
+ nowMinutes = parseInt(parts[1], 10);
205
+ }
206
+ catch {
207
+ // Invalid timezone — treat as not within quiet hours
208
+ return false;
209
+ }
210
+ const nowTotal = nowHours * 60 + nowMinutes;
211
+ const startTotal = start.hours * 60 + start.minutes;
212
+ const endTotal = end.hours * 60 + end.minutes;
213
+ // Handle overnight quiet hours (e.g., 22:00 - 07:00)
214
+ if (startTotal <= endTotal) {
215
+ return nowTotal >= startTotal && nowTotal < endTotal;
216
+ }
217
+ else {
218
+ return nowTotal >= startTotal || nowTotal < endTotal;
219
+ }
220
+ }
221
+ /**
222
+ * Check if Do Not Disturb is currently active.
223
+ * Req 56.7: DND suppresses all non-critical notifications.
224
+ * Req 56.8: DND duration options.
225
+ */
226
+ isDndActive(config) {
227
+ if (!config.enabled) {
228
+ return false;
229
+ }
230
+ // If there's an expiration, check if it has passed
231
+ if (config.expiresAt) {
232
+ const expiresAt = new Date(config.expiresAt);
233
+ if (new Date() >= expiresAt) {
234
+ return false;
235
+ }
236
+ }
237
+ // Enabled with no expiration (permanent) or not yet expired
238
+ return true;
239
+ }
240
+ /**
241
+ * Check if a notification type is critical (should bypass DND/quiet hours).
242
+ * Req 56.9: Critical system notifications delivered even during DND.
243
+ */
244
+ isCriticalNotificationType(type) {
245
+ return (type === brighthub_lib_1.NotificationType.SecurityAlert ||
246
+ type === brighthub_lib_1.NotificationType.SystemAlert);
247
+ }
248
+ // ═══════════════════════════════════════════════════════
249
+ // Notification CRUD (Req 9.1-9.7, 54.1-54.8)
250
+ // ═══════════════════════════════════════════════════════
251
+ async createNotification(recipientId, type, actorId, options) {
252
+ if (!recipientId || !actorId) {
253
+ throw new brighthub_lib_1.NotificationServiceError(brighthub_lib_1.NotificationErrorCode.InvalidInput, 'recipientId and actorId are required');
254
+ }
255
+ // Req 9.10: Suppress notifications from quiet-mode connections
256
+ const isQuiet = await this.isQuietModeConnection(recipientId, actorId);
257
+ if (isQuiet) {
258
+ return null;
259
+ }
260
+ const category = this.getCategoryForType(type);
261
+ const isCritical = this.isCriticalNotificationType(type);
262
+ // Req 56.4: Respect user preferences when creating notifications
263
+ if (!isCritical) {
264
+ const prefs = await this.getOrCreateDefaultPreferences(recipientId);
265
+ // Check if the category is disabled (Req 56.1-56.3)
266
+ const catSettings = prefs.categorySettings[category];
267
+ if (catSettings && !catSettings.enabled) {
268
+ return null;
269
+ }
270
+ // Req 56.5-56.6: Check quiet hours
271
+ if (prefs.quietHours && this.isWithinQuietHours(prefs.quietHours)) {
272
+ return null;
273
+ }
274
+ // Req 56.7-56.8: Check DND
275
+ if (prefs.dndConfig && this.isDndActive(prefs.dndConfig)) {
276
+ return null;
277
+ }
278
+ }
279
+ const now = new Date().toISOString();
280
+ const record = {
281
+ _id: (0, crypto_1.randomUUID)(),
282
+ recipientId,
283
+ type,
284
+ category,
285
+ actorId,
286
+ targetId: options?.targetId,
287
+ content: options?.content ?? '',
288
+ clickThroughUrl: options?.clickThroughUrl ?? '',
289
+ isRead: false,
290
+ createdAt: now,
291
+ };
292
+ await this.notificationsCollection.create(record);
293
+ return this.recordToNotification(record);
294
+ }
295
+ async getNotifications(userId, options) {
296
+ const limit = this.clampLimit(options?.limit);
297
+ // Build filter
298
+ const filter = { recipientId: userId };
299
+ if (options?.category) {
300
+ filter.category = options.category;
301
+ }
302
+ if (options?.isRead !== undefined) {
303
+ filter.isRead = options.isRead;
304
+ }
305
+ // Query with reverse chronological order
306
+ let query = this.notificationsCollection.find(filter);
307
+ if (query.sort) {
308
+ query = query.sort({ createdAt: -1 });
309
+ }
310
+ // Cursor-based pagination: skip past cursor
311
+ if (options?.cursor && query.skip) {
312
+ const cursorIndex = parseInt(options.cursor, 10);
313
+ if (!isNaN(cursorIndex) && cursorIndex > 0) {
314
+ query = query.skip(cursorIndex);
315
+ }
316
+ }
317
+ // Fetch limit + 1 to determine hasMore
318
+ if (query.limit) {
319
+ query = query.limit(limit + 1);
320
+ }
321
+ const records = await query.exec();
322
+ const hasMore = records.length > limit;
323
+ const items = records
324
+ .slice(0, limit)
325
+ .map((r) => this.recordToNotification(r));
326
+ // Calculate next cursor
327
+ const currentOffset = options?.cursor
328
+ ? parseInt(options.cursor, 10) || 0
329
+ : 0;
330
+ const nextCursor = hasMore ? String(currentOffset + limit) : undefined;
331
+ return {
332
+ items,
333
+ cursor: nextCursor,
334
+ hasMore,
335
+ };
336
+ }
337
+ async getUnreadCount(userId) {
338
+ const filter = {
339
+ recipientId: userId,
340
+ isRead: false,
341
+ };
342
+ if (this.notificationsCollection.countDocuments) {
343
+ return this.notificationsCollection.countDocuments(filter).exec();
344
+ }
345
+ // Fallback: count via find
346
+ const records = await this.notificationsCollection.find(filter).exec();
347
+ return records.length;
348
+ }
349
+ async markAsRead(notificationId, userId) {
350
+ const record = await this.notificationsCollection
351
+ .findOne({ _id: notificationId })
352
+ .exec();
353
+ if (!record) {
354
+ throw new brighthub_lib_1.NotificationServiceError(brighthub_lib_1.NotificationErrorCode.NotificationNotFound, `Notification ${notificationId} not found`);
355
+ }
356
+ if (record.recipientId !== userId) {
357
+ throw new brighthub_lib_1.NotificationServiceError(brighthub_lib_1.NotificationErrorCode.Unauthorized, "Cannot mark another user's notification as read");
358
+ }
359
+ await this.notificationsCollection
360
+ .updateOne({ _id: notificationId }, { isRead: true })
361
+ .exec();
362
+ }
363
+ async markAllAsRead(userId) {
364
+ // Find all unread notifications for the user and mark them as read
365
+ const unread = await this.notificationsCollection
366
+ .find({
367
+ recipientId: userId,
368
+ isRead: false,
369
+ })
370
+ .exec();
371
+ for (const record of unread) {
372
+ await this.notificationsCollection
373
+ .updateOne({ _id: record._id }, { isRead: true })
374
+ .exec();
375
+ }
376
+ }
377
+ async deleteNotification(notificationId, userId) {
378
+ const record = await this.notificationsCollection
379
+ .findOne({ _id: notificationId })
380
+ .exec();
381
+ if (!record) {
382
+ throw new brighthub_lib_1.NotificationServiceError(brighthub_lib_1.NotificationErrorCode.NotificationNotFound, `Notification ${notificationId} not found`);
383
+ }
384
+ if (record.recipientId !== userId) {
385
+ throw new brighthub_lib_1.NotificationServiceError(brighthub_lib_1.NotificationErrorCode.Unauthorized, "Cannot delete another user's notification");
386
+ }
387
+ await this.notificationsCollection
388
+ .deleteOne({ _id: notificationId })
389
+ .exec();
390
+ }
391
+ async deleteAllNotifications(userId) {
392
+ if (this.notificationsCollection.deleteMany) {
393
+ await this.notificationsCollection
394
+ .deleteMany({ recipientId: userId })
395
+ .exec();
396
+ return;
397
+ }
398
+ // Fallback: delete one by one
399
+ const records = await this.notificationsCollection
400
+ .find({ recipientId: userId })
401
+ .exec();
402
+ for (const record of records) {
403
+ await this.notificationsCollection
404
+ .deleteOne({ _id: record._id })
405
+ .exec();
406
+ }
407
+ }
408
+ // ═══════════════════════════════════════════════════════
409
+ // Filtering (Req 9.8-9.12)
410
+ // ═══════════════════════════════════════════════════════
411
+ /**
412
+ * Req 9.8: Get notifications filtered by connection list members.
413
+ * Returns only notifications where the actorId is a member of the given list.
414
+ */
415
+ async getNotificationsByList(userId, listId, options) {
416
+ // Get all member userIds from the list
417
+ const memberRecords = await this.listMembersCollection
418
+ .find({ listId })
419
+ .exec();
420
+ const memberIds = new Set(memberRecords.map((m) => m.userId));
421
+ // Get all notifications for the user, then filter by actor membership
422
+ const allResult = await this.getNotifications(userId, options);
423
+ const filtered = allResult.items.filter((n) => memberIds.has(n.actorId));
424
+ return {
425
+ items: filtered,
426
+ cursor: allResult.cursor,
427
+ hasMore: allResult.hasMore,
428
+ };
429
+ }
430
+ /**
431
+ * Req 9.9: Get notifications filtered by connection category.
432
+ * Returns only notifications where the actorId is in the given category.
433
+ */
434
+ async getNotificationsByConnectionCategory(userId, categoryId, options) {
435
+ // Get all connections assigned to this category for this user
436
+ const assignments = await this.categoryAssignmentsCollection
437
+ .find({
438
+ ownerId: userId,
439
+ categoryId,
440
+ })
441
+ .exec();
442
+ const connectionIds = new Set(assignments.map((a) => a.connectionId));
443
+ // Get all notifications for the user, then filter by actor in category
444
+ const allResult = await this.getNotifications(userId, options);
445
+ const filtered = allResult.items.filter((n) => connectionIds.has(n.actorId));
446
+ return {
447
+ items: filtered,
448
+ cursor: allResult.cursor,
449
+ hasMore: allResult.hasMore,
450
+ };
451
+ }
452
+ /**
453
+ * Req 9.10: Check if a connection has quiet mode enabled.
454
+ */
455
+ async isQuietModeConnection(userId, connectionId) {
456
+ const metadata = await this.connectionMetadataCollection
457
+ .findOne({
458
+ userId,
459
+ connectionId,
460
+ })
461
+ .exec();
462
+ return metadata?.isQuiet === true;
463
+ }
464
+ /**
465
+ * Req 9.12: Create a reconnect reminder for a 30-day inactive connection.
466
+ * Checks that the connection hasn't interacted in RECONNECT_REMINDER_DAYS days,
467
+ * then creates a notification with type ReconnectReminder and category Connections.
468
+ */
469
+ async createReconnectReminder(userId, connectionId) {
470
+ // Look up the interaction record
471
+ const interaction = await this.connectionInteractionsCollection
472
+ .findOne({
473
+ userId,
474
+ connectionId,
475
+ })
476
+ .exec();
477
+ const cutoffDate = new Date();
478
+ cutoffDate.setDate(cutoffDate.getDate() - brighthub_lib_1.RECONNECT_REMINDER_DAYS);
479
+ // If there's a recent interaction, don't create a reminder
480
+ if (interaction?.lastInteractionAt) {
481
+ const lastInteraction = new Date(interaction.lastInteractionAt);
482
+ if (lastInteraction > cutoffDate) {
483
+ throw new brighthub_lib_1.NotificationServiceError(brighthub_lib_1.NotificationErrorCode.InvalidInput, `Connection ${connectionId} has interacted within the last ${brighthub_lib_1.RECONNECT_REMINDER_DAYS} days`);
484
+ }
485
+ }
486
+ // Create the reconnect reminder notification directly (bypass quiet mode check
487
+ // since this is a system-initiated reminder, not an actor-initiated notification)
488
+ const now = new Date().toISOString();
489
+ const record = {
490
+ _id: (0, crypto_1.randomUUID)(),
491
+ recipientId: userId,
492
+ type: brighthub_lib_1.NotificationType.ReconnectReminder,
493
+ category: brighthub_lib_1.NotificationCategory.Connections,
494
+ actorId: connectionId,
495
+ content: `You haven't interacted with this connection in ${brighthub_lib_1.RECONNECT_REMINDER_DAYS} days. Consider reconnecting!`,
496
+ clickThroughUrl: `/users/${connectionId}`,
497
+ isRead: false,
498
+ createdAt: now,
499
+ };
500
+ await this.notificationsCollection.create(record);
501
+ return this.recordToNotification(record);
502
+ }
503
+ // ═══════════════════════════════════════════════════════
504
+ // Preferences (Req 56.1-56.12)
505
+ // ═══════════════════════════════════════════════════════
506
+ /**
507
+ * Get notification preferences for a user.
508
+ * Returns existing preferences or creates defaults if none exist.
509
+ * Req 56.11: Store preferences in user profile and sync across devices.
510
+ */
511
+ async getPreferences(userId) {
512
+ return this.getOrCreateDefaultPreferences(userId);
513
+ }
514
+ /**
515
+ * Update notification preferences for a user.
516
+ * Merges partial updates into existing preferences.
517
+ * Req 56.1-56.3: Per-category enable/disable and per-channel settings.
518
+ * Req 56.10: Sound preferences.
519
+ * Req 56.12: Preferences update reflected immediately.
520
+ */
521
+ async updatePreferences(userId, preferences) {
522
+ const existing = await this.getOrCreateDefaultPreferences(userId);
523
+ // Merge category settings
524
+ if (preferences.categorySettings) {
525
+ for (const cat of Object.values(brighthub_lib_1.NotificationCategory)) {
526
+ if (preferences.categorySettings[cat]) {
527
+ existing.categorySettings[cat] = {
528
+ ...existing.categorySettings[cat],
529
+ ...preferences.categorySettings[cat],
530
+ channels: {
531
+ ...existing.categorySettings[cat].channels,
532
+ ...(preferences.categorySettings[cat].channels ?? {}),
533
+ },
534
+ };
535
+ }
536
+ }
537
+ }
538
+ // Merge channel settings
539
+ if (preferences.channelSettings) {
540
+ existing.channelSettings = {
541
+ ...existing.channelSettings,
542
+ ...preferences.channelSettings,
543
+ };
544
+ }
545
+ // Merge optional fields
546
+ if (preferences.quietHours !== undefined) {
547
+ existing.quietHours = preferences.quietHours;
548
+ }
549
+ if (preferences.dndConfig !== undefined) {
550
+ existing.dndConfig = preferences.dndConfig;
551
+ }
552
+ if (preferences.soundEnabled !== undefined) {
553
+ existing.soundEnabled = preferences.soundEnabled;
554
+ }
555
+ // Save to database
556
+ const now = new Date().toISOString();
557
+ await this.preferencesCollection
558
+ .updateOne({ userId }, {
559
+ categorySettings: existing.categorySettings,
560
+ channelSettings: existing.channelSettings,
561
+ quietHours: existing.quietHours,
562
+ dndConfig: existing.dndConfig,
563
+ soundEnabled: existing.soundEnabled,
564
+ updatedAt: now,
565
+ })
566
+ .exec();
567
+ return existing;
568
+ }
569
+ /**
570
+ * Set quiet hours configuration.
571
+ * Req 56.5: Suppress in-app notifications during quiet hours.
572
+ * Req 56.6: Start/end times with timezone support.
573
+ */
574
+ async setQuietHours(userId, config) {
575
+ // Validate HH:mm format
576
+ const timeRegex = /^\d{2}:\d{2}$/;
577
+ if (!timeRegex.test(config.startTime) || !timeRegex.test(config.endTime)) {
578
+ throw new brighthub_lib_1.NotificationServiceError(brighthub_lib_1.NotificationErrorCode.InvalidQuietHoursConfig, 'startTime and endTime must be in HH:mm format');
579
+ }
580
+ // Validate timezone is non-empty
581
+ if (!config.timezone || config.timezone.trim().length === 0) {
582
+ throw new brighthub_lib_1.NotificationServiceError(brighthub_lib_1.NotificationErrorCode.InvalidQuietHoursConfig, 'timezone is required');
583
+ }
584
+ // Get or create preferences, then update quiet hours
585
+ await this.getOrCreateDefaultPreferences(userId);
586
+ const now = new Date().toISOString();
587
+ await this.preferencesCollection
588
+ .updateOne({ userId }, {
589
+ quietHours: config,
590
+ updatedAt: now,
591
+ })
592
+ .exec();
593
+ }
594
+ /**
595
+ * Set Do Not Disturb configuration.
596
+ * Req 56.7: DND suppresses all non-critical notifications.
597
+ * Req 56.8: Duration options (1h, 8h, 24h, until manually disabled).
598
+ * Req 56.9: Critical system notifications still delivered during DND.
599
+ */
600
+ async setDoNotDisturb(userId, config) {
601
+ // Calculate expiresAt from duration if provided
602
+ const resolvedConfig = { ...config };
603
+ if (config.enabled && config.duration && !config.expiresAt) {
604
+ const now = new Date();
605
+ const durationMs = this.parseDurationToMs(config.duration);
606
+ if (durationMs > 0) {
607
+ resolvedConfig.expiresAt = new Date(now.getTime() + durationMs).toISOString();
608
+ }
609
+ // Permanent duration: no expiresAt
610
+ }
611
+ // Get or create preferences, then update DND config
612
+ await this.getOrCreateDefaultPreferences(userId);
613
+ const now = new Date().toISOString();
614
+ await this.preferencesCollection
615
+ .updateOne({ userId }, {
616
+ dndConfig: resolvedConfig,
617
+ updatedAt: now,
618
+ })
619
+ .exec();
620
+ }
621
+ /**
622
+ * Convert a MuteDuration to milliseconds.
623
+ * Returns 0 for Permanent (no expiration).
624
+ */
625
+ parseDurationToMs(duration) {
626
+ switch (duration) {
627
+ case brighthub_lib_1.MuteDuration.OneHour:
628
+ return 60 * 60 * 1000;
629
+ case brighthub_lib_1.MuteDuration.EightHours:
630
+ return 8 * 60 * 60 * 1000;
631
+ case brighthub_lib_1.MuteDuration.TwentyFourHours:
632
+ return 24 * 60 * 60 * 1000;
633
+ case brighthub_lib_1.MuteDuration.SevenDays:
634
+ return 7 * 24 * 60 * 60 * 1000;
635
+ case brighthub_lib_1.MuteDuration.ThirtyDays:
636
+ return 30 * 24 * 60 * 60 * 1000;
637
+ case brighthub_lib_1.MuteDuration.Permanent:
638
+ return 0;
639
+ default:
640
+ return 0;
641
+ }
642
+ }
643
+ // ═══════════════════════════════════════════════════════
644
+ // Grouping (Req 55.6-55.9)
645
+ // ═══════════════════════════════════════════════════════
646
+ /**
647
+ * Group notifications by type and target within the grouping window (1 hour).
648
+ *
649
+ * Req 55.6: Same action on same content within 1 hour → single grouped notification
650
+ * Req 55.7: Grouped notification displays count and list of actors
651
+ * Req 55.8: Individual actors with timestamps available via notificationIds
652
+ * Req 55.9: Supports ungrouping via skipGrouping flag (preference-driven)
653
+ *
654
+ * @param notifications - Array of notifications to group
655
+ * @param skipGrouping - When true, each notification becomes its own group (Req 55.9)
656
+ * @returns Array of notification groups
657
+ */
658
+ async groupNotifications(notifications, skipGrouping) {
659
+ if (notifications.length === 0) {
660
+ return [];
661
+ }
662
+ // Req 55.9: If ungrouping is preferred, return each notification as its own group
663
+ if (skipGrouping) {
664
+ return notifications.map((n) => ({
665
+ _id: (0, crypto_1.randomUUID)(),
666
+ groupKey: `${n.type}:${n.targetId ?? n._id}`,
667
+ notificationIds: [n._id],
668
+ actorIds: [n.actorId],
669
+ count: 1,
670
+ latestAt: n.createdAt,
671
+ }));
672
+ }
673
+ // Sort notifications by createdAt ascending so we process oldest first
674
+ const sorted = [...notifications].sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
675
+ // Build groups keyed by type:targetId.
676
+ // Within each key, we may have multiple time-window clusters.
677
+ const groupClusters = new Map();
678
+ for (const notification of sorted) {
679
+ const groupKey = `${notification.type}:${notification.targetId ?? notification._id}`;
680
+ const createdAtMs = new Date(notification.createdAt).getTime();
681
+ if (!groupClusters.has(groupKey)) {
682
+ groupClusters.set(groupKey, []);
683
+ }
684
+ const clusters = groupClusters.get(groupKey);
685
+ // Try to find an existing cluster where this notification fits
686
+ // (within NOTIFICATION_GROUPING_WINDOW_MS of the cluster's earliest notification)
687
+ let addedToCluster = false;
688
+ for (const cluster of clusters) {
689
+ if (createdAtMs - cluster.earliestAt <
690
+ brighthub_lib_1.NOTIFICATION_GROUPING_WINDOW_MS) {
691
+ cluster.notificationIds.push(notification._id);
692
+ cluster.actorIds.add(notification.actorId);
693
+ if (createdAtMs > cluster.latestAt) {
694
+ cluster.latestAt = createdAtMs;
695
+ }
696
+ addedToCluster = true;
697
+ break;
698
+ }
699
+ }
700
+ // No matching cluster found — start a new one
701
+ if (!addedToCluster) {
702
+ clusters.push({
703
+ notificationIds: [notification._id],
704
+ actorIds: new Set([notification.actorId]),
705
+ earliestAt: createdAtMs,
706
+ latestAt: createdAtMs,
707
+ });
708
+ }
709
+ }
710
+ // Convert clusters to IBaseNotificationGroup<string>
711
+ const groups = [];
712
+ for (const [groupKey, clusters] of groupClusters) {
713
+ for (const cluster of clusters) {
714
+ groups.push({
715
+ _id: (0, crypto_1.randomUUID)(),
716
+ groupKey,
717
+ notificationIds: cluster.notificationIds,
718
+ actorIds: Array.from(cluster.actorIds),
719
+ count: cluster.notificationIds.length,
720
+ latestAt: new Date(cluster.latestAt).toISOString(),
721
+ });
722
+ }
723
+ }
724
+ // Sort groups by latestAt descending (most recent first)
725
+ groups.sort((a, b) => new Date(b.latestAt).getTime() - new Date(a.latestAt).getTime());
726
+ return groups;
727
+ }
728
+ // ═══════════════════════════════════════════════════════
729
+ // Real-time (Req 52.4, 52.5) — Task 20
730
+ // ═══════════════════════════════════════════════════════
731
+ wsHandler = null;
732
+ /**
733
+ * Late-bind the WebSocket handler for real-time notification delivery.
734
+ * Called after both NotificationService and BrightHubWebSocketHandler are created.
735
+ */
736
+ setWebSocketHandler(handler) {
737
+ this.wsHandler = handler;
738
+ }
739
+ subscribeToNotifications(_userId, _callback) {
740
+ // Real-time subscriptions are handled by BrightHubWebSocketHandler
741
+ // via room-based pub/sub on ClientWebSocketServer.
742
+ // This method is kept for interface compatibility.
743
+ return () => {
744
+ /* unsubscribe is handled by WebSocket disconnect */
745
+ };
746
+ }
747
+ async broadcastNotification(notification) {
748
+ if (this.wsHandler) {
749
+ this.wsHandler.broadcastNotification(notification);
750
+ // Also send updated unread count
751
+ const count = await this.getUnreadCount(notification.recipientId);
752
+ this.wsHandler.broadcastNotificationCount(notification.recipientId, count);
753
+ }
754
+ }
755
+ }
756
+ exports.NotificationService = NotificationService;
757
+ // ═══════════════════════════════════════════════════════
758
+ // Factory function
759
+ // ═══════════════════════════════════════════════════════
760
+ /**
761
+ * Create a new NotificationService instance
762
+ * @param application Application with database collections
763
+ * @returns NotificationService instance
764
+ */
765
+ function createNotificationService(application) {
766
+ return new NotificationService(application);
767
+ }
768
+ //# sourceMappingURL=notificationService.js.map