@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
package/src/storage.ts CHANGED
@@ -1,43 +1,47 @@
1
+ import type { Dialect } from '@enbox/dwn-sql-store';
1
2
  import type { DidResolver } from '@enbox/dids';
3
+ import type { DwnServerConfig } from './config.js';
2
4
  import type {
3
5
  DataStore,
4
6
  DwnConfig,
5
7
  EventLog,
6
- EventStream,
7
8
  MessageStore,
8
9
  ResumableTaskStore,
10
+ StateIndex,
9
11
  TenantGate,
10
12
  } from '@enbox/dwn-sdk-js';
11
- import type { Dialect } from '@enbox/dwn-sql-store';
12
- import type { DwnServerConfig } from './config.js';
13
13
 
14
14
  import * as fs from 'fs';
15
15
  import Cursor from 'pg-cursor';
16
- import Database from 'better-sqlite3';
17
- import pg from 'pg';
18
16
  import { createPool as MySQLCreatePool } from 'mysql2';
17
+ import pg from 'pg';
18
+
19
+ import { Kysely } from 'kysely';
20
+
21
+ import { createBunSqliteDatabase } from '@enbox/dwn-sql-store';
19
22
  import { PluginLoader } from './plugin-loader.js';
20
23
 
21
24
  import {
22
25
  DataStoreLevel,
23
- EventLogLevel,
24
26
  MessageStoreLevel,
25
27
  ResumableTaskStoreLevel,
28
+ StateIndexLevel,
26
29
  } from '@enbox/dwn-sdk-js';
27
30
  import {
28
31
  DataStoreSql,
29
- EventLogSql,
30
32
  MessageStoreSql,
31
33
  MysqlDialect,
32
34
  PostgresDialect,
33
35
  ResumableTaskStoreSql,
36
+ runDwnStoreMigrations,
34
37
  SqliteDialect,
38
+ StateIndexSql,
35
39
  } from '@enbox/dwn-sql-store';
36
40
 
37
41
  export enum StoreType {
38
42
  DataStore,
39
43
  MessageStore,
40
- EventLog,
44
+ StateIndex,
41
45
  ResumableTaskStore,
42
46
  }
43
47
 
@@ -48,23 +52,113 @@ export enum BackendTypes {
48
52
  POSTGRES = 'postgres',
49
53
  }
50
54
 
51
- export type DwnStore = DataStore | EventLog | MessageStore | ResumableTaskStore;
55
+ export type DwnStore = DataStore | StateIndex | MessageStore | ResumableTaskStore;
56
+
57
+ /**
58
+ * Cache of shared PostgreSQL dialects keyed by connection URL. When multiple
59
+ * DWN stores share the same Postgres URL, they reuse a single dialect (and
60
+ * thus a single `pg.Pool`) instead of each creating their own. This reduces
61
+ * connection count from 4 × pool_max to 1 × pool_max per DWN process.
62
+ */
63
+ const sharedDialectCache: Map<string, Dialect> = new Map();
64
+
65
+ /**
66
+ * Returns a (potentially cached) dialect for the given Postgres connection URL.
67
+ * Non-Postgres URLs always return a fresh dialect (no caching).
68
+ */
69
+ function getOrCreateDialect(connectionUrl: URL, config: DwnServerConfig): Dialect {
70
+ const protocol = connectionUrl.protocol.slice(0, -1);
71
+
72
+ if (protocol !== BackendTypes.POSTGRES) {
73
+ return getDialectFromUrl(connectionUrl);
74
+ }
75
+
76
+ const key = connectionUrl.toString();
77
+ const cached = sharedDialectCache.get(key);
78
+ if (cached !== undefined) {
79
+ return cached;
80
+ }
81
+
82
+ // Create a single pg.Pool instance with configurable sizing.
83
+ const pool = new pg.Pool({
84
+ connectionString : connectionUrl.toString(),
85
+ min : config.pgPoolMin,
86
+ max : config.pgPoolMax,
87
+ idleTimeoutMillis : config.pgPoolIdleTimeout,
88
+ });
89
+
90
+ const dialect = new PostgresDialect({
91
+ pool : async (): Promise<pg.Pool> => pool,
92
+ cursor : Cursor,
93
+ });
94
+
95
+ sharedDialectCache.set(key, dialect);
96
+ return dialect;
97
+ }
52
98
 
53
99
  export async function getDwnConfig(
54
- config : DwnServerConfig,
100
+ config : DwnServerConfig,
55
101
  options : {
56
102
  didResolver? : DidResolver,
57
- tenantGate? : TenantGate,
58
- eventStream? : EventStream,
103
+ tenantGate? : TenantGate,
104
+ eventLog? : EventLog,
59
105
  }
60
106
  ): Promise<DwnConfig> {
61
- const { tenantGate, eventStream, didResolver } = options;
62
- const dataStore: DataStore = await getStore(config.dataStore, StoreType.DataStore);
63
- const eventLog: EventLog = await getStore(config.eventLog, StoreType.EventLog);
64
- const messageStore: MessageStore = await getStore(config.messageStore, StoreType.MessageStore);
65
- const resumableTaskStore: ResumableTaskStore = await getStore(config.resumableTaskStore, StoreType.ResumableTaskStore);
107
+ const { tenantGate, eventLog, didResolver } = options;
108
+
109
+ // Run SQL schema migrations before creating stores. Uses the data store
110
+ // connection to determine the dialect — all SQL stores typically share the
111
+ // same database. Non-SQL backends (level://) are skipped.
112
+ await runSqlMigrationsIfNeeded(config);
66
113
 
67
- return { didResolver, eventStream, eventLog, dataStore, messageStore, resumableTaskStore, tenantGate };
114
+ const dataStore: DataStore = await getStore(config, config.dataStore, StoreType.DataStore);
115
+ const stateIndex: StateIndex = await getStore(config, config.stateIndex, StoreType.StateIndex);
116
+ const messageStore: MessageStore = await getStore(config, config.messageStore, StoreType.MessageStore);
117
+ const resumableTaskStore: ResumableTaskStore = await getStore(config, config.resumableTaskStore, StoreType.ResumableTaskStore);
118
+
119
+ return { didResolver, eventLog, stateIndex, dataStore, messageStore, resumableTaskStore, tenantGate };
120
+ }
121
+
122
+ /**
123
+ * Runs DWN SQL schema migrations if the data store is configured with a SQL
124
+ * backend. Creates a temporary Kysely instance, runs all pending migrations,
125
+ * then destroys it. The subsequent store `open()` calls will reuse the shared
126
+ * dialect/pool and find the schema already in place.
127
+ */
128
+ async function runSqlMigrationsIfNeeded(config: DwnServerConfig): Promise<void> {
129
+ // Skip if the data store config is a file path (plugin) or non-SQL backend
130
+ if (isFilePath(config.dataStore)) {
131
+ return;
132
+ }
133
+
134
+ let storeUrl: URL;
135
+ try {
136
+ storeUrl = new URL(config.dataStore);
137
+ } catch {
138
+ return; // Not a valid URL — skip
139
+ }
140
+
141
+ const protocol = storeUrl.protocol.slice(0, -1);
142
+ const sqlBackends: string[] = [BackendTypes.SQLITE, BackendTypes.MYSQL, BackendTypes.POSTGRES];
143
+ if (!sqlBackends.includes(protocol)) {
144
+ return;
145
+ }
146
+
147
+ const dialect = getOrCreateDialect(storeUrl, config);
148
+ const db = new Kysely<Record<string, unknown>>({ dialect });
149
+ try {
150
+ const applied = await runDwnStoreMigrations(db, dialect);
151
+ if (applied.length > 0) {
152
+ console.log(`DWN migrations applied: ${applied.join(', ')}`);
153
+ }
154
+ } finally {
155
+ // Don't destroy the Kysely instance if using a shared Postgres pool —
156
+ // the pool is cached in sharedDialectCache and will be reused by stores.
157
+ // Only destroy for non-cached dialects (SQLite, MySQL).
158
+ if (protocol !== BackendTypes.POSTGRES) {
159
+ await db.destroy();
160
+ }
161
+ }
68
162
  }
69
163
 
70
164
  function getLevelStore(
@@ -78,12 +172,12 @@ function getLevelStore(
78
172
  });
79
173
  case StoreType.MessageStore:
80
174
  return new MessageStoreLevel({
81
- blockstoreLocation: storeURI.host + storeURI.pathname + '/MESSAGESTORE',
82
- indexLocation: storeURI.host + storeURI.pathname + '/INDEX',
175
+ blockstoreLocation : storeURI.host + storeURI.pathname + '/MESSAGESTORE',
176
+ indexLocation : storeURI.host + storeURI.pathname + '/INDEX',
83
177
  });
84
- case StoreType.EventLog:
85
- return new EventLogLevel({
86
- location: storeURI.host + storeURI.pathname + '/EVENTLOG',
178
+ case StoreType.StateIndex:
179
+ return new StateIndexLevel({
180
+ location: storeURI.host + storeURI.pathname + '/STATEINDEX',
87
181
  });
88
182
  case StoreType.ResumableTaskStore:
89
183
  return new ResumableTaskStoreLevel({
@@ -95,18 +189,19 @@ function getLevelStore(
95
189
  }
96
190
 
97
191
  function getSqlStore(
192
+ config: DwnServerConfig,
98
193
  connectionUrl: URL,
99
194
  storeType: StoreType,
100
195
  ): DwnStore {
101
- const dialect = getDialectFromUrl(connectionUrl);
196
+ const dialect = getOrCreateDialect(connectionUrl, config);
102
197
 
103
198
  switch (storeType) {
104
199
  case StoreType.DataStore:
105
200
  return new DataStoreSql(dialect);
106
201
  case StoreType.MessageStore:
107
202
  return new MessageStoreSql(dialect);
108
- case StoreType.EventLog:
109
- return new EventLogSql(dialect);
203
+ case StoreType.StateIndex:
204
+ return new StateIndexSql(dialect);
110
205
  case StoreType.ResumableTaskStore:
111
206
  return new ResumableTaskStoreSql(dialect);
112
207
  default:
@@ -122,16 +217,16 @@ function isFilePath(configString: string): boolean {
122
217
  return filePathPrefixes.some(prefix => configString.startsWith(prefix));
123
218
  }
124
219
 
125
- async function getStore(storeString: string, storeType: StoreType.DataStore): Promise<DataStore>;
126
- async function getStore(storeString: string, storeType: StoreType.EventLog): Promise<EventLog>;
127
- async function getStore(storeString: string, storeType: StoreType.MessageStore): Promise<MessageStore>;
128
- async function getStore(storeString: string, storeType: StoreType.ResumableTaskStore): Promise<ResumableTaskStore>;
129
- async function getStore(storeConfigString: string, storeType: StoreType): Promise<DwnStore> {
220
+ async function getStore(config: DwnServerConfig, storeString: string, storeType: StoreType.DataStore): Promise<DataStore>;
221
+ async function getStore(config: DwnServerConfig, storeString: string, storeType: StoreType.StateIndex): Promise<StateIndex>;
222
+ async function getStore(config: DwnServerConfig, storeString: string, storeType: StoreType.MessageStore): Promise<MessageStore>;
223
+ async function getStore(config: DwnServerConfig, storeString: string, storeType: StoreType.ResumableTaskStore): Promise<ResumableTaskStore>;
224
+ async function getStore(config: DwnServerConfig, storeConfigString: string, storeType: StoreType): Promise<DwnStore> {
130
225
  if (isFilePath(storeConfigString)) {
131
226
  return await loadStoreFromFilePath(storeConfigString, storeType);
132
227
  }
133
228
  // else treat the `storeConfigString` as a connection string
134
-
229
+
135
230
  const storeURI = new URL(storeConfigString);
136
231
 
137
232
  switch (storeURI.protocol.slice(0, -1)) {
@@ -141,7 +236,7 @@ async function getStore(storeConfigString: string, storeType: StoreType): Promis
141
236
  case BackendTypes.SQLITE:
142
237
  case BackendTypes.MYSQL:
143
238
  case BackendTypes.POSTGRES:
144
- return getSqlStore(storeURI, storeType);
239
+ return getSqlStore(config, storeURI, storeType);
145
240
 
146
241
  default:
147
242
  throw invalidStorageSchemeMessage(storeURI.protocol);
@@ -158,8 +253,8 @@ async function loadStoreFromFilePath(
158
253
  switch (storeType) {
159
254
  case StoreType.DataStore:
160
255
  return await PluginLoader.loadPlugin<DataStore>(filePath);
161
- case StoreType.EventLog:
162
- return await PluginLoader.loadPlugin<EventLog>(filePath);
256
+ case StoreType.StateIndex:
257
+ return await PluginLoader.loadPlugin<StateIndex>(filePath);
163
258
  case StoreType.MessageStore:
164
259
  return await PluginLoader.loadPlugin<MessageStore>(filePath);
165
260
  case StoreType.ResumableTaskStore:
@@ -171,7 +266,7 @@ async function loadStoreFromFilePath(
171
266
 
172
267
  export function getDialectFromUrl(connectionUrl: URL): Dialect {
173
268
  switch (connectionUrl.protocol.slice(0, -1)) {
174
- case BackendTypes.SQLITE:
269
+ case BackendTypes.SQLITE: {
175
270
  const path = connectionUrl.host + connectionUrl.pathname;
176
271
  console.log('SQL-lite relative path:', path ? path : undefined); // NOTE, using ? for lose equality comparison
177
272
 
@@ -184,16 +279,17 @@ export function getDialectFromUrl(connectionUrl: URL): Dialect {
184
279
  const dbPath = path || ':memory:';
185
280
 
186
281
  return new SqliteDialect({
187
- database: async () => new Database(dbPath),
282
+ database: async () => createBunSqliteDatabase(dbPath),
188
283
  });
284
+ }
189
285
  case BackendTypes.MYSQL:
190
286
  return new MysqlDialect({
191
287
  pool: async () => MySQLCreatePool(connectionUrl.toString()),
192
288
  });
193
289
  case BackendTypes.POSTGRES:
194
290
  return new PostgresDialect({
195
- pool: async () => new pg.Pool({ connectionString: connectionUrl.toString() }),
196
- cursor: Cursor,
291
+ pool : async () => new pg.Pool({ connectionString: connectionUrl.toString() }),
292
+ cursor : Cursor,
197
293
  });
198
294
  }
199
295
  }
@@ -205,7 +301,7 @@ function invalidStorageSchemeMessage(protocol: string): string {
205
301
  }
206
302
  return (
207
303
  'Unknown storage protocol ' +
208
- protocol.slice(0, 1) +
304
+ protocol.slice(0, -1) +
209
305
  '! Please use one of: ' +
210
306
  schemes.join(', ') +
211
307
  '. For details, see README'
@@ -39,9 +39,9 @@ export class SqlTtlCache {
39
39
  // 512 chars to accommodate potentially large `state` in Web5 Connect flow
40
40
  .addColumn('key', 'varchar(512)', (column) => column.primaryKey())
41
41
  .addColumn('value', 'text', (column) => column.notNull())
42
- .addColumn('expiry', 'integer', (column) => column.notNull())
42
+ .addColumn('expiry', 'bigint', (column) => column.notNull())
43
43
  .execute();
44
-
44
+
45
45
  await this.db.schema
46
46
  .createIndex('index_expiry')
47
47
  // .ifNotExists() // intentionally kept commented out code to show that it is not supported by all dialects (ie. MySQL)
@@ -97,12 +97,19 @@ export class SqlTtlCache {
97
97
  const entry = result[0];
98
98
 
99
99
  // if the entry is expired, don't return it and delete it
100
- if (Date.now() >= entry.expiry) {
100
+ const expiry = typeof entry.expiry === 'string' ? parseInt(entry.expiry, 10) : entry.expiry;
101
+ if (Date.now() >= expiry) {
101
102
  this.delete(key); // no need to await
102
103
  return undefined;
103
104
  }
104
105
 
105
- return JSON.parse(entry.value);
106
+ try {
107
+ return JSON.parse(entry.value);
108
+ } catch {
109
+ // Corrupt entry — remove it and return undefined.
110
+ this.delete(key); // no need to await
111
+ return undefined;
112
+ }
106
113
  }
107
114
 
108
115
  /**
@@ -129,7 +136,7 @@ export class SqlTtlCache {
129
136
  interface CacheEntry {
130
137
  key: string;
131
138
  value: string;
132
- expiry: number;
139
+ expiry: number | string; // bigint is returned as string by PostgreSQL driver
133
140
  }
134
141
 
135
142
  interface CacheDatabase {
@@ -1,16 +1,17 @@
1
- import { getDialectFromUrl } from "../storage.js";
2
1
  import { CryptoUtils } from '@enbox/crypto';
3
- import { SqlTtlCache } from "./sql-ttl-cache.js";
2
+
3
+ import { getDialectFromUrl } from '../storage.js';
4
+ import { SqlTtlCache } from './sql-ttl-cache.js';
4
5
 
5
6
  /**
6
7
  * The Web5 Connect Request object.
7
8
  */
8
- export type Web5ConnectRequest = any; // TODO: define type in common repo for reuse (https://github.com/TBD54566975/dwn-server/issues/138)
9
+ export type Web5ConnectRequest = any; // TODO: define type in common repo for reuse (https://github.com/enboxorg/enbox/issues/138)
9
10
 
10
11
  /**
11
12
  * The Web5 Connect Response object, which is also an OIDC ID token
12
13
  */
13
- export type Web5ConnectResponse = any; // TODO: define type in common repo for reuse (https://github.com/TBD54566975/dwn-server/issues/138)
14
+ export type Web5ConnectResponse = any; // TODO: define type in common repo for reuse (https://github.com/enboxorg/enbox/issues/138)
14
15
 
15
16
  /**
16
17
  * The result of the setWeb5ConnectRequest() method.
@@ -25,7 +26,7 @@ export type SetWeb5ConnectRequestResult = {
25
26
  * The time in seconds that the Request URI is valid for.
26
27
  */
27
28
  expires_in: number;
28
- }
29
+ };
29
30
 
30
31
  /**
31
32
  * The Web5 Connect Server is responsible for handling the Web5 Connect flow.
@@ -69,13 +70,13 @@ export class Web5ConnectServer {
69
70
  // Generate a request URI
70
71
  const requestId = CryptoUtils.randomUuid();
71
72
  const request_uri = `${this.baseUrl}/connect/authorize/${requestId}.jwt`;
72
-
73
+
73
74
  // Store the Request Object.
74
75
  this.cache.insert(`request:${requestId}`, request, Web5ConnectServer.ttlInSeconds);
75
-
76
+
76
77
  return {
77
78
  request_uri,
78
- expires_in : Web5ConnectServer.ttlInSeconds,
79
+ expires_in: Web5ConnectServer.ttlInSeconds,
79
80
  };
80
81
  }
81
82
 
package/src/ws-api.ts CHANGED
@@ -1,45 +1,58 @@
1
+ import type { Dwn } from '@enbox/dwn-sdk-js';
2
+ import type { ServerWebSocket } from 'bun';
1
3
 
2
- import type {
3
- Dwn,
4
- } from '@enbox/dwn-sdk-js';
5
-
6
- import type { Server } from 'http';
7
-
8
- import { WebSocketServer } from 'ws';
9
-
4
+ import type { ActivityLog } from './admin/activity-log.js';
5
+ import type { AdminStore } from './admin/admin-store.js';
10
6
  import type { ConnectionManager } from './connection/connection-manager.js';
7
+ import type { DwnServerConfig } from './config.js';
8
+ import type { MessageProcessedHook } from './message-processed-hook.js';
9
+ import type { RateLimiter } from './rate-limiter.js';
10
+ import type { RegistrationStore } from './registration/registration-store.js';
11
+ import type { HttpApi, WsData } from './http-api.js';
12
+
11
13
  import { InMemoryConnectionManager } from './connection/connection-manager.js';
12
14
 
13
15
  export class WsApi {
14
- #wsServer: WebSocketServer;
15
16
  dwn: Dwn;
16
- #connectionManager: ConnectionManager
17
-
18
- constructor(server: Server, dwn: Dwn, connectionManager?: ConnectionManager) {
17
+ #connectionManager: ConnectionManager;
18
+
19
+ constructor(
20
+ httpApi: HttpApi, dwn: Dwn, connectionManager?: ConnectionManager,
21
+ maxInFlight?: number, activityLog?: ActivityLog,
22
+ options?: {
23
+ adminStore? : AdminStore;
24
+ registrationStore? : RegistrationStore;
25
+ config? : DwnServerConfig;
26
+ tenantRateLimiter? : RateLimiter;
27
+ messageProcessedHooks? : MessageProcessedHook[];
28
+ },
29
+ ) {
19
30
  this.dwn = dwn;
20
- this.#connectionManager = connectionManager || new InMemoryConnectionManager(dwn);
21
- this.#wsServer = new WebSocketServer({ server });
31
+ this.#connectionManager = connectionManager ||
32
+ new InMemoryConnectionManager(
33
+ dwn, new Map(), maxInFlight, activityLog,
34
+ options?.adminStore, options?.registrationStore, options?.config, options?.tenantRateLimiter,
35
+ options?.messageProcessedHooks,
36
+ );
37
+
38
+ // Wire up the WebSocket open event from Bun.serve() to the connection manager.
39
+ httpApi.onWebSocketConnection = (ws: ServerWebSocket<WsData>): void => {
40
+ this.#connectionManager.connect(ws);
41
+ };
22
42
  }
23
43
 
24
- get server(): WebSocketServer {
25
- return this.#wsServer;
44
+ start(): void {
45
+ // No additional setup needed — Bun.serve() handles WebSocket lifecycle.
26
46
  }
27
47
 
28
48
  /**
29
- * Handler for starting a WebSocket.
30
- * Sets listeners for `connection`, `close` events.
49
+ * Returns the connection manager. Used by the admin API for connection introspection.
31
50
  */
32
- #setupWebSocket(): void {
33
- this.#wsServer.on('connection', (socket, request) => this.#connectionManager.connect(socket, request));
34
- this.#wsServer.on('close', () => this.#connectionManager.closeAll());
35
- }
36
-
37
- start(): void {
38
- this.#setupWebSocket();
51
+ get connectionManager(): ConnectionManager {
52
+ return this.#connectionManager;
39
53
  }
40
54
 
41
55
  async close(): Promise<void> {
42
- this.#wsServer.close();
43
56
  await this.#connectionManager.closeAll();
44
57
  }
45
58
  }