@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
@@ -1,775 +0,0 @@
1
- // node.js 18 and earlier, needs globalThis.crypto polyfill
2
- import sinon from 'sinon';
3
- import { DataStream, DwnErrorCode, ProtocolsConfigure, RecordsQuery, TestDataGenerator, Time, } from '@enbox/dwn-sdk-js';
4
- import { expect } from 'chai';
5
- import fetch from 'node-fetch';
6
- import { webcrypto } from 'node:crypto';
7
- import { useFakeTimers } from 'sinon';
8
- import request from 'supertest';
9
- import { v4 as uuidv4 } from 'uuid';
10
- import { config } from '../src/config.js';
11
- import log from 'loglevel';
12
- import { HttpApi } from '../src/http-api.js';
13
- import { createJsonRpcRequest, JsonRpcErrorCodes, } from '../src/lib/json-rpc.js';
14
- import { getTestDwn } from './test-dwn.js';
15
- import { createRecordsWriteMessage, getDwnResponse, getFileAsReadStream, } from './utils.js';
16
- import { RegistrationManager } from '../src/registration/registration-manager.js';
17
- import CommonScenarioValidator from './common-scenario-validator.js';
18
- import { Convert } from '@enbox/common';
19
- if (!globalThis.crypto) {
20
- // @ts-ignore
21
- globalThis.crypto = webcrypto;
22
- }
23
- describe('http api', function () {
24
- let httpApi;
25
- let alice;
26
- let registrationManager;
27
- let dwn;
28
- let clock;
29
- before(async function () {
30
- clock = useFakeTimers({ shouldAdvanceTime: true });
31
- // TODO: Remove direct use of default config to avoid changes bleed/pollute between tests - https://github.com/TBD54566975/dwn-server/issues/144
32
- config.registrationStoreUrl = 'sqlite://';
33
- config.registrationProofOfWorkEnabled = true;
34
- config.termsOfServiceFilePath = './tests/fixtures/terms-of-service.txt';
35
- config.registrationProofOfWorkInitialMaxHash = '0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'; // 1 in 16 chance of solving
36
- // RegistrationManager creation
37
- const registrationStoreUrl = config.registrationStoreUrl;
38
- const termsOfServiceFilePath = config.termsOfServiceFilePath;
39
- const proofOfWorkInitialMaximumAllowedHash = config.registrationProofOfWorkInitialMaxHash;
40
- registrationManager = await RegistrationManager.create({ registrationStoreUrl, termsOfServiceFilePath, proofOfWorkInitialMaximumAllowedHash });
41
- dwn = await getTestDwn({ tenantGate: registrationManager });
42
- httpApi = await HttpApi.create(config, dwn, registrationManager);
43
- });
44
- beforeEach(async function () {
45
- sinon.restore();
46
- await httpApi.start(3000);
47
- // generate a new persona for each test to avoid state pollution
48
- alice = await TestDataGenerator.generateDidKeyPersona();
49
- await registrationManager.recordTenantRegistration({ did: alice.did, termsOfServiceHash: registrationManager.getTermsOfServiceHash() });
50
- });
51
- afterEach(async function () {
52
- await httpApi.close();
53
- });
54
- after(function () {
55
- sinon.restore();
56
- clock.restore();
57
- });
58
- describe('/ (rpc)', function () {
59
- it('responds with a 400 if no dwn-request header is provided', async function () {
60
- const response = await request(httpApi.api).post('/').send();
61
- expect(response.statusCode).to.equal(400);
62
- const body = response.body;
63
- expect(body.error.code).to.equal(JsonRpcErrorCodes.BadRequest);
64
- expect(body.error.message).to.equal('request payload required.');
65
- });
66
- it('responds with a 400 if parsing dwn request fails', async function () {
67
- const response = await request(httpApi.api)
68
- .post('/')
69
- .set('dwn-request', ';;;;@!#@!$$#!@%')
70
- .send();
71
- expect(response.statusCode).to.equal(400);
72
- const body = response.body;
73
- expect(body.error.code).to.equal(JsonRpcErrorCodes.BadRequest);
74
- expect(body.error.message).to.include('JSON');
75
- });
76
- it('responds with a 2XX HTTP status if JSON RPC handler returns 4XX/5XX DWN status code', async function () {
77
- const { recordsWrite, dataStream } = await createRecordsWriteMessage(alice);
78
- // Intentionally delete a required property to produce an invalid RecordsWrite message.
79
- const message = recordsWrite.toJSON();
80
- delete message['descriptor']['interface'];
81
- const requestId = uuidv4();
82
- const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
83
- message: message,
84
- target: alice.did,
85
- });
86
- const dataBytes = await DataStream.toBytes(dataStream);
87
- // Attempt an initial RecordsWrite with the invalid message to ensure the DWN returns an error.
88
- const responseInitialWrite = await fetch('http://localhost:3000', {
89
- method: 'POST',
90
- headers: {
91
- 'dwn-request': JSON.stringify(dwnRequest),
92
- },
93
- body: new Blob([dataBytes]),
94
- });
95
- expect(responseInitialWrite.status).to.equal(200);
96
- const body = (await responseInitialWrite.json());
97
- expect(body.id).to.equal(requestId);
98
- expect(body.error).to.not.exist;
99
- const { reply } = body.result;
100
- expect(reply.status.code).to.equal(400);
101
- expect(reply.status.detail).to.include('Both interface and method must be present');
102
- });
103
- it('exposes dwn-response header', async function () {
104
- // This test verifies that the Express web server includes `dwn-response` in the list of
105
- // `access-control-expose-headers` returned in each HTTP response. This is necessary to enable applications
106
- // that have CORS enabled to read and parse DWeb Messages that are returned as Response headers, particularly
107
- // in the case of RecordsRead messages.
108
- // TODO: github.com/TBD54566975/dwn-server/issues/50
109
- // Consider replacing this test with a more robust method of testing, such as writing Playwright tests
110
- // that run in a browser to verify that the `dwn-response` header can be read from the `fetch()` response
111
- // when CORS mode is enabled.
112
- const response = await request(httpApi.api).post('/').send();
113
- // Check if the 'access-control-expose-headers' header is present
114
- expect(response.headers).to.have.property('access-control-expose-headers');
115
- // Check if the 'dwn-response' header is listed in 'access-control-expose-headers'
116
- const exposedHeaders = response.headers['access-control-expose-headers'];
117
- expect(exposedHeaders).to.include('dwn-response');
118
- });
119
- it('works fine when no request body is provided', async function () {
120
- const recordsQuery = await RecordsQuery.create({
121
- filter: {
122
- schema: 'woosa',
123
- },
124
- signer: alice.signer,
125
- });
126
- const requestId = uuidv4();
127
- const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
128
- message: recordsQuery.toJSON(),
129
- target: alice.did,
130
- });
131
- const response = await request(httpApi.api)
132
- .post('/')
133
- .set('dwn-request', JSON.stringify(dwnRequest))
134
- .send();
135
- expect(response.statusCode).to.equal(200);
136
- expect(response.body.id).to.equal(requestId);
137
- expect(response.body.error).to.not.exist;
138
- expect(response.body.result.reply.status.code).to.equal(200);
139
- });
140
- });
141
- describe('P0 Scenarios', function () {
142
- it('should be able to read and write a protocol record', async function () {
143
- await CommonScenarioValidator.sanityTestDwnReadWrite(config.baseUrl, alice);
144
- });
145
- });
146
- describe('RecordsWrite', function () {
147
- it('handles RecordsWrite overwrite that does not mutate data', async function () {
148
- // First RecordsWrite that creates the record.
149
- const { recordsWrite: initialWrite, dataStream } = await createRecordsWriteMessage(alice);
150
- const dataBytes = await DataStream.toBytes(dataStream);
151
- let requestId = uuidv4();
152
- let dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
153
- message: initialWrite.toJSON(),
154
- target: alice.did,
155
- });
156
- const responseInitialWrite = await fetch('http://localhost:3000', {
157
- method: 'POST',
158
- headers: {
159
- 'dwn-request': JSON.stringify(dwnRequest),
160
- },
161
- body: new Blob([dataBytes]),
162
- });
163
- expect(responseInitialWrite.status).to.equal(200);
164
- // Waiting for minimal time to make sure subsequent RecordsWrite has a later timestamp.
165
- await Time.minimalSleep();
166
- // Subsequent RecordsWrite that mutates the published property of the record.
167
- const { recordsWrite: overWrite } = await createRecordsWriteMessage(alice, {
168
- recordId: initialWrite.message.recordId,
169
- dataCid: initialWrite.message.descriptor.dataCid,
170
- dataSize: initialWrite.message.descriptor.dataSize,
171
- dateCreated: initialWrite.message.descriptor.dateCreated,
172
- published: true,
173
- });
174
- requestId = uuidv4();
175
- dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
176
- message: overWrite.toJSON(),
177
- target: alice.did,
178
- });
179
- const responseOverwrite = await fetch('http://localhost:3000', {
180
- method: 'POST',
181
- headers: {
182
- 'dwn-request': JSON.stringify(dwnRequest),
183
- },
184
- });
185
- expect(responseOverwrite.status).to.equal(200);
186
- const body = (await responseOverwrite.json());
187
- expect(body.error).to.not.exist;
188
- expect(body.id).to.equal(requestId);
189
- expect(body.error).to.not.exist;
190
- const { reply } = body.result;
191
- expect(reply.status.code).to.equal(202);
192
- });
193
- it('handles a RecordsWrite tombstone', async function () {
194
- const { recordsWrite: tombstone } = await createRecordsWriteMessage(alice);
195
- const requestId = uuidv4();
196
- const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
197
- message: tombstone.toJSON(),
198
- target: alice.did,
199
- });
200
- const responeTombstone = await fetch('http://localhost:3000', {
201
- method: 'POST',
202
- headers: {
203
- 'dwn-request': JSON.stringify(dwnRequest),
204
- },
205
- });
206
- expect(responeTombstone.status).to.equal(200);
207
- });
208
- });
209
- describe('health check', function () {
210
- it('returns a health check', async function () {
211
- const response = await fetch('http://localhost:3000/health', {
212
- method: 'GET',
213
- });
214
- expect(response.status).to.equal(200);
215
- });
216
- });
217
- describe('default http get response', function () {
218
- it('returns returns a default message', async function () {
219
- const response = await fetch('http://localhost:3000/', {
220
- method: 'GET',
221
- });
222
- expect(response.status).to.equal(200);
223
- });
224
- });
225
- describe('/:did/records/:id', function () {
226
- it('returns record data if record is published', async function () {
227
- const filePath = './fixtures/test.jpeg';
228
- const { cid: expectedCid, size, stream, } = await getFileAsReadStream(filePath);
229
- const { recordsWrite } = await createRecordsWriteMessage(alice, {
230
- dataCid: expectedCid,
231
- dataSize: size,
232
- published: true,
233
- });
234
- const requestId = uuidv4();
235
- const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
236
- message: recordsWrite.toJSON(),
237
- target: alice.did,
238
- });
239
- let response = await fetch('http://localhost:3000', {
240
- method: 'POST',
241
- headers: {
242
- 'dwn-request': JSON.stringify(dwnRequest),
243
- },
244
- body: stream,
245
- });
246
- expect(response.status).to.equal(200);
247
- const body = (await response.json());
248
- expect(body.id).to.equal(requestId);
249
- expect(body.error).to.not.exist;
250
- const { reply } = body.result;
251
- expect(reply.status.code).to.equal(202);
252
- response = await fetch(`http://localhost:3000/${alice.did}/records/${recordsWrite.message.recordId}`);
253
- const blob = await response.blob();
254
- expect(blob.size).to.equal(size);
255
- });
256
- it('returns a 404 if an unpublished record is requested', async function () {
257
- const filePath = './fixtures/test.jpeg';
258
- const { cid: expectedCid, size, stream, } = await getFileAsReadStream(filePath);
259
- const { recordsWrite } = await createRecordsWriteMessage(alice, {
260
- dataCid: expectedCid,
261
- dataSize: size,
262
- });
263
- const requestId = uuidv4();
264
- const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
265
- message: recordsWrite.toJSON(),
266
- target: alice.did,
267
- });
268
- let response = await fetch('http://localhost:3000', {
269
- method: 'POST',
270
- headers: {
271
- 'dwn-request': JSON.stringify(dwnRequest),
272
- },
273
- body: stream,
274
- });
275
- expect(response.status).to.equal(200);
276
- const body = (await response.json());
277
- expect(body.id).to.equal(requestId);
278
- expect(body.error).to.not.exist;
279
- const { reply } = body.result;
280
- expect(reply.status.code).to.equal(202);
281
- response = await fetch(`http://localhost:3000/${alice.did}/records/${recordsWrite.message.recordId}`);
282
- expect(response.status).to.equal(404);
283
- });
284
- it('returns a 404 if record does not exist', async function () {
285
- const { recordsWrite } = await createRecordsWriteMessage(alice);
286
- const response = await fetch(`http://localhost:3000/${alice.did}/records/${recordsWrite.message.recordId}`);
287
- expect(response.status).to.equal(404);
288
- });
289
- it('returns a 404 for invalid or unauthorized did', async function () {
290
- const unauthorized = await TestDataGenerator.generateDidKeyPersona();
291
- const { recordsWrite } = await createRecordsWriteMessage(unauthorized);
292
- const response = await fetch(`http://localhost:3000/${unauthorized.did}/records/${recordsWrite.message.recordId}`);
293
- expect(response.status).to.equal(404);
294
- });
295
- it('returns a 404 for invalid record id', async function () {
296
- const response = await fetch(`http://localhost:3000/${alice.did}/records/kaka`);
297
- expect(response.status).to.equal(404);
298
- });
299
- });
300
- describe('/:did/read/records/:id', function () {
301
- it('returns record data if record is published', async function () {
302
- const filePath = './fixtures/test.jpeg';
303
- const { cid: expectedCid, size, stream, } = await getFileAsReadStream(filePath);
304
- const { recordsWrite } = await createRecordsWriteMessage(alice, {
305
- dataCid: expectedCid,
306
- dataSize: size,
307
- published: true,
308
- });
309
- const requestId = uuidv4();
310
- const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
311
- message: recordsWrite.toJSON(),
312
- target: alice.did,
313
- });
314
- let response = await fetch('http://localhost:3000', {
315
- method: 'POST',
316
- headers: {
317
- 'dwn-request': JSON.stringify(dwnRequest),
318
- },
319
- body: stream,
320
- });
321
- expect(response.status).to.equal(200);
322
- const body = (await response.json());
323
- expect(body.id).to.equal(requestId);
324
- expect(body.error).to.not.exist;
325
- const { reply } = body.result;
326
- expect(reply.status.code).to.equal(202);
327
- response = await fetch(`http://localhost:3000/${alice.did}/read/records/${recordsWrite.message.recordId}`);
328
- const blob = await response.blob();
329
- expect(blob.size).to.equal(size);
330
- });
331
- it('returns a 404 if an unpublished record is requested', async function () {
332
- const filePath = './fixtures/test.jpeg';
333
- const { cid: expectedCid, size, stream, } = await getFileAsReadStream(filePath);
334
- const { recordsWrite } = await createRecordsWriteMessage(alice, {
335
- dataCid: expectedCid,
336
- dataSize: size,
337
- });
338
- const requestId = uuidv4();
339
- const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
340
- message: recordsWrite.toJSON(),
341
- target: alice.did,
342
- });
343
- let response = await fetch('http://localhost:3000', {
344
- method: 'POST',
345
- headers: {
346
- 'dwn-request': JSON.stringify(dwnRequest),
347
- },
348
- body: stream,
349
- });
350
- expect(response.status).to.equal(200);
351
- const body = (await response.json());
352
- expect(body.id).to.equal(requestId);
353
- expect(body.error).to.not.exist;
354
- const { reply } = body.result;
355
- expect(reply.status.code).to.equal(202);
356
- response = await fetch(`http://localhost:3000/${alice.did}/read/records/${recordsWrite.message.recordId}`);
357
- expect(response.status).to.equal(404);
358
- });
359
- it('returns a 404 if record does not exist', async function () {
360
- const { recordsWrite } = await createRecordsWriteMessage(alice);
361
- const response = await fetch(`http://localhost:3000/${alice.did}/read/records/${recordsWrite.message.recordId}`);
362
- expect(response.status).to.equal(404);
363
- });
364
- it('returns a 404 for invalid or unauthorized did', async function () {
365
- const unauthorized = await TestDataGenerator.generateDidKeyPersona();
366
- const { recordsWrite } = await createRecordsWriteMessage(unauthorized);
367
- const response = await fetch(`http://localhost:3000/${unauthorized.did}/read/records/${recordsWrite.message.recordId}`);
368
- expect(response.status).to.equal(404);
369
- });
370
- it('returns a 404 for invalid record id', async function () {
371
- const response = await fetch(`http://localhost:3000/${alice.did}/read/records/kaka`);
372
- expect(response.status).to.equal(404);
373
- });
374
- });
375
- describe('/:did/read/protocols/:protocol', function () {
376
- it('returns protocol definition if protocol is published', async function () {
377
- // Create and publish a protocol
378
- const protocolConfigure = await ProtocolsConfigure.create({
379
- definition: {
380
- protocol: 'http://example.com/protocol',
381
- published: true,
382
- types: {
383
- foo: {},
384
- },
385
- structure: {
386
- foo: {}
387
- }
388
- },
389
- signer: alice.signer,
390
- });
391
- const requestId = uuidv4();
392
- const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
393
- message: protocolConfigure.toJSON(),
394
- target: alice.did,
395
- });
396
- const response = await fetch('http://localhost:3000', {
397
- method: 'POST',
398
- headers: {
399
- 'dwn-request': JSON.stringify(dwnRequest),
400
- },
401
- });
402
- expect(response.status).to.equal(200);
403
- // Fetch the protocol definition using the HTTP API
404
- const base64urlEncodedProtocol = Convert.string(protocolConfigure.message.descriptor.definition.protocol).toBase64Url();
405
- const protocolUrl = `http://localhost:3000/${alice.did}/read/protocols/${base64urlEncodedProtocol}`;
406
- const protocolQueryResponse = await fetch(protocolUrl);
407
- expect(protocolQueryResponse.status).to.equal(200);
408
- // get the JSON response
409
- const protocolConfigureReply = await protocolQueryResponse.json();
410
- expect(protocolConfigureReply.descriptor).to.deep.equal(protocolConfigure.message.descriptor);
411
- });
412
- it('returns a 404 if protocol is not published', async function () {
413
- // Create a not-published protocol
414
- const protocolConfigure = await ProtocolsConfigure.create({
415
- definition: {
416
- protocol: 'http://example.com/protocol',
417
- published: false,
418
- types: {
419
- foo: {},
420
- },
421
- structure: {
422
- foo: {}
423
- }
424
- },
425
- signer: alice.signer,
426
- });
427
- const requestId = uuidv4();
428
- const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
429
- message: protocolConfigure.toJSON(),
430
- target: alice.did,
431
- });
432
- const response = await fetch('http://localhost:3000', {
433
- method: 'POST',
434
- headers: {
435
- 'dwn-request': JSON.stringify(dwnRequest),
436
- },
437
- });
438
- expect(response.status).to.equal(200);
439
- // Fetch the protocol definition using the HTTP API
440
- const base64urlEncodedProtocol = Convert.string(protocolConfigure.message.descriptor.definition.protocol).toBase64Url();
441
- const protocolUrl = `http://localhost:3000/${alice.did}/read/protocols/${base64urlEncodedProtocol}`;
442
- const protocolQueryResponse = await fetch(protocolUrl);
443
- expect(protocolQueryResponse.status).to.equal(404);
444
- });
445
- it('returns a 400 if protocol is not base64url encoded', async function () {
446
- const protocolUrl = `http://localhost:3000/${alice.did}/read/protocols/invalid-protocol`;
447
- const protocolQueryResponse = await fetch(protocolUrl);
448
- expect(protocolQueryResponse.status).to.equal(400);
449
- expect(await protocolQueryResponse.text()).to.equal('Bad Request');
450
- });
451
- });
452
- describe('/:did/query/protocols', function () {
453
- it('returns protocol definition if protocol is published', async function () {
454
- // create two protocol definitions, one published and one not
455
- const protocolConfigurePublished = await ProtocolsConfigure.create({
456
- definition: {
457
- protocol: 'http://example.com/protocol',
458
- published: true,
459
- types: {
460
- foo: {},
461
- },
462
- structure: {
463
- foo: {}
464
- }
465
- },
466
- signer: alice.signer,
467
- });
468
- const requestId = uuidv4();
469
- const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
470
- message: protocolConfigurePublished.toJSON(),
471
- target: alice.did,
472
- });
473
- const response = await fetch('http://localhost:3000', {
474
- method: 'POST',
475
- headers: {
476
- 'dwn-request': JSON.stringify(dwnRequest),
477
- },
478
- });
479
- expect(response.status).to.equal(200);
480
- const protocolConfigureNotPublished = await ProtocolsConfigure.create({
481
- definition: {
482
- protocol: 'http://example.com/protocol2',
483
- published: false,
484
- types: {
485
- foo: {},
486
- },
487
- structure: {
488
- foo: {}
489
- }
490
- },
491
- signer: alice.signer,
492
- });
493
- const requestId2 = uuidv4();
494
- const dwnRequest2 = createJsonRpcRequest(requestId2, 'dwn.processMessage', {
495
- message: protocolConfigureNotPublished.toJSON(),
496
- target: alice.did,
497
- });
498
- const response2 = await fetch('http://localhost:3000', {
499
- method: 'POST',
500
- headers: {
501
- 'dwn-request': JSON.stringify(dwnRequest2),
502
- },
503
- });
504
- expect(response2.status).to.equal(200);
505
- // now query for a list of protocols
506
- const protocolQueryUrl = `http://localhost:3000/${alice.did}/query/protocols`;
507
- const protocolQueryResponse = await fetch(protocolQueryUrl);
508
- expect(protocolQueryResponse.status).to.equal(200);
509
- // get the JSON response
510
- const protocolQueryReply = await protocolQueryResponse.json();
511
- expect(protocolQueryReply).to.have.lengthOf(1);
512
- // check that the published protocol is returned
513
- expect(protocolQueryReply[0].descriptor).to.deep.equal(protocolConfigurePublished.message.descriptor);
514
- });
515
- });
516
- describe('/:did/read/protocols/:protocol/*', function () {
517
- it('returns record for a given protocol and protocolPath that is published', async function () {
518
- // Create and publish a protocol
519
- const protocolConfigure = await ProtocolsConfigure.create({
520
- definition: {
521
- protocol: 'http://example.com/protocol',
522
- published: true,
523
- types: {
524
- foo: {},
525
- },
526
- structure: {
527
- foo: {}
528
- }
529
- },
530
- signer: alice.signer,
531
- });
532
- const requestId = uuidv4();
533
- const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
534
- message: protocolConfigure.toJSON(),
535
- target: alice.did,
536
- });
537
- const response = await fetch('http://localhost:3000', {
538
- method: 'POST',
539
- headers: {
540
- 'dwn-request': JSON.stringify(dwnRequest),
541
- },
542
- });
543
- expect(response.status).to.equal(200);
544
- // Create a foo record
545
- const filePath = './fixtures/test.jpeg';
546
- const { cid: expectedCid, size, stream, } = await getFileAsReadStream(filePath);
547
- const { recordsWrite } = await createRecordsWriteMessage(alice, {
548
- dataCid: expectedCid,
549
- dataSize: size,
550
- published: true,
551
- protocol: protocolConfigure.message.descriptor.definition.protocol,
552
- protocolPath: 'foo',
553
- });
554
- const recordsWriteRequestId = uuidv4();
555
- const recordsWriteDwnRequest = createJsonRpcRequest(recordsWriteRequestId, 'dwn.processMessage', {
556
- message: recordsWrite.toJSON(),
557
- target: alice.did,
558
- });
559
- const recordsWriteResponse = await fetch('http://localhost:3000', {
560
- method: 'POST',
561
- headers: {
562
- 'dwn-request': JSON.stringify(recordsWriteDwnRequest),
563
- },
564
- body: stream,
565
- });
566
- expect(recordsWriteResponse.status).to.equal(200);
567
- const responseJson = await recordsWriteResponse.json();
568
- expect(responseJson.result.reply.status.code).to.equal(202);
569
- // Fetch the record using the HTTP API
570
- const base64urlEncodedProtocol = Convert.string(protocolConfigure.message.descriptor.definition.protocol).toBase64Url();
571
- const protocolUrl = `http://localhost:3000/${alice.did}/read/protocols/${base64urlEncodedProtocol}/foo`;
572
- const recordReadResponse = await fetch(protocolUrl);
573
- expect(recordReadResponse.status).to.equal(200);
574
- // get the data response
575
- const blob = await recordReadResponse.blob();
576
- expect(blob.size).to.equal(size);
577
- // get dwn message response
578
- const { status, entry } = getDwnResponse(recordReadResponse);
579
- expect(status.code).to.equal(200);
580
- expect(entry).to.exist;
581
- expect(entry.recordsWrite.recordId).to.equal(recordsWrite.message.recordId);
582
- });
583
- it('removes the trailing slash from the protocol path', async function () {
584
- const recordsQueryCreateSpy = sinon.spy(RecordsQuery, 'create');
585
- const base64urlEncodedProtocol = Convert.string('http://example.com/protocol').toBase64Url();
586
- const protocolUrl = `http://localhost:3000/${alice.did}/read/protocols/${base64urlEncodedProtocol}/foo/`; // trailing slash
587
- const recordReadResponse = await fetch(protocolUrl);
588
- expect(recordReadResponse.status).to.equal(404);
589
- expect(recordsQueryCreateSpy.calledOnce).to.be.true;
590
- const recordsQueryFilter = recordsQueryCreateSpy.getCall(0).args[0].filter;
591
- expect(recordsQueryFilter.protocolPath).to.equal('foo');
592
- });
593
- it('returns a 404 if record for a given protocol and protocolPath is not published', async function () {
594
- // Create and publish a protocol
595
- const protocolConfigure = await ProtocolsConfigure.create({
596
- definition: {
597
- protocol: 'http://example.com/protocol',
598
- published: true,
599
- types: {
600
- foo: {},
601
- },
602
- structure: {
603
- foo: {}
604
- }
605
- },
606
- signer: alice.signer,
607
- });
608
- const requestId = uuidv4();
609
- const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
610
- message: protocolConfigure.toJSON(),
611
- target: alice.did,
612
- });
613
- const response = await fetch('http://localhost:3000', {
614
- method: 'POST',
615
- headers: {
616
- 'dwn-request': JSON.stringify(dwnRequest),
617
- },
618
- });
619
- expect(response.status).to.equal(200);
620
- // Create a foo record
621
- const filePath = './fixtures/test.jpeg';
622
- const { cid: expectedCid, size, stream, } = await getFileAsReadStream(filePath);
623
- const { recordsWrite } = await createRecordsWriteMessage(alice, {
624
- dataCid: expectedCid,
625
- dataSize: size,
626
- published: false, // not published
627
- protocol: protocolConfigure.message.descriptor.definition.protocol,
628
- protocolPath: 'foo',
629
- });
630
- const recordsWriteRequestId = uuidv4();
631
- const recordsWriteDwnRequest = createJsonRpcRequest(recordsWriteRequestId, 'dwn.processMessage', {
632
- message: recordsWrite.toJSON(),
633
- target: alice.did,
634
- });
635
- const recordsWriteResponse = await fetch('http://localhost:3000', {
636
- method: 'POST',
637
- headers: {
638
- 'dwn-request': JSON.stringify(recordsWriteDwnRequest),
639
- },
640
- body: stream,
641
- });
642
- expect(recordsWriteResponse.status).to.equal(200);
643
- const responseJson = await recordsWriteResponse.json();
644
- expect(responseJson.result.reply.status.code).to.equal(202);
645
- // Fetch the record using the HTTP API
646
- const base64urlEncodedProtocol = Convert.string(protocolConfigure.message.descriptor.definition.protocol).toBase64Url();
647
- const protocolUrl = `http://localhost:3000/${alice.did}/read/protocols/${base64urlEncodedProtocol}/foo`;
648
- const recordReadResponse = await fetch(protocolUrl);
649
- expect(recordReadResponse.status).to.equal(404);
650
- });
651
- it('returns a 400 if protocol path is not provided', async function () {
652
- // Fetch a protocol record without providing a protocol path
653
- const base64urlEncodedProtocol = Convert.string('http://example.com/protocol').toBase64Url();
654
- const protocolUrl = `http://localhost:3000/${alice.did}/read/protocols/${base64urlEncodedProtocol}/`; // missing protocol path
655
- const recordReadResponse = await fetch(protocolUrl);
656
- expect(recordReadResponse.status).to.equal(400);
657
- expect(await recordReadResponse.text()).to.equal('protocol path is required');
658
- });
659
- it('returns a 400 error if protocol cannot be base64url encoded', async function () {
660
- const protocolUrl = `http://localhost:3000/${alice.did}/read/protocols/invalid-protocol/foo`;
661
- const recordReadResponse = await fetch(protocolUrl);
662
- expect(recordReadResponse.status).to.equal(400);
663
- expect(await recordReadResponse.text()).to.equal('Bad Request');
664
- });
665
- });
666
- describe('/:did/query', function () {
667
- it('returns record data if record is published', async function () {
668
- const filePath = './fixtures/test.jpeg';
669
- const { cid: expectedCid, size, stream, } = await getFileAsReadStream(filePath);
670
- const { recordsWrite } = await createRecordsWriteMessage(alice, {
671
- dataCid: expectedCid,
672
- dataSize: size,
673
- published: true,
674
- });
675
- const requestId = uuidv4();
676
- const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
677
- message: recordsWrite.toJSON(),
678
- target: alice.did,
679
- });
680
- const response = await fetch('http://localhost:3000', {
681
- method: 'POST',
682
- headers: {
683
- 'dwn-request': JSON.stringify(dwnRequest),
684
- },
685
- body: stream,
686
- });
687
- expect(response.status).to.equal(200);
688
- const body = (await response.json());
689
- expect(body.id).to.equal(requestId);
690
- expect(body.error).to.not.exist;
691
- const { reply } = body.result;
692
- expect(reply.status.code).to.equal(202);
693
- const { entries } = await fetch(`http://localhost:3000/${alice.did}/query?filter.recordId=${recordsWrite.message.recordId}&other.random.param=unused-value`).then(response => response.json());
694
- expect(entries?.length).to.equal(1);
695
- });
696
- it('should return 400 if user provide invalid query', async function () {
697
- const response = await fetch(`http://localhost:3000/${alice.did}/query?filter=invalid-filter`);
698
- expect(response.status).to.equal(400);
699
- const responseBody = await response.json();
700
- expect(responseBody.code).to.equal(DwnErrorCode.SchemaValidatorAdditionalPropertyNotAllowed);
701
- });
702
- });
703
- describe('/info', function () {
704
- it('verify /info has some of the fields it is supposed to have', async function () {
705
- const resp = await fetch(`http://localhost:3000/info`);
706
- expect(resp.status).to.equal(200);
707
- const info = await resp.json();
708
- expect(info['url']).to.equal('http://localhost:3000');
709
- expect(info['server']).to.equal('@enbox/dwn-server');
710
- expect(info['registrationRequirements']).to.include('terms-of-service');
711
- expect(info['registrationRequirements']).to.include('proof-of-work-sha256-v0');
712
- });
713
- it('verify /info signals websocket support', async function () {
714
- let resp = await fetch(`http://localhost:3000/info`);
715
- expect(resp.status).to.equal(200);
716
- let info = await resp.json();
717
- expect(info['server']).to.equal('@enbox/dwn-server');
718
- expect(info['webSocketSupport']).to.equal(true);
719
- // start server without websocket support enabled
720
- await httpApi.close();
721
- config.webSocketSupport = false;
722
- httpApi = await HttpApi.create(config, dwn, registrationManager);
723
- await httpApi.start(3000);
724
- resp = await fetch(`http://localhost:3000/info`);
725
- expect(resp.status).to.equal(200);
726
- info = await resp.json();
727
- expect(info['server']).to.equal('@enbox/dwn-server');
728
- expect(info['webSocketSupport']).to.equal(false);
729
- // restore old config value
730
- config.webSocketSupport = true;
731
- });
732
- it('verify /info still returns when package.json file does not exist', async function () {
733
- await httpApi.close();
734
- // set up spy to check for an info log by the server
735
- const logSpy = sinon.spy(log, 'info');
736
- // set the config to an invalid file path
737
- const packageJsonConfig = config.packageJsonPath;
738
- config.packageJsonPath = '/some/invalid/file.json';
739
- httpApi = await HttpApi.create(config, dwn, registrationManager);
740
- await httpApi.start(3000);
741
- const resp = await fetch(`http://localhost:3000/info`);
742
- const info = await resp.json();
743
- expect(resp.status).to.equal(200);
744
- // check that server name exists in the info object
745
- expect(info['server']).to.equal('@enbox/dwn-server');
746
- // check that `sdkVersion` and `version` are undefined as they were not abel to be retrieved from the invalid file.
747
- expect(info['sdkVersion']).to.be.undefined;
748
- expect(info['version']).to.be.undefined;
749
- // check the logSpy was called
750
- expect(logSpy.callCount).to.be.gt(0);
751
- expect(logSpy.calledWith(sinon.match('could not read `package.json` for version info'))).to.be.true;
752
- // restore old config path
753
- config.packageJsonPath = packageJsonConfig;
754
- });
755
- it('verify /info returns server name from config', async function () {
756
- await httpApi.close();
757
- // set a custom name for the `serverName`
758
- const serverName = config.serverName;
759
- config.serverName = '@enbox/dwn-server-2';
760
- httpApi = await HttpApi.create(config, dwn, registrationManager);
761
- await httpApi.start(3000);
762
- const resp = await fetch(`http://localhost:3000/info`);
763
- const info = await resp.json();
764
- expect(resp.status).to.equal(200);
765
- // verify that the custom server name was passed to the info endpoint
766
- expect(info['server']).to.equal('@enbox/dwn-server-2');
767
- // verify that `sdkVersion` and `version` exist.
768
- expect(info['sdkVersion']).to.not.be.undefined;
769
- expect(info['version']).to.not.be.undefined;
770
- // restore server name config
771
- config.serverName = serverName;
772
- });
773
- });
774
- });
775
- //# sourceMappingURL=http-api.spec.js.map