@enbox/dwn-server 0.0.3 → 0.0.5

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 (295) hide show
  1. package/LICENSE +3 -2
  2. package/README.md +112 -212
  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 +122 -3
  36. package/dist/esm/src/config.d.ts.map +1 -1
  37. package/dist/esm/src/config.js +151 -5
  38. package/dist/esm/src/config.js.map +1 -1
  39. package/dist/esm/src/connection/connection-manager.d.ts +24 -1
  40. package/dist/esm/src/connection/connection-manager.d.ts.map +1 -1
  41. package/dist/esm/src/connection/connection-manager.js +33 -2
  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 +39 -4
  48. package/dist/esm/src/connection/socket-connection.d.ts.map +1 -1
  49. package/dist/esm/src/connection/socket-connection.js +80 -9
  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 +8 -0
  60. package/dist/esm/src/dwn-server.d.ts.map +1 -1
  61. package/dist/esm/src/dwn-server.js +198 -12
  62. package/dist/esm/src/dwn-server.js.map +1 -1
  63. package/dist/esm/src/http-api.d.ts +19 -2
  64. package/dist/esm/src/http-api.d.ts.map +1 -1
  65. package/dist/esm/src/http-api.js +219 -19
  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 +106 -4
  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 +22 -4
  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 +13 -1
  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/provider-auth-plugin.d.ts +46 -0
  123. package/dist/esm/src/registration/provider-auth-plugin.d.ts.map +1 -0
  124. package/dist/esm/src/registration/provider-auth-plugin.js +29 -0
  125. package/dist/esm/src/registration/provider-auth-plugin.js.map +1 -0
  126. package/dist/esm/src/registration/registration-manager.d.ts +27 -4
  127. package/dist/esm/src/registration/registration-manager.d.ts.map +1 -1
  128. package/dist/esm/src/registration/registration-manager.js +77 -6
  129. package/dist/esm/src/registration/registration-manager.js.map +1 -1
  130. package/dist/esm/src/registration/registration-store.d.ts +83 -3
  131. package/dist/esm/src/registration/registration-store.d.ts.map +1 -1
  132. package/dist/esm/src/registration/registration-store.js +248 -11
  133. package/dist/esm/src/registration/registration-store.js.map +1 -1
  134. package/dist/esm/src/storage.d.ts +4 -4
  135. package/dist/esm/src/storage.d.ts.map +1 -1
  136. package/dist/esm/src/storage.js +100 -20
  137. package/dist/esm/src/storage.js.map +1 -1
  138. package/dist/esm/src/web5-connect/sql-ttl-cache.d.ts.map +1 -1
  139. package/dist/esm/src/web5-connect/sql-ttl-cache.js +8 -1
  140. package/dist/esm/src/web5-connect/sql-ttl-cache.js.map +1 -1
  141. package/dist/esm/src/ws-api.d.ts +17 -1
  142. package/dist/esm/src/ws-api.d.ts.map +1 -1
  143. package/dist/esm/src/ws-api.js +9 -2
  144. package/dist/esm/src/ws-api.js.map +1 -1
  145. package/package.json +18 -16
  146. package/src/admin/activity-log.ts +100 -0
  147. package/src/admin/admin-api.ts +1308 -0
  148. package/src/admin/admin-auth.ts +56 -0
  149. package/src/admin/admin-store.ts +515 -0
  150. package/src/admin/audit-log.ts +327 -0
  151. package/src/admin/index.ts +34 -0
  152. package/src/admin/types.ts +352 -0
  153. package/src/admin/webhook-manager.ts +245 -0
  154. package/src/config.ts +177 -5
  155. package/src/connection/connection-manager.ts +50 -6
  156. package/src/connection/flow-controller.ts +117 -0
  157. package/src/connection/socket-connection.ts +103 -21
  158. package/src/delivery-service.ts +740 -0
  159. package/src/dwn-error.ts +9 -0
  160. package/src/dwn-server.ts +242 -14
  161. package/src/http-api.ts +271 -30
  162. package/src/index.ts +13 -2
  163. package/src/json-rpc-api.ts +2 -1
  164. package/src/json-rpc-handlers/dwn/process-message.ts +140 -5
  165. package/src/json-rpc-handlers/subscription/ack.ts +63 -0
  166. package/src/json-rpc-handlers/subscription/close.ts +2 -6
  167. package/src/json-rpc-handlers/subscription/index.ts +1 -0
  168. package/src/lib/json-rpc-router.ts +22 -6
  169. package/src/lib/sql-utils.ts +7 -0
  170. package/src/main.ts +0 -8
  171. package/src/message-processed-hook.ts +33 -0
  172. package/src/metrics.ts +50 -1
  173. package/src/plugins/event-log-nats.ts +466 -0
  174. package/src/rate-limiter.ts +143 -0
  175. package/src/registration/jwt-provider-auth-plugin.ts +119 -0
  176. package/src/registration/open-auth-handler.ts +263 -0
  177. package/src/registration/proof-of-work-manager.ts +1 -1
  178. package/src/registration/provider-auth-plugin.ts +84 -0
  179. package/src/registration/registration-manager.ts +108 -12
  180. package/src/registration/registration-store.ts +326 -17
  181. package/src/storage.ts +121 -27
  182. package/src/web5-connect/sql-ttl-cache.ts +7 -1
  183. package/src/ws-api.ts +30 -2
  184. package/dist/esm/src/json-rpc-socket.d.ts +0 -39
  185. package/dist/esm/src/json-rpc-socket.d.ts.map +0 -1
  186. package/dist/esm/src/json-rpc-socket.js +0 -125
  187. package/dist/esm/src/json-rpc-socket.js.map +0 -1
  188. package/dist/esm/src/lib/json-rpc.d.ts +0 -54
  189. package/dist/esm/src/lib/json-rpc.d.ts.map +0 -1
  190. package/dist/esm/src/lib/json-rpc.js +0 -60
  191. package/dist/esm/src/lib/json-rpc.js.map +0 -1
  192. package/dist/esm/src/registration/proof-of-work-types.d.ts +0 -8
  193. package/dist/esm/src/registration/proof-of-work-types.d.ts.map +0 -1
  194. package/dist/esm/src/registration/proof-of-work-types.js +0 -2
  195. package/dist/esm/src/registration/proof-of-work-types.js.map +0 -1
  196. package/dist/esm/src/registration/registration-types.d.ts +0 -18
  197. package/dist/esm/src/registration/registration-types.d.ts.map +0 -1
  198. package/dist/esm/src/registration/registration-types.js +0 -2
  199. package/dist/esm/src/registration/registration-types.js.map +0 -1
  200. package/dist/esm/tests/common-scenario-validator.d.ts +0 -11
  201. package/dist/esm/tests/common-scenario-validator.d.ts.map +0 -1
  202. package/dist/esm/tests/common-scenario-validator.js +0 -113
  203. package/dist/esm/tests/common-scenario-validator.js.map +0 -1
  204. package/dist/esm/tests/connection/connection-manager.spec.d.ts +0 -2
  205. package/dist/esm/tests/connection/connection-manager.spec.d.ts.map +0 -1
  206. package/dist/esm/tests/connection/connection-manager.spec.js +0 -49
  207. package/dist/esm/tests/connection/connection-manager.spec.js.map +0 -1
  208. package/dist/esm/tests/connection/socket-connection.spec.d.ts +0 -2
  209. package/dist/esm/tests/connection/socket-connection.spec.d.ts.map +0 -1
  210. package/dist/esm/tests/connection/socket-connection.spec.js +0 -147
  211. package/dist/esm/tests/connection/socket-connection.spec.js.map +0 -1
  212. package/dist/esm/tests/cors/http-api.browser.d.ts +0 -2
  213. package/dist/esm/tests/cors/http-api.browser.d.ts.map +0 -1
  214. package/dist/esm/tests/cors/http-api.browser.js +0 -60
  215. package/dist/esm/tests/cors/http-api.browser.js.map +0 -1
  216. package/dist/esm/tests/cors/ping.browser.d.ts +0 -2
  217. package/dist/esm/tests/cors/ping.browser.d.ts.map +0 -1
  218. package/dist/esm/tests/cors/ping.browser.js +0 -7
  219. package/dist/esm/tests/cors/ping.browser.js.map +0 -1
  220. package/dist/esm/tests/dwn-process-message.spec.d.ts +0 -2
  221. package/dist/esm/tests/dwn-process-message.spec.d.ts.map +0 -1
  222. package/dist/esm/tests/dwn-process-message.spec.js +0 -172
  223. package/dist/esm/tests/dwn-process-message.spec.js.map +0 -1
  224. package/dist/esm/tests/dwn-server.spec.d.ts +0 -2
  225. package/dist/esm/tests/dwn-server.spec.d.ts.map +0 -1
  226. package/dist/esm/tests/dwn-server.spec.js +0 -48
  227. package/dist/esm/tests/dwn-server.spec.js.map +0 -1
  228. package/dist/esm/tests/http-api.spec.d.ts +0 -2
  229. package/dist/esm/tests/http-api.spec.d.ts.map +0 -1
  230. package/dist/esm/tests/http-api.spec.js +0 -782
  231. package/dist/esm/tests/http-api.spec.js.map +0 -1
  232. package/dist/esm/tests/json-rpc-socket.spec.d.ts +0 -2
  233. package/dist/esm/tests/json-rpc-socket.spec.d.ts.map +0 -1
  234. package/dist/esm/tests/json-rpc-socket.spec.js +0 -227
  235. package/dist/esm/tests/json-rpc-socket.spec.js.map +0 -1
  236. package/dist/esm/tests/plugins/data-store-sqlite.d.ts +0 -17
  237. package/dist/esm/tests/plugins/data-store-sqlite.d.ts.map +0 -1
  238. package/dist/esm/tests/plugins/data-store-sqlite.js +0 -23
  239. package/dist/esm/tests/plugins/data-store-sqlite.js.map +0 -1
  240. package/dist/esm/tests/plugins/event-log-sqlite.d.ts +0 -17
  241. package/dist/esm/tests/plugins/event-log-sqlite.d.ts.map +0 -1
  242. package/dist/esm/tests/plugins/event-log-sqlite.js +0 -23
  243. package/dist/esm/tests/plugins/event-log-sqlite.js.map +0 -1
  244. package/dist/esm/tests/plugins/event-stream-in-memory.d.ts +0 -17
  245. package/dist/esm/tests/plugins/event-stream-in-memory.d.ts.map +0 -1
  246. package/dist/esm/tests/plugins/event-stream-in-memory.js +0 -21
  247. package/dist/esm/tests/plugins/event-stream-in-memory.js.map +0 -1
  248. package/dist/esm/tests/plugins/message-store-sqlite.d.ts +0 -17
  249. package/dist/esm/tests/plugins/message-store-sqlite.d.ts.map +0 -1
  250. package/dist/esm/tests/plugins/message-store-sqlite.js +0 -23
  251. package/dist/esm/tests/plugins/message-store-sqlite.js.map +0 -1
  252. package/dist/esm/tests/plugins/resumable-task-store-sqlite.d.ts +0 -17
  253. package/dist/esm/tests/plugins/resumable-task-store-sqlite.d.ts.map +0 -1
  254. package/dist/esm/tests/plugins/resumable-task-store-sqlite.js +0 -23
  255. package/dist/esm/tests/plugins/resumable-task-store-sqlite.js.map +0 -1
  256. package/dist/esm/tests/process-handler.spec.d.ts +0 -2
  257. package/dist/esm/tests/process-handler.spec.d.ts.map +0 -1
  258. package/dist/esm/tests/process-handler.spec.js +0 -60
  259. package/dist/esm/tests/process-handler.spec.js.map +0 -1
  260. package/dist/esm/tests/registration/proof-of-work-manager.spec.d.ts +0 -2
  261. package/dist/esm/tests/registration/proof-of-work-manager.spec.d.ts.map +0 -1
  262. package/dist/esm/tests/registration/proof-of-work-manager.spec.js +0 -156
  263. package/dist/esm/tests/registration/proof-of-work-manager.spec.js.map +0 -1
  264. package/dist/esm/tests/rpc-subscribe-close.spec.d.ts +0 -2
  265. package/dist/esm/tests/rpc-subscribe-close.spec.d.ts.map +0 -1
  266. package/dist/esm/tests/rpc-subscribe-close.spec.js +0 -81
  267. package/dist/esm/tests/rpc-subscribe-close.spec.js.map +0 -1
  268. package/dist/esm/tests/scenarios/dynamic-plugin-loading.spec.d.ts +0 -2
  269. package/dist/esm/tests/scenarios/dynamic-plugin-loading.spec.d.ts.map +0 -1
  270. package/dist/esm/tests/scenarios/dynamic-plugin-loading.spec.js +0 -74
  271. package/dist/esm/tests/scenarios/dynamic-plugin-loading.spec.js.map +0 -1
  272. package/dist/esm/tests/scenarios/registration.spec.d.ts +0 -2
  273. package/dist/esm/tests/scenarios/registration.spec.d.ts.map +0 -1
  274. package/dist/esm/tests/scenarios/registration.spec.js +0 -511
  275. package/dist/esm/tests/scenarios/registration.spec.js.map +0 -1
  276. package/dist/esm/tests/scenarios/web5-connect.spec.d.ts +0 -2
  277. package/dist/esm/tests/scenarios/web5-connect.spec.d.ts.map +0 -1
  278. package/dist/esm/tests/scenarios/web5-connect.spec.js +0 -141
  279. package/dist/esm/tests/scenarios/web5-connect.spec.js.map +0 -1
  280. package/dist/esm/tests/test-dwn.d.ts +0 -7
  281. package/dist/esm/tests/test-dwn.d.ts.map +0 -1
  282. package/dist/esm/tests/test-dwn.js +0 -28
  283. package/dist/esm/tests/test-dwn.js.map +0 -1
  284. package/dist/esm/tests/utils.d.ts +0 -43
  285. package/dist/esm/tests/utils.d.ts.map +0 -1
  286. package/dist/esm/tests/utils.js +0 -107
  287. package/dist/esm/tests/utils.js.map +0 -1
  288. package/dist/esm/tests/ws-api.spec.d.ts +0 -2
  289. package/dist/esm/tests/ws-api.spec.d.ts.map +0 -1
  290. package/dist/esm/tests/ws-api.spec.js +0 -332
  291. package/dist/esm/tests/ws-api.spec.js.map +0 -1
  292. package/src/json-rpc-socket.ts +0 -156
  293. package/src/lib/json-rpc.ts +0 -126
  294. package/src/registration/proof-of-work-types.ts +0 -7
  295. package/src/registration/registration-types.ts +0 -18
package/LICENSE CHANGED
@@ -1,3 +1,4 @@
1
+
1
2
  Apache License
2
3
  Version 2.0, January 2004
3
4
  http://www.apache.org/licenses/
@@ -186,7 +187,7 @@
186
187
  same "printed page" as the copyright notice for easier
187
188
  identification within third-party archives.
188
189
 
189
- Copyright [yyyy] [name of copyright owner]
190
+ Copyright 2025 Liran Cohen
190
191
 
191
192
  Licensed under the Apache License, Version 2.0 (the "License");
192
193
  you may not use this file except in compliance with the License.
@@ -198,4 +199,4 @@
198
199
  distributed under the License is distributed on an "AS IS" BASIS,
199
200
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
201
  See the License for the specific language governing permissions and
201
- limitations under the License.
202
+ limitations under the License.
package/README.md CHANGED
@@ -1,118 +1,92 @@
1
1
  # DWN Server
2
2
 
3
- Exposes a multi-tenanted DWN (aka Decentralized Web Node) through a JSON-RPC API over `http:` and `ws:`
3
+ > **Research Preview** Enbox is under active development. APIs may change without notice.
4
+
5
+ [![Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/LiranCohen/02d15f39a46173a612a8862ec6d7cfcf/raw/dwn-server.json)](https://github.com/enboxorg/enbox/actions/workflows/ci.yml)
6
+
7
+ A multi-tenant Decentralized Web Node exposed via JSON-RPC over HTTP and WebSocket, powered by `Bun.serve()`.
4
8
 
5
9
  - [Supported DBs](#supported-dbs)
6
10
  - [Installation](#installation)
7
- - [Package usage](#package-usage)
8
- - [Running The Server](#running-the-server)
11
+ - [Running the Server](#running-the-server)
9
12
  - [JSON-RPC API](#json-rpc-api)
10
- - [Available Methods](#available-methods)
11
- - [`dwn.processMessage`](#dwnprocessmessage)
12
- - [Params](#params)
13
- - [Example Request Message](#example-request-message)
14
- - [Example Success Response](#example-success-response)
15
- - [Example Error Response](#example-error-response)
16
- - [Transporting large amounts of data](#transporting-large-amounts-of-data)
17
- - [Receiving large amounts of data](#receiving-large-amounts-of-data)
18
- - [npm scripts](#npm-scripts)
19
13
  - [Configuration](#configuration)
20
- - [Storage Options](#storage-options)
14
+ - [Hosting Your Own DWN Server](#hosting-your-own-dwn-server)
15
+ - [Registration Requirements](#registration-requirements)
21
16
 
22
17
  ## Supported DBs
23
18
 
24
- - LevelDB :heavy_check_mark:
25
- - SQLite :heavy_check_mark:
26
- - MySQL :heavy_check_mark:
27
- - PostgreSQL :heavy_check_mark:
28
-
29
- See more in [Storage Options](#storage-options)
30
-
31
- ## Running online environment
19
+ - LevelDB
20
+ - SQLite
21
+ - MySQL
22
+ - PostgreSQL
32
23
 
33
- Interested in contributing instantly? You can make your updates directly without cloning in the running CodeSandbox environment.
34
-
35
- [![Button to click and edit the code in CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/github/enboxorg/enbox/main)
24
+ See [Storage Options](#storage-options) for details.
36
25
 
37
26
  ## Installation
38
27
 
39
28
  ```bash
40
- npm install @enbox/dwn-server
29
+ bun add @enbox/dwn-server
41
30
  ```
42
31
 
43
- ## Package usage
32
+ ## Package Usage
44
33
 
45
34
  ```typescript
46
35
  import { DwnServer } from '@enbox/dwn-server';
47
36
 
48
37
  const server = new DwnServer();
49
-
50
38
  server.start();
51
39
  ```
52
40
 
53
- ## Running the server
41
+ ## Running the Server
54
42
 
55
- ### Running via docker
43
+ ### Via Docker
56
44
 
57
- `docker run -p 3000:3000 -v myvolume:/dwn-server/data ghcr.io/enboxorg/dwn-server:main`
58
-
59
- This can run on services like AWS, GCP, VPS, home server (with ngrok or cloudflare), fly.io, render.com etc.
60
- Ideally the volume is persistent so that data is kept (or has to be synced back from another DWN instance).
45
+ ```bash
46
+ docker run -p 3000:3000 -v myvolume:/dwn-server/data ghcr.io/enboxorg/dwn-server:main
47
+ ```
61
48
 
62
- ### Running a specific version
49
+ This can run on AWS, GCP, VPS, home server (with ngrok or Cloudflare tunnel), Fly.io, Render, etc. Use a persistent volume so data is kept (or synced back from another DWN instance).
63
50
 
64
- Running the command above will run the latest version at the time the image is pulled. If you need to run a specific version (and in many cases this is recommended) [you can see the list published images here](https://github.com/enboxorg/enbox/pkgs/container/dwn-server/versions)
51
+ To run a specific version, [see published images](https://github.com/enboxorg/enbox/pkgs/container/dwn-server/versions):
65
52
 
66
- To run a specific image:
67
- `docker pull ghcr.io/enboxorg/dwn-server@sha256:870e0f0f12016e6607060a81ea31458443f7439522fab2688d7a6706ab366c58`
53
+ ```bash
54
+ docker pull ghcr.io/enboxorg/dwn-server@sha256:<hash>
55
+ ```
68
56
 
69
- ### Running Locally for Development
57
+ ### Locally for Development
70
58
 
71
59
  ```bash
72
60
  git clone https://github.com/enboxorg/enbox.git
73
- cd enbox/packages/dwn-server
74
- npm install
75
- npm run server
61
+ cd enbox
62
+ bun install
63
+ bun run --filter @enbox/dwn-server build
64
+ bun run --filter @enbox/dwn-server server
76
65
  ```
77
66
 
78
- ### Building a docker image locally
67
+ ### Building a Docker Image Locally
79
68
 
80
- A docker image is continuously published from this repository, but if you want to build it locally run:
81
- `docker build -t dwn-server .`
69
+ ```bash
70
+ docker build -t dwn-server .
71
+ ```
82
72
 
83
73
  ## JSON-RPC API
84
74
 
85
- [JSON-RPC](https://www.jsonrpc.org/specification) is a lightweight remote procedure call (RPC) protocol that uses JSON as a data format for exchanging information between a client and a server over a network. JSON-RPC is language-independent and transport-agnostic which makes it usable in a variety of contexts (e.g. browser, server-side)
86
-
87
- With JSON-RPC, a client sends a request message to a server over a network, and the server responds with a response message.
75
+ [JSON-RPC](https://www.jsonrpc.org/specification) is a lightweight RPC protocol using JSON, language-independent and transport-agnostic.
88
76
 
89
- The request message consists of:
90
-
91
- - a method name (`method`)
92
- - a set of parameters (`params`)
93
- - an identifier (`id`).
94
-
95
- The response message contains:
96
-
97
- - the same identifier that was sent with the request message (`id`)
98
- - the result of the method invocation (`result`)
99
- - an error message if the method invocation failed (`error`)
100
-
101
- ### Available Methods
102
-
103
- #### `dwn.processMessage`
77
+ ### `dwn.processMessage`
104
78
 
105
79
  Used to send DWeb Messages to the server.
106
80
 
107
- ##### Params
81
+ #### Params
108
82
 
109
- | Property | Required (Y/N) | Description |
110
- | ------------- | -------------- | ------------------------------------------------------------------------- |
111
- | `target` | Y | The DID that the message is intended for |
112
- | `message` | Y | The DWeb Message |
113
- | `encodedData` | N | Data associated to the message (e.g. data associated to a `RecordsWrite`) |
83
+ | Property | Required | Description |
84
+ | ------------- | -------- | ------------------------------------------------------------------------- |
85
+ | `target` | Y | The DID that the message is intended for |
86
+ | `message` | Y | The DWeb Message |
87
+ | `encodedData` | N | Data associated to the message (e.g. data associated to a `RecordsWrite`) |
114
88
 
115
- ##### Example Request Message
89
+ #### Example Request
116
90
 
117
91
  ```json
118
92
  {
@@ -131,15 +105,7 @@ Used to send DWeb Messages to the server.
131
105
  "dateModified": "2023-04-30T22:49:37.713976Z",
132
106
  "dataFormat": "application/json"
133
107
  },
134
- "authorization": {
135
- "payload": "eyJyZWNvcmRJZCI6ImJhZnlyZWlkdGl4Nmdoam1zYmc3ZWl0ZXhzbXd6dmp4YzdhZWxhZ3NxYXN5Ym1xbDd6cm1zMzRqdTZpIiwiZGVzY3JpcHRvckNpZCI6ImJhZnlyZWlheTVwNWZ1bzJhc2hqZXRvbzR1M3p1b282dW02cGlzNHl5NnUzaHE1emxsdmZhN2ZubXY0In0",
136
- "signatures": [
137
- {
138
- "protected": "eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDprZXk6ejZNa3UxaDRMZGtoWFczSG5uQktBTnhnVWFRMTYyY3ZXbVJ1emNiZDJZZThWc3RaI2RpZDprZXk6ejZNa3UxaDRMZGtoWFczSG5uQktBTnhnVWFRMTYyY3ZXbVJ1emNiZDJZZThWc3RaI3o2TWt1MWg0TGRraFhXM0hubkJLQU54Z1VhUTE2MmN2V21SdXpjYmQyWWU4VnN0WiJ9",
139
- "signature": "cy_RtWjjVK2mmKkI_35qiv54_1Pp_f7SjAx0z75PBL4th-fgfjuLZmF-V3czCWwFYMMnN0W4zl3LJ2jEf_t9DQ"
140
- }
141
- ]
142
- }
108
+ "authorization": { "..." : "..." }
143
109
  },
144
110
  "target": "did:key:z6Mku1h4LdkhXW3HnnBKANxgUaQ162cvWmRuzcbd2Ye8VstZ",
145
111
  "encodedData": "ub3-FwUsSs4GgZWqt5eXSH41RKlwCx41y3dgio9Di74"
@@ -147,7 +113,7 @@ Used to send DWeb Messages to the server.
147
113
  }
148
114
  ```
149
115
 
150
- ##### Example Success Response
116
+ #### Example Success Response
151
117
 
152
118
  ```json
153
119
  {
@@ -155,16 +121,13 @@ Used to send DWeb Messages to the server.
155
121
  "id": "18eb421f-4750-4e31-a062-412b71139546",
156
122
  "result": {
157
123
  "reply": {
158
- "status": {
159
- "code": 202,
160
- "detail": "Accepted"
161
- }
124
+ "status": { "code": 202, "detail": "Accepted" }
162
125
  }
163
126
  }
164
127
  }
165
128
  ```
166
129
 
167
- ##### Example Error Response
130
+ #### Example Error Response
168
131
 
169
132
  ```json
170
133
  {
@@ -177,166 +140,92 @@ Used to send DWeb Messages to the server.
177
140
  }
178
141
  ```
179
142
 
180
- ##### Transporting large amounts of data
181
-
182
- `RecordsWrite` data can be of any size. If needed, large amounts of data can be streamed to the server over http by:
183
-
184
- - including the JSON-RPC request message in a `dwn-request` request header
185
- - setting the `content-type` request header to `application/octet-stream`
186
- - sending binary data in the request body.
187
-
188
- > :bulb: Examples can be found in the [`examples`](./examples) directory.
143
+ #### Transporting Large Data
189
144
 
190
- ##### Receiving large amounts of data
145
+ `RecordsWrite` data can be of any size. Large data can be streamed over HTTP by:
191
146
 
192
- `RecordsWrite` data can be of any size. `RecordsWrite` messages returned as the result of a `RecordsQuery` will include `encodedData` _if_ the `RecordsWrite` data is under `9.77KB`. Data larger than this will need to be fetched using `RecordsRead` which can be done over http. The response to a `RecordsRead` includes:
147
+ - Including the JSON-RPC request message in a `dwn-request` request header
148
+ - Setting `content-type` to `application/octet-stream`
149
+ - Sending binary data in the request body
193
150
 
194
- - The JSON-RPC response message in a `dwn-response` header
195
- - The associated data as binary in the response body.
151
+ #### Receiving Large Data
196
152
 
197
- Examples can be found in the `examples` directory.
153
+ `RecordsWrite` messages returned from a `RecordsQuery` include `encodedData` only if the data is under ~9.77KB. Larger data must be fetched via `RecordsRead` over HTTP, which returns:
198
154
 
199
- > :bulb: **TODO**: Add examples in `examples` directory
155
+ - The JSON-RPC response in a `dwn-response` header
156
+ - The binary data in the response body
200
157
 
201
- ## Hosting your own DWN-server
202
-
203
- By default, when you call `Enbox.connect()` there will be some bootstrap DWN nodes included which allow people to reach you via your DID.
158
+ ## Configuration
204
159
 
205
- You may want to run a DWN server just for you, or as a public service for you and your friends and family.
206
- DWNs can be as simple as a docker image or a node process running somewhere.
160
+ All configuration is via environment variables:
207
161
 
208
- DWN-servers can run anywhere you can run node.js or docker. http and websocket need to be available to the DWN server.
209
- See below for some suggestions.
162
+ | Env Var | Description | Default |
163
+ | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ---------------------- |
164
+ | `DS_PORT` | Port the server listens on | `3000` |
165
+ | `DS_MAX_RECORD_DATA_SIZE` | Maximum size for `RecordsWrite` data (`b`, `kb`, `mb`, `gb`) | `1gb` |
166
+ | `DS_WEBSOCKET_SERVER` | Enable WebSocket listener: `on` / `off` | `on` |
167
+ | `DWN_BASE_URL` | Base external URL of this DWN | `http://localhost` |
168
+ | `DWN_STORAGE` | Default storage URL. See [Storage Options](#storage-options) | `level://data` |
169
+ | `DWN_STORAGE_MESSAGES` | Message store URL (overrides `DWN_STORAGE`) | value of `DWN_STORAGE` |
170
+ | `DWN_STORAGE_DATA` | Data store URL (overrides `DWN_STORAGE`) | value of `DWN_STORAGE` |
171
+ | `DWN_STORAGE_RESUMABLE_TASKS` | Resumable task store URL | value of `DWN_STORAGE` |
172
+ | `DWN_STORAGE_STATE_INDEX` | State index store URL | value of `DWN_STORAGE` |
173
+ | `DWN_EVENT_STREAM_PLUGIN_PATH` | Path to custom Event Stream plugin | unset |
174
+ | `DWN_REGISTRATION_STORE_URL` | URL for registered DID storage. Unset = open for all | unset |
175
+ | `DWN_REGISTRATION_PROOF_OF_WORK_ENABLED` | Require proof-of-work for registration | `false` |
176
+ | `DWN_REGISTRATION_PROOF_OF_WORK_SEED` | Seed for challenge nonce (cluster consistency) | unset |
177
+ | `DWN_REGISTRATION_PROOF_OF_WORK_INITIAL_MAX_HASH` | Initial max hash (64 char hex). More leading zeros = higher difficulty | `000000FF...` |
178
+ | `DWN_TERMS_OF_SERVICE_FILE_PATH` | Path to terms of service file. Unset = no ToS requirement | unset |
179
+ | `DWN_TTL_CACHE_URL` | TTL cache URL (SQL databases only) | `sqlite://` |
210
180
 
211
- ### Running on render.com
181
+ ### Storage Options
212
182
 
213
- You can run an instance on the render.com service:
183
+ | Database | Example | Notes |
184
+ | ---------- | ----------------------------------------------------- | -------------------------------------------------------------------------------- |
185
+ | LevelDB | `level://data` | Two slashes for relative paths, three for absolute |
186
+ | SQLite | `sqlite://dwn.db` | Two slashes for relative paths, three for absolute |
187
+ | MySQL | `mysql://user:pass@host/db?debug=true&timezone=-0700` | [Options](https://github.com/mysqljs/mysql#connection-options) |
188
+ | PostgreSQL | `postgres:///dwn` | Also supports [standard env vars](https://node-postgres.com/features/connecting) |
214
189
 
215
- - Create a render.com account
216
- - Fork this repo
217
- - Upgrade your render.com account to a paid account
218
- - Create a new "Web service" type application
219
- - Choose the forked repo to run (or you can point to the main repo)
220
- - Choose the "starter" size instance
221
- - Create a 1GB (or larger) disk, and mount it on /dwn-server/data
190
+ ### Plugins
222
191
 
223
- ### Running with ngrok
192
+ Custom implementations of `DataStore`, `MessageStore`, `ResumableDataStore`, `StateIndex`, or `EventStream` can be loaded by pointing the corresponding env var to the absolute path of a `.js` file. The file must default-export a class with a no-arg constructor.
224
193
 
225
- You can run a DWN-server on your local machine or home server and expose it to the internet using ngrok.
194
+ ## Hosting Your Own DWN Server
226
195
 
227
- First, install [ngrok](https://ngrok.com/download)
196
+ By default, `Enbox.connect()` uses bootstrap DWN nodes. You can run your own for yourself or your community. DWNs can run anywhere you can run Bun or Docker — HTTP and WebSocket must be reachable.
228
197
 
229
- Then run:
198
+ ### With ngrok
230
199
 
231
200
  ```bash
232
201
  docker run -p 3000:3000 -v myvolume:/dwn-server/data ghcr.io/enboxorg/dwn-server:main
233
202
 
234
- ## in another terminal:
203
+ # In another terminal:
235
204
  ngrok http 3000
236
205
  ```
237
206
 
238
- Note the resulting publicly addressable https url for your DWN instance.
239
-
240
- ### Running with cloudflared
241
-
242
- Cloudflare has a tunnel service that you can use to expose your DWN server to the internet, if you run it on a server at home.
243
- With [cloudflared](https://github.com/cloudflare/cloudflared) installed, run the following commands:
207
+ ### With Cloudflare Tunnel
244
208
 
245
209
  ```bash
246
- git clone https://github.com/enboxorg/enbox.git
247
- cd enbox/packages/dwn-server
248
- npm install
249
- npm run server
250
-
251
- ## in another terminal:
252
-
210
+ # Start the server, then:
253
211
  cloudflared tunnel --url http://localhost:3000
254
212
  ```
255
213
 
256
- ### Running on GCP
257
-
258
- ... check back soon ...
259
- (enterprising people I am sure can work it out)
260
-
261
- ## `npm` scripts
262
-
263
- | Script | Description |
264
- | ---------------------- | ------------------------------------------------------------------ |
265
- | `npm run build:esm` | compiles typescript into ESM JS |
266
- | `npm run build:cjs` | compiles typescript into CommonJS |
267
- | `npm run build` | compiles typescript into ESM JS & CommonJS |
268
- | `npm run clean` | deletes compiled JS |
269
- | `npm run lint` | runs linter |
270
- | `npm run lint:fix` | runs linter and fixes auto-fixable problems |
271
- | `npm run test` | runs tests |
272
- | `npm run server` | starts server |
273
- | `npm run prepare` | prepares husky for pre-commit hooks (auto-runs with `npm install`) |
274
-
275
- ## Configuration
276
-
277
- Configuration can be set using environment variables
278
-
279
- | Env Var | Description | Default |
280
- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ---------------------- |
281
- | `DS_PORT` | Port that the server listens on | `3000` |
282
- | `DS_MAX_RECORD_DATA_SIZE` | Maximum size for `RecordsWrite` data. use `b`, `kb`, `mb`, `gb` for value | `1gb` |
283
- | `DS_WEBSOCKET_SERVER` | Whether to enable listening over `ws:`. values: `on`,`off` | `on` |
284
- | `DWN_BASE_URL` | Base external URL of this DWN. Used to construct URL paths such as the `Request URI` for the Enbox Connect flow. | `http://localhost` |
285
- | `DWN_EVENT_STREAM_PLUGIN_PATH` | Path to DWN Event Stream plugin to use. Default single-node implementation will be used if left empty. | unset |
286
- | `DWN_REGISTRATION_STORE_URL` | URL to use for storage of registered DIDs. Leave unset to if DWN does not require registration (ie. open for all) | unset |
287
- | `DWN_REGISTRATION_PROOF_OF_WORK_SEED` | Optional seed to generate the challenge nonce from, this allows all DWN instances in a cluster to generate the same challenge. | unset |
288
- | `DWN_REGISTRATION_PROOF_OF_WORK_ENABLED` | Require new users to complete a proof-of-work challenge | `false` |
289
- | `DWN_REGISTRATION_PROOF_OF_WORK_INITIAL_MAX_HASH` | Initial maximum allowed hash in 64 char HEX string. The more leading zeros (smaller number) the higher the difficulty. | `000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF` |
290
- | `DWN_STORAGE` | URL to use for storage by default. See [Storage Options](#storage-options) for details | `level://data` |
291
- | `DWN_STORAGE_MESSAGES` | Connection URL or file path to custom plugin to use for the message store. | value of `DWN_STORAGE` |
292
- | `DWN_STORAGE_DATA` | Connection URL or file path to custom plugin to use for the data store. | value of `DWN_STORAGE` |
293
- | `DWN_STORAGE_RESUMABLE_TASKS` | Connection URL or file path to custom plugin to use for the resumable task store. | value of `DWN_STORAGE` |
294
- | `DWN_STORAGE_EVENTS` | Connection URL or file path to custom plugin to use for the event store. | value of `DWN_STORAGE` |
295
- | `DWN_TERMS_OF_SERVICE_FILE_PATH` | Required terms of service agreement if set. Value is path to the terms of service file. | unset |
296
- | `DWN_TTL_CACHE_URL` | URL of the TTL cache used by the DWN. Currently only supports SQL databases. | `sqlite://` |
297
-
298
- ### Storage Options
214
+ ### On Render.com
299
215
 
300
- Several built storage options are supported, and may be configured with the `DWN_STORAGE_*` environment variables:
301
-
302
- | Database | Example | Notes |
303
- | ---------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
304
- | LevelDB | `level://data` | use three slashes for absolute paths, two for relative. Example shown uses directory `data` in the current working directory |
305
- | Sqlite | `sqlite://dwn.db` | use three slashes for absolute paths, two for relative. Example shown creates a file `dwn.db` in the current working directory |
306
- | MySQL | `mysql://user:pass@host/db?debug=true&timezone=-0700` | [all URL options documented here](https://github.com/mysqljs/mysql#connection-options) |
307
- | PostgreSQL | `postgres:///dwn` | any options other than the URL scheme (`postgres://`) may also be specified via [standard environment variables](https://node-postgres.com/features/connecting#environment-variables) |
308
-
309
- ### Plugins
310
-
311
- In some scenarios, you may want to provide a custom implementation of a pluggable module for the DWN Server. The following interfaces defined in `dwn-sdk-js` package are supported:
312
-
313
- - `DataStore`
314
- - `MessageStore`
315
- - `ResumableDataStore`
316
- - `EventLog`
317
- - `EventStream`
318
-
319
- To load your custom plugin, specify the absolute path to the `.js` file of your custom implementation using the corresponding environment variable. For instance, use `DWN_STORAGE_DATA` for a custom DWN Data Store.
320
-
321
- Refer to the `tests/plugins/*.ts` files for examples of plugin implementations. In summary, you need to:
322
-
323
- - Implement the corresponding interface from the `dwn-sdk-js` package. For example, implement the `DataStore` interface for a DWN Data Store.
324
- - Ensure that the built `.js` file that will be referenced by the DWN Server config environment variable contains a class that:
325
- 1. Is a default export. This is how DWN Server locates the correct class for instantiation.
326
- 1. Has a public constructor that does not take any arguments. This is how DWN Server instantiates the plugin.
216
+ Fork this repo, create a "Web service" on Render, point it at the fork, choose the starter size, and mount a 1GB+ disk at `/dwn-server/data`.
327
217
 
328
218
  ## Registration Requirements
329
219
 
330
- There are multiple optional registration gates, each of which can be enabled (all are disabled by default). Tenants (DIDs) must comply with whatever
331
- requirements are enabled before they are allowed to use the server. Tenants that have not completed the registration requirements will be met with a 401. Note that registration is tracked in a database, and only SQL-based databases are supported (LevelDB is not supported). Current registration
332
- requirements are available at the `/info` endpoint.
220
+ Optional registration gates (all disabled by default). Tenants that haven't completed registration get a 401. Registration is tracked in a SQL database (LevelDB not supported). Current requirements are exposed at `/info`.
221
+
222
+ - **Proof of Work** (`DWN_REGISTRATION_PROOF_OF_WORK_ENABLED=true`): GET `/registration/proof-of-work` for a challenge, compute a nonce where `sha256(challenge + nonce)` starts with the required number of zeros, POST it back. Challenges expire after 5 minutes.
333
223
 
334
- - **Proof of Work** (`DWN_REGISTRATION_PROOF_OF_WORK_ENABLED=true`) - new tenants must GET `/registration/proof-of-work` for a challenge, then generate a nonce that produces a string that has a sha256 hex sum starting with the specified (`complexity`) number of zeros (`0`) when added to the end of the challenge (`sha256(challenge + nonce)`). This nonce should be POSTed to `/registration/proof-of-work` with a JSON body including the `challenge`, the nonce in field `response` and `did`. Challenges expire after 5 minutes, and complexity will increase based on the number of successful proof-of-work registrations that have been completed within the last hour. This registration requirement is listed in `/info` as `proof-of-work-sha256-v0`.
335
- - **Terms of Service** (`DWN_TERMS_OF_SERVICE_FILE_PATH=/path/to/terms-of-service.txt`) - new tenants must GET `/registration/terms-of-service` to fetch the terms. These terms must be displayed to the human end-user, who must actively accept them. When the user accepts the terms, send the sha256 hash of the accepted terms and the user's did via POST `/registration/terms-of-service`. The JSON body should have fields `termsOfServiceHash` and `did`. To change the terms, update the file and restart the server. Users that accepted the old terms will be blocked until they accept the new terms. This registration requirement is listed in `/info` as `terms-of-service`.
224
+ - **Terms of Service** (`DWN_TERMS_OF_SERVICE_FILE_PATH=/path/to/tos.txt`): GET `/registration/terms-of-service`, display to user, POST `{ termsOfServiceHash, did }` on acceptance. Changing the file invalidates old acceptances.
336
225
 
337
- ## Server info
226
+ ## Server Info
338
227
 
339
- the server exposes information about itself via the `/info` endpoint, which returns data in the following format:
228
+ The `/info` endpoint returns:
340
229
 
341
230
  ```json
342
231
  {
@@ -349,5 +238,16 @@ the server exposes information about itself via the `/info` endpoint, which retu
349
238
  }
350
239
  ```
351
240
 
352
- - `server` is read from the `process.env.npm_package_name` variable that `npm` provides. If that does not exist, it will check for a `DWN_SERVER_PACKAGE_NAME` environment variable set by the user, or otherwise it will default to `@enbox/dwn-server`.
353
- - `version` and `sdkVersion` are read from the `package.json` file. It will locate the file's path either from the `process.env.npm_package_json` variable that `npm` provides. If that does not exist, it will check for a `DWN_SERVER_PACKAGE_JSON` environment variable set by the user, or otherwise it will default to `/dwn-server/package.json` which is the path within the default Docker container build.
241
+ ## Development
242
+
243
+ ```bash
244
+ bun run build # compile TypeScript
245
+ bun run test # run tests
246
+ bun run lint # lint
247
+ bun run lint:fix # auto-fix lint issues
248
+ bun run server # start the server
249
+ ```
250
+
251
+ ## License
252
+
253
+ Apache-2.0
@@ -0,0 +1,44 @@
1
+ import type { AdminActivityEvent } from './types.js';
2
+ /** Default maximum number of events retained in the ring buffer. */
3
+ export declare const DEFAULT_ACTIVITY_LOG_CAPACITY = 10000;
4
+ /**
5
+ * In-memory ring buffer that captures recent DWN request activity.
6
+ *
7
+ * Events are assigned a monotonically increasing `id` that acts as a cursor.
8
+ * When the buffer reaches capacity, the oldest events are evicted. This is
9
+ * **not** a persistent audit log — it is designed for real-time admin
10
+ * observability.
11
+ */
12
+ export declare class ActivityLog {
13
+ #private;
14
+ constructor(capacity?: number);
15
+ /**
16
+ * Records a new activity event. If the buffer is full, the oldest event is
17
+ * evicted.
18
+ */
19
+ record(event: Omit<AdminActivityEvent, 'id' | 'timestamp'>): void;
20
+ /**
21
+ * Returns recent events, optionally filtered by a cursor (returns events
22
+ * with `id > since`) and limited to `limit` entries.
23
+ */
24
+ getEvents(options?: {
25
+ since?: number;
26
+ limit?: number;
27
+ }): {
28
+ events: AdminActivityEvent[];
29
+ cursor?: number;
30
+ };
31
+ /**
32
+ * Returns the current number of events in the buffer.
33
+ */
34
+ get size(): number;
35
+ /**
36
+ * Returns the configured capacity of the ring buffer.
37
+ */
38
+ get capacity(): number;
39
+ /**
40
+ * Clears all events from the buffer.
41
+ */
42
+ clear(): void;
43
+ }
44
+ //# sourceMappingURL=activity-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity-log.d.ts","sourceRoot":"","sources":["../../../../src/admin/activity-log.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,oEAAoE;AACpE,eAAO,MAAM,6BAA6B,QAAS,CAAC;AAEpD;;;;;;;GAOG;AACH,qBAAa,WAAW;;gBAKV,QAAQ,GAAE,MAAsC;IAK5D;;;OAGG;IACI,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,kBAAkB,EAAE,IAAI,GAAG,WAAW,CAAC,GAAG,IAAI;IAmBxE;;;OAGG;IACI,SAAS,CAAC,OAAO,CAAC,EAAE;QACzB,KAAK,CAAC,EAAG,MAAM,CAAC;QAChB,KAAK,CAAC,EAAG,MAAM,CAAC;KACjB,GAAG;QAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;IA0BrD;;OAEG;IACH,IAAW,IAAI,IAAI,MAAM,CAExB;IAED;;OAEG;IACH,IAAW,QAAQ,IAAI,MAAM,CAE5B;IAED;;OAEG;IACI,KAAK,IAAI,IAAI;CAGrB"}
@@ -0,0 +1,85 @@
1
+ /** Default maximum number of events retained in the ring buffer. */
2
+ export const DEFAULT_ACTIVITY_LOG_CAPACITY = 10_000;
3
+ /**
4
+ * In-memory ring buffer that captures recent DWN request activity.
5
+ *
6
+ * Events are assigned a monotonically increasing `id` that acts as a cursor.
7
+ * When the buffer reaches capacity, the oldest events are evicted. This is
8
+ * **not** a persistent audit log — it is designed for real-time admin
9
+ * observability.
10
+ */
11
+ export class ActivityLog {
12
+ #capacity;
13
+ #buffer;
14
+ #nextId = 1;
15
+ constructor(capacity = DEFAULT_ACTIVITY_LOG_CAPACITY) {
16
+ this.#capacity = Math.max(1, capacity);
17
+ this.#buffer = [];
18
+ }
19
+ /**
20
+ * Records a new activity event. If the buffer is full, the oldest event is
21
+ * evicted.
22
+ */
23
+ record(event) {
24
+ const entry = {
25
+ id: this.#nextId++,
26
+ timestamp: new Date().toISOString(),
27
+ tenant: event.tenant,
28
+ interface: event.interface,
29
+ method: event.method,
30
+ statusCode: event.statusCode,
31
+ transport: event.transport,
32
+ dataSizeBytes: event.dataSizeBytes,
33
+ };
34
+ if (this.#buffer.length >= this.#capacity) {
35
+ this.#buffer.shift();
36
+ }
37
+ this.#buffer.push(entry);
38
+ }
39
+ /**
40
+ * Returns recent events, optionally filtered by a cursor (returns events
41
+ * with `id > since`) and limited to `limit` entries.
42
+ */
43
+ getEvents(options) {
44
+ const since = options?.since ?? 0;
45
+ const limit = options?.limit ?? 50;
46
+ // Binary search for the start index (events are ordered by id).
47
+ let startIdx = 0;
48
+ if (since > 0 && this.#buffer.length > 0) {
49
+ let lo = 0;
50
+ let hi = this.#buffer.length;
51
+ while (lo < hi) {
52
+ const mid = (lo + hi) >>> 1;
53
+ if (this.#buffer[mid].id <= since) {
54
+ lo = mid + 1;
55
+ }
56
+ else {
57
+ hi = mid;
58
+ }
59
+ }
60
+ startIdx = lo;
61
+ }
62
+ const events = this.#buffer.slice(startIdx, startIdx + limit);
63
+ const cursor = events.length > 0 ? events[events.length - 1].id : undefined;
64
+ return { events, cursor };
65
+ }
66
+ /**
67
+ * Returns the current number of events in the buffer.
68
+ */
69
+ get size() {
70
+ return this.#buffer.length;
71
+ }
72
+ /**
73
+ * Returns the configured capacity of the ring buffer.
74
+ */
75
+ get capacity() {
76
+ return this.#capacity;
77
+ }
78
+ /**
79
+ * Clears all events from the buffer.
80
+ */
81
+ clear() {
82
+ this.#buffer.length = 0;
83
+ }
84
+ }
85
+ //# sourceMappingURL=activity-log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity-log.js","sourceRoot":"","sources":["../../../../src/admin/activity-log.ts"],"names":[],"mappings":"AAEA,oEAAoE;AACpE,MAAM,CAAC,MAAM,6BAA6B,GAAG,MAAM,CAAC;AAEpD;;;;;;;GAOG;AACH,MAAM,OAAO,WAAW;IACb,SAAS,CAAS;IAClB,OAAO,CAAuB;IACvC,OAAO,GAAG,CAAC,CAAC;IAEZ,YAAY,WAAmB,6BAA6B;QAC1D,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QACvC,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IACpB,CAAC;IAED;;;OAGG;IACI,MAAM,CAAC,KAAmD;QAC/D,MAAM,KAAK,GAAuB;YAChC,EAAE,EAAc,IAAI,CAAC,OAAO,EAAE;YAC9B,SAAS,EAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACxC,MAAM,EAAU,KAAK,CAAC,MAAM;YAC5B,SAAS,EAAO,KAAK,CAAC,SAAS;YAC/B,MAAM,EAAU,KAAK,CAAC,MAAM;YAC5B,UAAU,EAAM,KAAK,CAAC,UAAU;YAChC,SAAS,EAAO,KAAK,CAAC,SAAS;YAC/B,aAAa,EAAG,KAAK,CAAC,aAAa;SACpC,CAAC;QAEF,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAC1C,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAED;;;OAGG;IACI,SAAS,CAAC,OAGhB;QACC,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,CAAC,CAAC;QAClC,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC;QAEnC,gEAAgE;QAChE,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,IAAI,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzC,IAAI,EAAE,GAAG,CAAC,CAAC;YACX,IAAI,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;YAC7B,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC;gBACf,MAAM,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;gBAC5B,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,KAAK,EAAE,CAAC;oBAClC,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC;gBACf,CAAC;qBAAM,CAAC;oBACN,EAAE,GAAG,GAAG,CAAC;gBACX,CAAC;YACH,CAAC;YACD,QAAQ,GAAG,EAAE,CAAC;QAChB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,GAAG,KAAK,CAAC,CAAC;QAC9D,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAE5E,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,IAAW,IAAI;QACb,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,IAAW,QAAQ;QACjB,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED;;OAEG;IACI,KAAK;QACV,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1B,CAAC;CACF"}