@enbox/dwn-server 0.0.2 → 0.0.4

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 (309) hide show
  1. package/LICENSE +3 -2
  2. package/README.md +115 -215
  3. package/dist/esm/src/admin/activity-log.d.ts +44 -0
  4. package/dist/esm/src/admin/activity-log.d.ts.map +1 -0
  5. package/dist/esm/src/admin/activity-log.js +85 -0
  6. package/dist/esm/src/admin/activity-log.js.map +1 -0
  7. package/dist/esm/src/admin/admin-api.d.ts +61 -0
  8. package/dist/esm/src/admin/admin-api.d.ts.map +1 -0
  9. package/dist/esm/src/admin/admin-api.js +1047 -0
  10. package/dist/esm/src/admin/admin-api.js.map +1 -0
  11. package/dist/esm/src/admin/admin-auth.d.ts +9 -0
  12. package/dist/esm/src/admin/admin-auth.d.ts.map +1 -0
  13. package/dist/esm/src/admin/admin-auth.js +45 -0
  14. package/dist/esm/src/admin/admin-auth.js.map +1 -0
  15. package/dist/esm/src/admin/admin-store.d.ts +111 -0
  16. package/dist/esm/src/admin/admin-store.d.ts.map +1 -0
  17. package/dist/esm/src/admin/admin-store.js +376 -0
  18. package/dist/esm/src/admin/admin-store.js.map +1 -0
  19. package/dist/esm/src/admin/audit-log.d.ts +94 -0
  20. package/dist/esm/src/admin/audit-log.d.ts.map +1 -0
  21. package/dist/esm/src/admin/audit-log.js +220 -0
  22. package/dist/esm/src/admin/audit-log.js.map +1 -0
  23. package/dist/esm/src/admin/index.d.ts +10 -0
  24. package/dist/esm/src/admin/index.d.ts.map +1 -0
  25. package/dist/esm/src/admin/index.js +7 -0
  26. package/dist/esm/src/admin/index.js.map +1 -0
  27. package/dist/esm/src/admin/types.d.ts +306 -0
  28. package/dist/esm/src/admin/types.d.ts.map +1 -0
  29. package/dist/esm/src/admin/types.js +2 -0
  30. package/dist/esm/src/admin/types.js.map +1 -0
  31. package/dist/esm/src/admin/webhook-manager.d.ts +55 -0
  32. package/dist/esm/src/admin/webhook-manager.d.ts.map +1 -0
  33. package/dist/esm/src/admin/webhook-manager.js +184 -0
  34. package/dist/esm/src/admin/webhook-manager.js.map +1 -0
  35. package/dist/esm/src/config.d.ts +124 -9
  36. package/dist/esm/src/config.d.ts.map +1 -1
  37. package/dist/esm/src/config.js +155 -13
  38. package/dist/esm/src/config.js.map +1 -1
  39. package/dist/esm/src/connection/connection-manager.d.ts +32 -9
  40. package/dist/esm/src/connection/connection-manager.d.ts.map +1 -1
  41. package/dist/esm/src/connection/connection-manager.js +38 -5
  42. package/dist/esm/src/connection/connection-manager.js.map +1 -1
  43. package/dist/esm/src/connection/flow-controller.d.ts +53 -0
  44. package/dist/esm/src/connection/flow-controller.d.ts.map +1 -0
  45. package/dist/esm/src/connection/flow-controller.js +101 -0
  46. package/dist/esm/src/connection/flow-controller.js.map +1 -0
  47. package/dist/esm/src/connection/socket-connection.d.ts +54 -18
  48. package/dist/esm/src/connection/socket-connection.d.ts.map +1 -1
  49. package/dist/esm/src/connection/socket-connection.js +102 -40
  50. package/dist/esm/src/connection/socket-connection.js.map +1 -1
  51. package/dist/esm/src/delivery-service.d.ts +43 -0
  52. package/dist/esm/src/delivery-service.d.ts.map +1 -0
  53. package/dist/esm/src/delivery-service.js +574 -0
  54. package/dist/esm/src/delivery-service.js.map +1 -0
  55. package/dist/esm/src/dwn-error.d.ts +10 -1
  56. package/dist/esm/src/dwn-error.d.ts.map +1 -1
  57. package/dist/esm/src/dwn-error.js +9 -0
  58. package/dist/esm/src/dwn-error.js.map +1 -1
  59. package/dist/esm/src/dwn-server.d.ts +13 -6
  60. package/dist/esm/src/dwn-server.d.ts.map +1 -1
  61. package/dist/esm/src/dwn-server.js +199 -24
  62. package/dist/esm/src/dwn-server.js.map +1 -1
  63. package/dist/esm/src/http-api.d.ts +28 -13
  64. package/dist/esm/src/http-api.d.ts.map +1 -1
  65. package/dist/esm/src/http-api.js +649 -374
  66. package/dist/esm/src/http-api.js.map +1 -1
  67. package/dist/esm/src/index.d.ts +6 -2
  68. package/dist/esm/src/index.d.ts.map +1 -1
  69. package/dist/esm/src/index.js +4 -1
  70. package/dist/esm/src/index.js.map +1 -1
  71. package/dist/esm/src/json-rpc-api.js +2 -1
  72. package/dist/esm/src/json-rpc-api.js.map +1 -1
  73. package/dist/esm/src/json-rpc-handlers/dwn/process-message.d.ts.map +1 -1
  74. package/dist/esm/src/json-rpc-handlers/dwn/process-message.js +109 -7
  75. package/dist/esm/src/json-rpc-handlers/dwn/process-message.js.map +1 -1
  76. package/dist/esm/src/json-rpc-handlers/subscription/ack.d.ts +20 -0
  77. package/dist/esm/src/json-rpc-handlers/subscription/ack.d.ts.map +1 -0
  78. package/dist/esm/src/json-rpc-handlers/subscription/ack.js +41 -0
  79. package/dist/esm/src/json-rpc-handlers/subscription/ack.js.map +1 -0
  80. package/dist/esm/src/json-rpc-handlers/subscription/close.d.ts.map +1 -1
  81. package/dist/esm/src/json-rpc-handlers/subscription/close.js +1 -1
  82. package/dist/esm/src/json-rpc-handlers/subscription/close.js.map +1 -1
  83. package/dist/esm/src/json-rpc-handlers/subscription/index.d.ts +1 -0
  84. package/dist/esm/src/json-rpc-handlers/subscription/index.d.ts.map +1 -1
  85. package/dist/esm/src/json-rpc-handlers/subscription/index.js +1 -0
  86. package/dist/esm/src/json-rpc-handlers/subscription/index.js.map +1 -1
  87. package/dist/esm/src/lib/json-rpc-router.d.ts +25 -8
  88. package/dist/esm/src/lib/json-rpc-router.d.ts.map +1 -1
  89. package/dist/esm/src/lib/json-rpc-router.js.map +1 -1
  90. package/dist/esm/src/lib/sql-utils.d.ts +6 -0
  91. package/dist/esm/src/lib/sql-utils.d.ts.map +1 -0
  92. package/dist/esm/src/lib/sql-utils.js +8 -0
  93. package/dist/esm/src/lib/sql-utils.js.map +1 -0
  94. package/dist/esm/src/main.js +0 -6
  95. package/dist/esm/src/main.js.map +1 -1
  96. package/dist/esm/src/message-processed-hook.d.ts +35 -0
  97. package/dist/esm/src/message-processed-hook.d.ts.map +1 -0
  98. package/dist/esm/src/message-processed-hook.js +2 -0
  99. package/dist/esm/src/message-processed-hook.js.map +1 -0
  100. package/dist/esm/src/metrics.d.ts +14 -2
  101. package/dist/esm/src/metrics.d.ts.map +1 -1
  102. package/dist/esm/src/metrics.js +41 -1
  103. package/dist/esm/src/metrics.js.map +1 -1
  104. package/dist/esm/src/plugins/event-log-nats.d.ts +25 -0
  105. package/dist/esm/src/plugins/event-log-nats.d.ts.map +1 -0
  106. package/dist/esm/src/plugins/event-log-nats.js +379 -0
  107. package/dist/esm/src/plugins/event-log-nats.js.map +1 -0
  108. package/dist/esm/src/rate-limiter.d.ts +60 -0
  109. package/dist/esm/src/rate-limiter.d.ts.map +1 -0
  110. package/dist/esm/src/rate-limiter.js +116 -0
  111. package/dist/esm/src/rate-limiter.js.map +1 -0
  112. package/dist/esm/src/registration/jwt-provider-auth-plugin.d.ts +53 -0
  113. package/dist/esm/src/registration/jwt-provider-auth-plugin.d.ts.map +1 -0
  114. package/dist/esm/src/registration/jwt-provider-auth-plugin.js +90 -0
  115. package/dist/esm/src/registration/jwt-provider-auth-plugin.js.map +1 -0
  116. package/dist/esm/src/registration/open-auth-handler.d.ts +37 -0
  117. package/dist/esm/src/registration/open-auth-handler.d.ts.map +1 -0
  118. package/dist/esm/src/registration/open-auth-handler.js +214 -0
  119. package/dist/esm/src/registration/open-auth-handler.js.map +1 -0
  120. package/dist/esm/src/registration/proof-of-work-manager.d.ts +1 -1
  121. package/dist/esm/src/registration/proof-of-work-manager.d.ts.map +1 -1
  122. package/dist/esm/src/registration/proof-of-work-manager.js +3 -3
  123. package/dist/esm/src/registration/proof-of-work-manager.js.map +1 -1
  124. package/dist/esm/src/registration/provider-auth-plugin.d.ts +46 -0
  125. package/dist/esm/src/registration/provider-auth-plugin.d.ts.map +1 -0
  126. package/dist/esm/src/registration/provider-auth-plugin.js +29 -0
  127. package/dist/esm/src/registration/provider-auth-plugin.js.map +1 -0
  128. package/dist/esm/src/registration/registration-manager.d.ts +28 -5
  129. package/dist/esm/src/registration/registration-manager.d.ts.map +1 -1
  130. package/dist/esm/src/registration/registration-manager.js +83 -12
  131. package/dist/esm/src/registration/registration-manager.js.map +1 -1
  132. package/dist/esm/src/registration/registration-store.d.ts +83 -3
  133. package/dist/esm/src/registration/registration-store.d.ts.map +1 -1
  134. package/dist/esm/src/registration/registration-store.js +248 -11
  135. package/dist/esm/src/registration/registration-store.js.map +1 -1
  136. package/dist/esm/src/storage.d.ts +5 -5
  137. package/dist/esm/src/storage.d.ts.map +1 -1
  138. package/dist/esm/src/storage.js +105 -24
  139. package/dist/esm/src/storage.js.map +1 -1
  140. package/dist/esm/src/web5-connect/sql-ttl-cache.d.ts.map +1 -1
  141. package/dist/esm/src/web5-connect/sql-ttl-cache.js +11 -3
  142. package/dist/esm/src/web5-connect/sql-ttl-cache.js.map +1 -1
  143. package/dist/esm/src/web5-connect/web5-connect-server.d.ts.map +1 -1
  144. package/dist/esm/src/web5-connect/web5-connect-server.js +2 -2
  145. package/dist/esm/src/web5-connect/web5-connect-server.js.map +1 -1
  146. package/dist/esm/src/ws-api.d.ts +18 -4
  147. package/dist/esm/src/ws-api.d.ts.map +1 -1
  148. package/dist/esm/src/ws-api.js +12 -16
  149. package/dist/esm/src/ws-api.js.map +1 -1
  150. package/package.json +34 -53
  151. package/src/admin/activity-log.ts +100 -0
  152. package/src/admin/admin-api.ts +1308 -0
  153. package/src/admin/admin-auth.ts +56 -0
  154. package/src/admin/admin-store.ts +515 -0
  155. package/src/admin/audit-log.ts +327 -0
  156. package/src/admin/index.ts +34 -0
  157. package/src/admin/types.ts +352 -0
  158. package/src/admin/webhook-manager.ts +245 -0
  159. package/src/config.ts +190 -22
  160. package/src/connection/connection-manager.ts +67 -17
  161. package/src/connection/flow-controller.ts +117 -0
  162. package/src/connection/socket-connection.ts +144 -67
  163. package/src/delivery-service.ts +740 -0
  164. package/src/dwn-error.ts +11 -2
  165. package/src/dwn-server.ts +254 -39
  166. package/src/http-api.ts +736 -392
  167. package/src/index.ts +13 -2
  168. package/src/json-rpc-api.ts +2 -1
  169. package/src/json-rpc-handlers/dwn/process-message.ts +149 -15
  170. package/src/json-rpc-handlers/subscription/ack.ts +63 -0
  171. package/src/json-rpc-handlers/subscription/close.ts +5 -9
  172. package/src/json-rpc-handlers/subscription/index.ts +1 -0
  173. package/src/lib/json-rpc-router.ts +26 -11
  174. package/src/lib/sql-utils.ts +7 -0
  175. package/src/main.ts +0 -8
  176. package/src/message-processed-hook.ts +33 -0
  177. package/src/metrics.ts +57 -8
  178. package/src/plugins/event-log-nats.ts +466 -0
  179. package/src/process-handlers.ts +5 -5
  180. package/src/rate-limiter.ts +143 -0
  181. package/src/registration/jwt-provider-auth-plugin.ts +119 -0
  182. package/src/registration/open-auth-handler.ts +263 -0
  183. package/src/registration/proof-of-work-manager.ts +11 -10
  184. package/src/registration/provider-auth-plugin.ts +84 -0
  185. package/src/registration/registration-manager.ts +129 -31
  186. package/src/registration/registration-store.ts +332 -22
  187. package/src/storage.ts +136 -40
  188. package/src/web5-connect/sql-ttl-cache.ts +12 -5
  189. package/src/web5-connect/web5-connect-server.ts +9 -8
  190. package/src/ws-api.ts +39 -26
  191. package/dist/cjs/index.js +0 -6811
  192. package/dist/cjs/package.json +0 -1
  193. package/dist/esm/src/json-rpc-socket.d.ts +0 -39
  194. package/dist/esm/src/json-rpc-socket.d.ts.map +0 -1
  195. package/dist/esm/src/json-rpc-socket.js +0 -125
  196. package/dist/esm/src/json-rpc-socket.js.map +0 -1
  197. package/dist/esm/src/lib/http-server-shutdown-handler.d.ts +0 -10
  198. package/dist/esm/src/lib/http-server-shutdown-handler.d.ts.map +0 -1
  199. package/dist/esm/src/lib/http-server-shutdown-handler.js +0 -65
  200. package/dist/esm/src/lib/http-server-shutdown-handler.js.map +0 -1
  201. package/dist/esm/src/lib/json-rpc.d.ts +0 -54
  202. package/dist/esm/src/lib/json-rpc.d.ts.map +0 -1
  203. package/dist/esm/src/lib/json-rpc.js +0 -60
  204. package/dist/esm/src/lib/json-rpc.js.map +0 -1
  205. package/dist/esm/src/registration/proof-of-work-types.d.ts +0 -8
  206. package/dist/esm/src/registration/proof-of-work-types.d.ts.map +0 -1
  207. package/dist/esm/src/registration/proof-of-work-types.js +0 -2
  208. package/dist/esm/src/registration/proof-of-work-types.js.map +0 -1
  209. package/dist/esm/src/registration/registration-types.d.ts +0 -18
  210. package/dist/esm/src/registration/registration-types.d.ts.map +0 -1
  211. package/dist/esm/src/registration/registration-types.js +0 -2
  212. package/dist/esm/src/registration/registration-types.js.map +0 -1
  213. package/dist/esm/tests/common-scenario-validator.d.ts +0 -11
  214. package/dist/esm/tests/common-scenario-validator.d.ts.map +0 -1
  215. package/dist/esm/tests/common-scenario-validator.js +0 -114
  216. package/dist/esm/tests/common-scenario-validator.js.map +0 -1
  217. package/dist/esm/tests/connection/connection-manager.spec.d.ts +0 -2
  218. package/dist/esm/tests/connection/connection-manager.spec.d.ts.map +0 -1
  219. package/dist/esm/tests/connection/connection-manager.spec.js +0 -47
  220. package/dist/esm/tests/connection/connection-manager.spec.js.map +0 -1
  221. package/dist/esm/tests/connection/socket-connection.spec.d.ts +0 -2
  222. package/dist/esm/tests/connection/socket-connection.spec.d.ts.map +0 -1
  223. package/dist/esm/tests/connection/socket-connection.spec.js +0 -125
  224. package/dist/esm/tests/connection/socket-connection.spec.js.map +0 -1
  225. package/dist/esm/tests/cors/http-api.browser.d.ts +0 -2
  226. package/dist/esm/tests/cors/http-api.browser.d.ts.map +0 -1
  227. package/dist/esm/tests/cors/http-api.browser.js +0 -60
  228. package/dist/esm/tests/cors/http-api.browser.js.map +0 -1
  229. package/dist/esm/tests/cors/ping.browser.d.ts +0 -2
  230. package/dist/esm/tests/cors/ping.browser.d.ts.map +0 -1
  231. package/dist/esm/tests/cors/ping.browser.js +0 -7
  232. package/dist/esm/tests/cors/ping.browser.js.map +0 -1
  233. package/dist/esm/tests/dwn-process-message.spec.d.ts +0 -2
  234. package/dist/esm/tests/dwn-process-message.spec.d.ts.map +0 -1
  235. package/dist/esm/tests/dwn-process-message.spec.js +0 -172
  236. package/dist/esm/tests/dwn-process-message.spec.js.map +0 -1
  237. package/dist/esm/tests/dwn-server.spec.d.ts +0 -2
  238. package/dist/esm/tests/dwn-server.spec.d.ts.map +0 -1
  239. package/dist/esm/tests/dwn-server.spec.js +0 -49
  240. package/dist/esm/tests/dwn-server.spec.js.map +0 -1
  241. package/dist/esm/tests/http-api.spec.d.ts +0 -2
  242. package/dist/esm/tests/http-api.spec.d.ts.map +0 -1
  243. package/dist/esm/tests/http-api.spec.js +0 -775
  244. package/dist/esm/tests/http-api.spec.js.map +0 -1
  245. package/dist/esm/tests/json-rpc-socket.spec.d.ts +0 -2
  246. package/dist/esm/tests/json-rpc-socket.spec.d.ts.map +0 -1
  247. package/dist/esm/tests/json-rpc-socket.spec.js +0 -225
  248. package/dist/esm/tests/json-rpc-socket.spec.js.map +0 -1
  249. package/dist/esm/tests/plugins/data-store-sqlite.d.ts +0 -17
  250. package/dist/esm/tests/plugins/data-store-sqlite.d.ts.map +0 -1
  251. package/dist/esm/tests/plugins/data-store-sqlite.js +0 -23
  252. package/dist/esm/tests/plugins/data-store-sqlite.js.map +0 -1
  253. package/dist/esm/tests/plugins/event-log-sqlite.d.ts +0 -17
  254. package/dist/esm/tests/plugins/event-log-sqlite.d.ts.map +0 -1
  255. package/dist/esm/tests/plugins/event-log-sqlite.js +0 -23
  256. package/dist/esm/tests/plugins/event-log-sqlite.js.map +0 -1
  257. package/dist/esm/tests/plugins/event-stream-in-memory.d.ts +0 -17
  258. package/dist/esm/tests/plugins/event-stream-in-memory.d.ts.map +0 -1
  259. package/dist/esm/tests/plugins/event-stream-in-memory.js +0 -21
  260. package/dist/esm/tests/plugins/event-stream-in-memory.js.map +0 -1
  261. package/dist/esm/tests/plugins/message-store-sqlite.d.ts +0 -17
  262. package/dist/esm/tests/plugins/message-store-sqlite.d.ts.map +0 -1
  263. package/dist/esm/tests/plugins/message-store-sqlite.js +0 -23
  264. package/dist/esm/tests/plugins/message-store-sqlite.js.map +0 -1
  265. package/dist/esm/tests/plugins/resumable-task-store-sqlite.d.ts +0 -17
  266. package/dist/esm/tests/plugins/resumable-task-store-sqlite.d.ts.map +0 -1
  267. package/dist/esm/tests/plugins/resumable-task-store-sqlite.js +0 -23
  268. package/dist/esm/tests/plugins/resumable-task-store-sqlite.js.map +0 -1
  269. package/dist/esm/tests/process-handler.spec.d.ts +0 -2
  270. package/dist/esm/tests/process-handler.spec.d.ts.map +0 -1
  271. package/dist/esm/tests/process-handler.spec.js +0 -60
  272. package/dist/esm/tests/process-handler.spec.js.map +0 -1
  273. package/dist/esm/tests/registration/proof-of-work-manager.spec.d.ts +0 -2
  274. package/dist/esm/tests/registration/proof-of-work-manager.spec.d.ts.map +0 -1
  275. package/dist/esm/tests/registration/proof-of-work-manager.spec.js +0 -157
  276. package/dist/esm/tests/registration/proof-of-work-manager.spec.js.map +0 -1
  277. package/dist/esm/tests/rpc-subscribe-close.spec.d.ts +0 -2
  278. package/dist/esm/tests/rpc-subscribe-close.spec.d.ts.map +0 -1
  279. package/dist/esm/tests/rpc-subscribe-close.spec.js +0 -81
  280. package/dist/esm/tests/rpc-subscribe-close.spec.js.map +0 -1
  281. package/dist/esm/tests/scenarios/dynamic-plugin-loading.spec.d.ts +0 -2
  282. package/dist/esm/tests/scenarios/dynamic-plugin-loading.spec.d.ts.map +0 -1
  283. package/dist/esm/tests/scenarios/dynamic-plugin-loading.spec.js +0 -73
  284. package/dist/esm/tests/scenarios/dynamic-plugin-loading.spec.js.map +0 -1
  285. package/dist/esm/tests/scenarios/registration.spec.d.ts +0 -2
  286. package/dist/esm/tests/scenarios/registration.spec.d.ts.map +0 -1
  287. package/dist/esm/tests/scenarios/registration.spec.js +0 -507
  288. package/dist/esm/tests/scenarios/registration.spec.js.map +0 -1
  289. package/dist/esm/tests/scenarios/web5-connect.spec.d.ts +0 -2
  290. package/dist/esm/tests/scenarios/web5-connect.spec.d.ts.map +0 -1
  291. package/dist/esm/tests/scenarios/web5-connect.spec.js +0 -137
  292. package/dist/esm/tests/scenarios/web5-connect.spec.js.map +0 -1
  293. package/dist/esm/tests/test-dwn.d.ts +0 -7
  294. package/dist/esm/tests/test-dwn.d.ts.map +0 -1
  295. package/dist/esm/tests/test-dwn.js +0 -34
  296. package/dist/esm/tests/test-dwn.js.map +0 -1
  297. package/dist/esm/tests/utils.d.ts +0 -46
  298. package/dist/esm/tests/utils.d.ts.map +0 -1
  299. package/dist/esm/tests/utils.js +0 -116
  300. package/dist/esm/tests/utils.js.map +0 -1
  301. package/dist/esm/tests/ws-api.spec.d.ts +0 -2
  302. package/dist/esm/tests/ws-api.spec.d.ts.map +0 -1
  303. package/dist/esm/tests/ws-api.spec.js +0 -327
  304. package/dist/esm/tests/ws-api.spec.js.map +0 -1
  305. package/src/json-rpc-socket.ts +0 -155
  306. package/src/lib/http-server-shutdown-handler.ts +0 -79
  307. package/src/lib/json-rpc.ts +0 -126
  308. package/src/registration/proof-of-work-types.ts +0 -7
  309. package/src/registration/registration-types.ts +0 -18
@@ -0,0 +1,101 @@
1
+ import log from 'loglevel';
2
+ import { createJsonRpcSuccessResponse } from '@enbox/dwn-clients';
3
+ /** Default maximum number of unacknowledged events before pausing delivery. */
4
+ export const DEFAULT_MAX_IN_FLIGHT = 32;
5
+ /** Maximum buffer size before the subscription is force-closed to prevent OOM. */
6
+ export const MAX_BUFFER_SIZE = 1000;
7
+ /**
8
+ * Per-subscription flow controller that enforces a sliding window of
9
+ * unacknowledged events. When the window is full, incoming events are
10
+ * buffered. When the client sends `rpc.ack` with a cursor, events up
11
+ * to that cursor are acknowledged and buffered events are flushed.
12
+ *
13
+ * If the buffer exceeds {@link MAX_BUFFER_SIZE}, the subscription is
14
+ * closed via the provided `onOverflow` callback to prevent unbounded
15
+ * memory growth.
16
+ */
17
+ export class FlowController {
18
+ subscriptionId;
19
+ maxInFlight;
20
+ send;
21
+ onOverflow;
22
+ /** Ordered list of cursors for events that have been sent but not yet acknowledged. */
23
+ unacked = [];
24
+ /** Buffer of events waiting to be sent once the window opens. */
25
+ buffer = [];
26
+ /** Whether the controller has been closed due to overflow. */
27
+ closed = false;
28
+ constructor(subscriptionId, maxInFlight, send, onOverflow) {
29
+ this.subscriptionId = subscriptionId;
30
+ this.maxInFlight = maxInFlight;
31
+ this.send = send;
32
+ this.onOverflow = onOverflow;
33
+ }
34
+ /**
35
+ * Accept an incoming {@link SubscriptionMessage} from the EventLog listener.
36
+ * If the window has room, send immediately. Otherwise buffer.
37
+ */
38
+ push(message) {
39
+ if (this.closed) {
40
+ return;
41
+ }
42
+ if (this.unacked.length < this.maxInFlight) {
43
+ this.sendMessage(message);
44
+ }
45
+ else {
46
+ this.buffer.push(message);
47
+ if (this.buffer.length > MAX_BUFFER_SIZE) {
48
+ log.warn(`FlowController: buffer overflow for subscription ${String(this.subscriptionId)}, ` +
49
+ `closing subscription (buffer=${this.buffer.length}, unacked=${this.unacked.length})`);
50
+ this.closed = true;
51
+ this.buffer = [];
52
+ this.unacked = [];
53
+ this.onOverflow();
54
+ }
55
+ }
56
+ }
57
+ /**
58
+ * Process an `rpc.ack` for this subscription. Acknowledges all events up
59
+ * to and including the given cursor, then flushes buffered events into the
60
+ * newly opened window slots.
61
+ */
62
+ ack(cursor) {
63
+ if (this.closed) {
64
+ return;
65
+ }
66
+ const idx = this.unacked.lastIndexOf(cursor);
67
+ if (idx === -1) {
68
+ // Unknown cursor — could be a stale or duplicate ack. Ignore silently.
69
+ log.debug(`FlowController: unknown cursor in ack for subscription ${String(this.subscriptionId)}: ${cursor}`);
70
+ return;
71
+ }
72
+ // Remove all entries up to and including the acked cursor.
73
+ this.unacked.splice(0, idx + 1);
74
+ // Flush buffered messages into the freed window slots.
75
+ while (this.buffer.length > 0 && this.unacked.length < this.maxInFlight) {
76
+ const buffered = this.buffer.shift();
77
+ this.sendMessage(buffered);
78
+ }
79
+ }
80
+ /**
81
+ * Returns the number of events currently in flight (sent but unacknowledged).
82
+ */
83
+ get inFlightCount() {
84
+ return this.unacked.length;
85
+ }
86
+ /**
87
+ * Returns the number of events currently buffered (waiting to be sent).
88
+ */
89
+ get bufferCount() {
90
+ return this.buffer.length;
91
+ }
92
+ /**
93
+ * Sends a single message over the wire and tracks its cursor.
94
+ */
95
+ sendMessage(message) {
96
+ const response = createJsonRpcSuccessResponse(this.subscriptionId, { subscription: message });
97
+ this.send(response);
98
+ this.unacked.push(message.cursor);
99
+ }
100
+ }
101
+ //# sourceMappingURL=flow-controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-controller.js","sourceRoot":"","sources":["../../../../src/connection/flow-controller.ts"],"names":[],"mappings":"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"}
@@ -1,18 +1,46 @@
1
- import type { Dwn } from "@enbox/dwn-sdk-js";
2
- import type { WebSocket } from "ws";
3
- import type { JsonRpcId, JsonRpcSubscription } from "../lib/json-rpc.js";
1
+ import type { ActivityLog } from '../admin/activity-log.js';
2
+ import type { AdminConnectionSnapshot } from '../admin/types.js';
3
+ import type { AdminStore } from '../admin/admin-store.js';
4
+ import type { DwnServerConfig } from '../config.js';
5
+ import type { MessageProcessedHook } from '../message-processed-hook.js';
6
+ import type { RateLimiter } from '../rate-limiter.js';
7
+ import type { RegistrationStore } from '../registration/registration-store.js';
8
+ import type { ServerWebSocket } from 'bun';
9
+ import type { WsData } from '../http-api.js';
10
+ import type { Dwn } from '@enbox/dwn-sdk-js';
11
+ import type { JsonRpcId, JsonRpcSubscription } from '@enbox/dwn-clients';
4
12
  /**
5
13
  * SocketConnection handles a WebSocket connection to a DWN using JSON RPC.
6
14
  * It also manages references to the long running RPC subscriptions for the connection.
15
+ *
16
+ * With Bun's native WebSocket, the message/close/error events are dispatched by the
17
+ * Bun.serve() websocket handlers in http-api.ts, which delegate to the public `message()`
18
+ * and `close()` methods on this class.
7
19
  */
8
20
  export declare class SocketConnection {
9
21
  private socket;
10
22
  private dwn;
11
- private onClose?;
23
+ private onCloseCallback?;
24
+ private maxInFlight;
25
+ private activityLog?;
26
+ private adminStore?;
27
+ private registrationStore?;
28
+ private serverConfig?;
29
+ private tenantRateLimiter?;
30
+ private messageProcessedHooks?;
31
+ /** Unique identifier for this connection (for admin introspection). */
32
+ readonly id: string;
33
+ /** Timestamp when the connection was established (for admin introspection). */
34
+ readonly connectedAt: number;
12
35
  private heartbeatInterval;
13
36
  private subscriptions;
37
+ private flowControllers;
14
38
  private isAlive;
15
- constructor(socket: WebSocket, dwn: Dwn, onClose?: () => void);
39
+ constructor(socket: ServerWebSocket<WsData>, dwn: Dwn, onCloseCallback?: () => void, maxInFlight?: number, activityLog?: ActivityLog, adminStore?: AdminStore, registrationStore?: RegistrationStore, serverConfig?: DwnServerConfig, tenantRateLimiter?: RateLimiter, messageProcessedHooks?: MessageProcessedHook[]);
40
+ /**
41
+ * Called when a pong is received (triggered by Bun's built-in ping/pong handling).
42
+ */
43
+ pong(): void;
16
44
  /**
17
45
  * Checks to see if the incoming `JsonRpcId` is already in use for a subscription.
18
46
  */
@@ -29,36 +57,44 @@ export declare class SocketConnection {
29
57
  */
30
58
  closeSubscription(id: JsonRpcId): Promise<void>;
31
59
  /**
32
- * Closes the existing connection and cleans up any listeners or subscriptions.
60
+ * Acknowledges subscription events up to the given cursor, advancing the
61
+ * flow-control window for the subscription.
33
62
  */
34
- close(): Promise<void>;
63
+ ackSubscription(id: JsonRpcId, cursor: string): void;
35
64
  /**
36
- * Pong messages are automatically sent in response to ping messages as required by
37
- * the websocket spec. So, no need to send explicit pongs.
65
+ * Closes the existing connection and cleans up any listeners or subscriptions.
38
66
  */
39
- private pong;
67
+ close(): Promise<void>;
40
68
  /**
41
69
  * Log the error and close the connection.
42
70
  */
43
- private error;
71
+ error(error: Error): Promise<void>;
44
72
  /**
45
73
  * Handles a `JSON RPC 2.0` encoded message.
74
+ * This is called by Bun's websocket message handler via http-api.ts.
46
75
  */
47
- private message;
76
+ message(dataBuffer: Buffer): Promise<void>;
48
77
  /**
49
- * Sends a JSON encoded Buffer through the Websocket.
78
+ * Returns the number of active subscriptions on this connection.
79
+ */
80
+ get subscriptionCount(): number;
81
+ /**
82
+ * Returns a serializable snapshot of this connection for the admin inspector.
83
+ */
84
+ toSnapshot(): AdminConnectionSnapshot;
85
+ /**
86
+ * Sends a JSON encoded string through the WebSocket.
50
87
  */
51
88
  private send;
52
89
  /**
53
- * Creates a subscription handler to send messages matching the subscription requested.
54
- *
55
- * Wraps the incoming `message` in a `JSON RPC Success Response` using the original subscription`JSON RPC Id` to send through the WebSocket.
90
+ * Creates a flow-controlled subscription handler that enforces the
91
+ * `maxInFlight` window. Returns a `SubscriptionListener` to be passed
92
+ * to the EventLog, and stores the `FlowController` for later `rpc.ack`
93
+ * processing.
56
94
  */
57
95
  private createSubscriptionHandler;
58
96
  /**
59
97
  * Builds a `RequestContext` object to use with the `JSON RPC API`.
60
- *
61
- * Adds a `subscriptionHandler` for `Subscribe` messages.
62
98
  */
63
99
  private buildRequestContext;
64
100
  }
@@ -1 +1 @@
1
- {"version":3,"file":"socket-connection.d.ts","sourceRoot":"","sources":["../../../../src/connection/socket-connection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAgC,MAAM,mBAAmB,CAAC;AAG3E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAKpC,OAAO,KAAK,EAAwB,SAAS,EAAmC,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAShI;;;GAGG;AACH,qBAAa,gBAAgB;IAMzB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,OAAO,CAAC;IAPlB,OAAO,CAAC,iBAAiB,CAAe;IACxC,OAAO,CAAC,aAAa,CAAkD;IACvE,OAAO,CAAC,OAAO,CAAU;gBAGf,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,GAAG,EACR,OAAO,CAAC,EAAE,MAAM,IAAI;IAsB9B;;OAEG;IACH,eAAe,CAAC,EAAE,EAAE,SAAS,GAAG,OAAO;IAIvC;;;OAGG;IACG,eAAe,CAAC,YAAY,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAWvE;;;;OAIG;IACG,iBAAiB,CAAC,EAAE,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAarD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB5B;;;OAGG;IACH,OAAO,CAAC,IAAI;IAIZ;;OAEG;YACW,KAAK;IAMnB;;OAEG;YACW,OAAO;IAmCrB;;OAEG;IACH,OAAO,CAAC,IAAI;IAIZ;;;;OAIG;IACH,OAAO,CAAC,yBAAyB;IAOjC;;;;OAIG;YACW,mBAAmB;CAuBlC"}
1
+ {"version":3,"file":"socket-connection.d.ts","sourceRoot":"","sources":["../../../../src/connection/socket-connection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAE/E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,KAAK,CAAC;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAE,GAAG,EAAuC,MAAM,mBAAmB,CAAC;AAClF,OAAO,KAAK,EAAwB,SAAS,EAAmC,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAchI;;;;;;;GAOG;AACH,qBAAa,gBAAgB;IAazB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,eAAe,CAAC;IACxB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,WAAW,CAAC;IACpB,OAAO,CAAC,UAAU,CAAC;IACnB,OAAO,CAAC,iBAAiB,CAAC;IAC1B,OAAO,CAAC,YAAY,CAAC;IACrB,OAAO,CAAC,iBAAiB,CAAC;IAC1B,OAAO,CAAC,qBAAqB,CAAC;IArBhC,uEAAuE;IACvE,SAAgB,EAAE,EAAE,MAAM,CAAY;IAEtC,+EAA+E;IAC/E,SAAgB,WAAW,EAAE,MAAM,CAAc;IAEjD,OAAO,CAAC,iBAAiB,CAAiC;IAC1D,OAAO,CAAC,aAAa,CAAkD;IACvE,OAAO,CAAC,eAAe,CAA6C;IACpE,OAAO,CAAC,OAAO,CAAU;gBAGf,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC,EAC/B,GAAG,EAAE,GAAG,EACR,eAAe,CAAC,EAAE,MAAM,IAAI,EAC5B,WAAW,GAAE,MAA8B,EAC3C,WAAW,CAAC,EAAE,WAAW,EACzB,UAAU,CAAC,EAAE,UAAU,EACvB,iBAAiB,CAAC,EAAE,iBAAiB,EACrC,YAAY,CAAC,EAAE,eAAe,EAC9B,iBAAiB,CAAC,EAAE,WAAW,EAC/B,qBAAqB,CAAC,EAAE,oBAAoB,EAAE;IAexD;;OAEG;IACH,IAAI,IAAI,IAAI;IAIZ;;OAEG;IACH,eAAe,CAAC,EAAE,EAAE,SAAS,GAAG,OAAO;IAIvC;;;OAGG;IACG,eAAe,CAAC,YAAY,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAWvE;;;;OAIG;IACG,iBAAiB,CAAC,EAAE,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAcrD;;;OAGG;IACH,eAAe,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAOpD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB5B;;OAEG;IACG,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAMxC;;;OAGG;IACG,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmChD;;OAEG;IACH,IAAI,iBAAiB,IAAI,MAAM,CAE9B;IAED;;OAEG;IACH,UAAU,IAAI,uBAAuB;IAiBrC;;OAEG;IACH,OAAO,CAAC,IAAI;IAIZ;;;;;OAKG;IACH,OAAO,CAAC,yBAAyB;IAsBjC;;OAEG;YACW,mBAAmB;CA4BlC"}
@@ -1,44 +1,68 @@
1
- import { DwnMethodName } from "@enbox/dwn-sdk-js";
2
1
  import log from 'loglevel';
2
+ import { DwnMethodName } from '@enbox/dwn-sdk-js';
3
+ import { jsonRpcRouter } from '../json-rpc-api.js';
4
+ import { requestCounter } from '../metrics.js';
3
5
  import { v4 as uuidv4 } from 'uuid';
4
- import { requestCounter } from "../metrics.js";
5
- import { jsonRpcRouter } from "../json-rpc-api.js";
6
- import { JsonRpcErrorCodes, createJsonRpcErrorResponse, createJsonRpcSuccessResponse } from "../lib/json-rpc.js";
7
- import { DwnServerError, DwnServerErrorCode } from "../dwn-error.js";
6
+ import { createJsonRpcErrorResponse, JsonRpcErrorCodes } from '@enbox/dwn-clients';
7
+ import { DEFAULT_MAX_IN_FLIGHT, FlowController } from './flow-controller.js';
8
+ import { DwnServerError, DwnServerErrorCode } from '../dwn-error.js';
8
9
  const HEARTBEAT_INTERVAL = 30_000;
9
10
  /**
10
11
  * SocketConnection handles a WebSocket connection to a DWN using JSON RPC.
11
12
  * It also manages references to the long running RPC subscriptions for the connection.
13
+ *
14
+ * With Bun's native WebSocket, the message/close/error events are dispatched by the
15
+ * Bun.serve() websocket handlers in http-api.ts, which delegate to the public `message()`
16
+ * and `close()` methods on this class.
12
17
  */
13
18
  export class SocketConnection {
14
19
  socket;
15
20
  dwn;
16
- onClose;
21
+ onCloseCallback;
22
+ maxInFlight;
23
+ activityLog;
24
+ adminStore;
25
+ registrationStore;
26
+ serverConfig;
27
+ tenantRateLimiter;
28
+ messageProcessedHooks;
29
+ /** Unique identifier for this connection (for admin introspection). */
30
+ id = uuidv4();
31
+ /** Timestamp when the connection was established (for admin introspection). */
32
+ connectedAt = Date.now();
17
33
  heartbeatInterval;
18
34
  subscriptions = new Map();
35
+ flowControllers = new Map();
19
36
  isAlive;
20
- constructor(socket, dwn, onClose) {
37
+ constructor(socket, dwn, onCloseCallback, maxInFlight = DEFAULT_MAX_IN_FLIGHT, activityLog, adminStore, registrationStore, serverConfig, tenantRateLimiter, messageProcessedHooks) {
21
38
  this.socket = socket;
22
39
  this.dwn = dwn;
23
- this.onClose = onClose;
24
- socket.on('message', this.message.bind(this));
25
- socket.on('close', this.close.bind(this));
26
- socket.on('error', this.error.bind(this));
27
- socket.on('pong', this.pong.bind(this));
28
- // Sometimes connections between client <-> server can get borked in such a way that
29
- // leaves both unaware of the borkage. ping messages can be used as a means to verify
30
- // that the remote endpoint is still responsive. Server will ping each socket every 30s
31
- // if a pong hasn't received from a socket by the next ping, the server will terminate
32
- // the socket connection
40
+ this.onCloseCallback = onCloseCallback;
41
+ this.maxInFlight = maxInFlight;
42
+ this.activityLog = activityLog;
43
+ this.adminStore = adminStore;
44
+ this.registrationStore = registrationStore;
45
+ this.serverConfig = serverConfig;
46
+ this.tenantRateLimiter = tenantRateLimiter;
47
+ this.messageProcessedHooks = messageProcessedHooks;
48
+ // Bun handles ping/pong automatically at the protocol level, but we still
49
+ // want an application-level heartbeat to detect dead connections.
33
50
  this.isAlive = true;
34
51
  this.heartbeatInterval = setInterval(() => {
35
52
  if (this.isAlive === false) {
36
53
  this.close();
54
+ return;
37
55
  }
38
56
  this.isAlive = false;
39
57
  this.socket.ping();
40
58
  }, HEARTBEAT_INTERVAL);
41
59
  }
60
+ /**
61
+ * Called when a pong is received (triggered by Bun's built-in ping/pong handling).
62
+ */
63
+ pong() {
64
+ this.isAlive = true;
65
+ }
42
66
  /**
43
67
  * Checks to see if the incoming `JsonRpcId` is already in use for a subscription.
44
68
  */
@@ -67,14 +91,23 @@ export class SocketConnection {
67
91
  const connection = this.subscriptions.get(id);
68
92
  await connection.close();
69
93
  this.subscriptions.delete(id);
94
+ this.flowControllers.delete(id);
95
+ }
96
+ /**
97
+ * Acknowledges subscription events up to the given cursor, advancing the
98
+ * flow-control window for the subscription.
99
+ */
100
+ ackSubscription(id, cursor) {
101
+ const fc = this.flowControllers.get(id);
102
+ if (fc) {
103
+ fc.ack(cursor);
104
+ }
70
105
  }
71
106
  /**
72
107
  * Closes the existing connection and cleans up any listeners or subscriptions.
73
108
  */
74
109
  async close() {
75
110
  clearInterval(this.heartbeatInterval);
76
- // clean up all socket event listeners
77
- this.socket.removeAllListeners();
78
111
  const closePromises = [];
79
112
  for (const [id, subscription] of this.subscriptions) {
80
113
  closePromises.push(subscription.close());
@@ -82,30 +115,26 @@ export class SocketConnection {
82
115
  }
83
116
  // close all of the associated subscriptions
84
117
  await Promise.all(closePromises);
118
+ // clear all flow controllers
119
+ this.flowControllers.clear();
85
120
  // close the socket.
86
121
  this.socket.close();
87
122
  // if there was a close handler passed call it after the connection has been closed
88
- if (this.onClose !== undefined) {
89
- this.onClose();
123
+ if (this.onCloseCallback !== undefined) {
124
+ this.onCloseCallback();
90
125
  }
91
126
  }
92
- /**
93
- * Pong messages are automatically sent in response to ping messages as required by
94
- * the websocket spec. So, no need to send explicit pongs.
95
- */
96
- pong() {
97
- this.isAlive = true;
98
- }
99
127
  /**
100
128
  * Log the error and close the connection.
101
129
  */
102
130
  async error(error) {
103
131
  log.error(`SocketConnection error, terminating connection`, error);
104
- this.socket.terminate();
132
+ this.socket.close();
105
133
  await this.close();
106
134
  }
107
135
  /**
108
136
  * Handles a `JSON RPC 2.0` encoded message.
137
+ * This is called by Bun's websocket message handler via http-api.ts.
109
138
  */
110
139
  async message(dataBuffer) {
111
140
  const requestData = dataBuffer.toString();
@@ -120,7 +149,6 @@ export class SocketConnection {
120
149
  const errorResponse = createJsonRpcErrorResponse(uuidv4(), JsonRpcErrorCodes.BadRequest, error.message);
121
150
  return this.send(errorResponse);
122
151
  }
123
- ;
124
152
  const requestContext = await this.buildRequestContext(jsonRequest);
125
153
  const { jsonRpcResponse } = await jsonRpcRouter.handle(jsonRequest, requestContext);
126
154
  if (jsonRpcResponse.error) {
@@ -135,26 +163,55 @@ export class SocketConnection {
135
163
  this.send(jsonRpcResponse);
136
164
  }
137
165
  /**
138
- * Sends a JSON encoded Buffer through the Websocket.
166
+ * Returns the number of active subscriptions on this connection.
167
+ */
168
+ get subscriptionCount() {
169
+ return this.subscriptions.size;
170
+ }
171
+ /**
172
+ * Returns a serializable snapshot of this connection for the admin inspector.
173
+ */
174
+ toSnapshot() {
175
+ const subscriptions = Array.from(this.flowControllers.entries()).map(([id, fc]) => ({
176
+ id: id,
177
+ inflight: fc.inFlightCount,
178
+ buffered: fc.bufferCount,
179
+ }));
180
+ return {
181
+ id: this.id,
182
+ connectedAt: new Date(this.connectedAt).toISOString(),
183
+ subscriptionCount: this.subscriptions.size,
184
+ subscriptions,
185
+ };
186
+ }
187
+ /**
188
+ * Sends a JSON encoded string through the WebSocket.
139
189
  */
140
190
  send(response) {
141
191
  this.socket.send(JSON.stringify(response));
142
192
  }
143
193
  /**
144
- * Creates a subscription handler to send messages matching the subscription requested.
145
- *
146
- * Wraps the incoming `message` in a `JSON RPC Success Response` using the original subscription`JSON RPC Id` to send through the WebSocket.
194
+ * Creates a flow-controlled subscription handler that enforces the
195
+ * `maxInFlight` window. Returns a `SubscriptionListener` to be passed
196
+ * to the EventLog, and stores the `FlowController` for later `rpc.ack`
197
+ * processing.
147
198
  */
148
199
  createSubscriptionHandler(id) {
149
- return (event) => {
150
- const response = createJsonRpcSuccessResponse(id, { event });
200
+ const fc = new FlowController(id, this.maxInFlight, (response) => {
151
201
  this.send(response);
202
+ }, () => {
203
+ // overflow: close the subscription to prevent OOM
204
+ this.closeSubscription(id).catch((err) => {
205
+ log.error(`FlowController: error closing subscription ${String(id)} on overflow`, err);
206
+ });
207
+ });
208
+ this.flowControllers.set(id, fc);
209
+ return (message) => {
210
+ fc.push(message);
152
211
  };
153
212
  }
154
213
  /**
155
214
  * Builds a `RequestContext` object to use with the `JSON RPC API`.
156
- *
157
- * Adds a `subscriptionHandler` for `Subscribe` messages.
158
215
  */
159
216
  async buildRequestContext(request) {
160
217
  const { params, method, subscription } = request;
@@ -162,15 +219,20 @@ export class SocketConnection {
162
219
  transport: 'ws',
163
220
  dwn: this.dwn,
164
221
  socketConnection: this,
222
+ activityLog: this.activityLog,
223
+ adminStore: this.adminStore,
224
+ registrationStore: this.registrationStore,
225
+ config: this.serverConfig,
226
+ tenantRateLimiter: this.tenantRateLimiter,
227
+ messageProcessedHooks: this.messageProcessedHooks,
165
228
  };
166
229
  // methods that expect a long-running subscription begin with `rpc.subscribe.`
167
230
  if (method.startsWith('rpc.subscribe.') && subscription) {
168
231
  const { message } = params;
169
232
  if (message?.descriptor.method === DwnMethodName.Subscribe) {
170
- const handlerFunc = this.createSubscriptionHandler(subscription.id);
171
233
  requestContext.subscriptionRequest = {
172
234
  id: subscription.id,
173
- subscriptionHandler: (message) => handlerFunc(message),
235
+ subscriptionHandler: this.createSubscriptionHandler(subscription.id),
174
236
  };
175
237
  }
176
238
  }
@@ -1 +1 @@
1
- {"version":3,"file":"socket-connection.js","sourceRoot":"","sources":["../../../../src/connection/socket-connection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"socket-connection.js","sourceRoot":"","sources":["../../../../src/connection/socket-connection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import type { DwnServerConfig } from './config.js';
2
+ import type { DidResolver } from '@enbox/dids';
3
+ import type { Dwn, GenericMessage } from '@enbox/dwn-sdk-js';
4
+ import type { MessageProcessedContext, MessageProcessedHook } from './message-processed-hook.js';
5
+ /**
6
+ * Server-side service that handles two complementary features:
7
+ *
8
+ * 1. **Endpoint forwarding** — When a RecordsWrite/RecordsDelete is processed,
9
+ * forwards the original signed message to the tenant's *other* DWN service
10
+ * endpoints (peer replication without the agent mediating).
11
+ *
12
+ * 2. **Record delivery** — When a RecordsWrite/RecordsDelete is processed at a
13
+ * protocol path with `$delivery`, proactively delivers to participants' DWN
14
+ * endpoints determined from protocol `$actions` role records.
15
+ *
16
+ * Both operations are fire-and-forget: failures are logged but never propagate
17
+ * to the original request handler.
18
+ */
19
+ export declare class DeliveryService implements MessageProcessedHook {
20
+ #private;
21
+ private constructor();
22
+ /**
23
+ * Factory method following the established server service pattern.
24
+ */
25
+ static create(dwn: Dwn, didResolver: DidResolver, config: DwnServerConfig): DeliveryService;
26
+ /**
27
+ * Hook entry point invoked by the hooks runner after `dwn.processMessage()`.
28
+ */
29
+ onMessageProcessed(context: MessageProcessedContext): void;
30
+ /**
31
+ * Evaluates whether forwarding or delivery should occur for a successfully
32
+ * processed message, and dispatches outbound requests asynchronously.
33
+ *
34
+ * This method does NOT await the outbound requests — it returns immediately
35
+ * after scheduling them.
36
+ *
37
+ * @param tenant - The tenant DID that owns the DWN.
38
+ * @param message - The original signed DWN message.
39
+ * @param statusCode - The reply status code from `dwn.processMessage()`.
40
+ */
41
+ dispatchIfNeeded(tenant: string, message: GenericMessage, statusCode: number): void;
42
+ }
43
+ //# sourceMappingURL=delivery-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delivery-service.d.ts","sourceRoot":"","sources":["../../../src/delivery-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAe,WAAW,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAE,GAAG,EAAE,cAAc,EAAuC,MAAM,mBAAmB,CAAC;AAClG,OAAO,KAAK,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAkCjG;;;;;;;;;;;;;GAaG;AACH,qBAAa,eAAgB,YAAW,oBAAoB;;IAwB1D,OAAO;IAOP;;OAEG;WACW,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,GAAG,eAAe;IAQlG;;OAEG;IACI,kBAAkB,CAAC,OAAO,EAAE,uBAAuB,GAAG,IAAI;IAQjE;;;;;;;;;;OAUG;IACI,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;CAgnB3F"}