spec-3nweb-server 1.8.4 → 1.8.6

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 (324) hide show
  1. package/.gitlab-ci-linux.yml +50 -0
  2. package/.gitlab-ci-mac.yml +29 -0
  3. package/.gitlab-ci-windows.yml +29 -0
  4. package/.gitlab-ci.yml +63 -0
  5. package/build/3nstorage/routes/owner/archive-obj-version.js +2 -2
  6. package/build/3nstorage/routes/owner/cancel-trans.js +2 -2
  7. package/build/3nstorage/routes/owner/delete-obj.js +2 -2
  8. package/build/3nstorage/routes/owner/get-current-obj.js +3 -4
  9. package/build/3nstorage/routes/owner/param-setter.js +2 -6
  10. package/build/asmail/routes/config/param-setter.js +2 -2
  11. package/build/asmail/routes/delivery/finalize-delivery.js +2 -2
  12. package/build/asmail/routes/delivery/put-obj.js +2 -2
  13. package/build/asmail/routes/delivery/sender-authorization.js +2 -2
  14. package/build/asmail/routes/retrieval/remove-message.js +2 -2
  15. package/build/cli/signup-cmd.js +0 -1
  16. package/build/lib-server/routes/sessions/close.js +2 -2
  17. package/build/lib-server/routes/sessions/mid-auth.js +2 -5
  18. package/build/main.js +12 -15
  19. package/build/mock/tls-options.js +46 -44
  20. package/build/signup/routes/add.js +4 -4
  21. package/build/tests/admin-proto/signup.d.ts +1 -0
  22. package/build/tests/admin-proto/signup.js +235 -0
  23. package/build/tests/jasmine.d.ts +1 -0
  24. package/build/tests/jasmine.js +32 -0
  25. package/build/tests/libs-for-tests/3nstorage.d.ts +22 -0
  26. package/build/tests/libs-for-tests/3nstorage.js +123 -0
  27. package/build/tests/libs-for-tests/asmail.d.ts +22 -0
  28. package/build/tests/libs-for-tests/asmail.js +179 -0
  29. package/build/tests/libs-for-tests/assert.d.ts +1 -0
  30. package/build/tests/libs-for-tests/assert.js +26 -0
  31. package/build/tests/libs-for-tests/async-jasmine.d.ts +7 -0
  32. package/build/tests/libs-for-tests/async-jasmine.js +77 -0
  33. package/build/tests/libs-for-tests/bytes-equal.d.ts +1 -0
  34. package/build/tests/libs-for-tests/bytes-equal.js +34 -0
  35. package/build/tests/libs-for-tests/json-copy.d.ts +1 -0
  36. package/build/tests/libs-for-tests/json-copy.js +45 -0
  37. package/build/tests/libs-for-tests/json-equal.d.ts +4 -0
  38. package/build/tests/libs-for-tests/json-equal.js +67 -0
  39. package/build/tests/libs-for-tests/mailerid.d.ts +13 -0
  40. package/build/tests/libs-for-tests/mailerid.js +114 -0
  41. package/build/tests/libs-for-tests/pkl.d.ts +28 -0
  42. package/build/tests/libs-for-tests/pkl.js +89 -0
  43. package/build/tests/libs-for-tests/server-components/3nstorage.d.ts +20 -0
  44. package/build/tests/libs-for-tests/server-components/3nstorage.js +200 -0
  45. package/build/tests/libs-for-tests/server-components/admin.d.ts +6 -0
  46. package/build/tests/libs-for-tests/server-components/admin.js +43 -0
  47. package/build/tests/libs-for-tests/server-components/asmail.d.ts +16 -0
  48. package/build/tests/libs-for-tests/server-components/asmail.js +143 -0
  49. package/build/tests/libs-for-tests/server-components/component.d.ts +13 -0
  50. package/build/tests/libs-for-tests/server-components/component.js +77 -0
  51. package/build/tests/libs-for-tests/server-components/mailerid.d.ts +10 -0
  52. package/build/tests/libs-for-tests/server-components/mailerid.js +103 -0
  53. package/build/tests/libs-for-tests/server-runner.d.ts +15 -0
  54. package/build/tests/libs-for-tests/server-runner.js +69 -0
  55. package/build/tests/libs-for-tests/spec-assembly.d.ts +6 -0
  56. package/build/tests/libs-for-tests/spec-assembly.js +55 -0
  57. package/build/tests/libs-for-tests/ws-utils.d.ts +3 -0
  58. package/build/tests/libs-for-tests/ws-utils.js +59 -0
  59. package/build/tests/libs-for-tests/xhr-utils.d.ts +61 -0
  60. package/build/tests/libs-for-tests/xhr-utils.js +154 -0
  61. package/build/tests/protocols/3nstorage/owner/specs/archive-obj-ver.d.ts +2 -0
  62. package/build/tests/protocols/3nstorage/owner/specs/archive-obj-ver.js +84 -0
  63. package/build/tests/protocols/3nstorage/owner/specs/archive-root-ver.d.ts +2 -0
  64. package/build/tests/protocols/3nstorage/owner/specs/archive-root-ver.js +78 -0
  65. package/build/tests/protocols/3nstorage/owner/specs/delete-archive-obj-ver.d.ts +2 -0
  66. package/build/tests/protocols/3nstorage/owner/specs/delete-archive-obj-ver.js +83 -0
  67. package/build/tests/protocols/3nstorage/owner/specs/delete-archive-root-ver.d.ts +2 -0
  68. package/build/tests/protocols/3nstorage/owner/specs/delete-archive-root-ver.js +77 -0
  69. package/build/tests/protocols/3nstorage/owner/specs/delete-obj.d.ts +2 -0
  70. package/build/tests/protocols/3nstorage/owner/specs/delete-obj.js +75 -0
  71. package/build/tests/protocols/3nstorage/owner/specs/events.d.ts +2 -0
  72. package/build/tests/protocols/3nstorage/owner/specs/events.js +91 -0
  73. package/build/tests/protocols/3nstorage/owner/specs/get-current-obj.d.ts +2 -0
  74. package/build/tests/protocols/3nstorage/owner/specs/get-current-obj.js +269 -0
  75. package/build/tests/protocols/3nstorage/owner/specs/get-current-root.d.ts +2 -0
  76. package/build/tests/protocols/3nstorage/owner/specs/get-current-root.js +262 -0
  77. package/build/tests/protocols/3nstorage/owner/specs/get-obj-status.d.ts +2 -0
  78. package/build/tests/protocols/3nstorage/owner/specs/get-obj-status.js +79 -0
  79. package/build/tests/protocols/3nstorage/owner/specs/get-root-status.d.ts +2 -0
  80. package/build/tests/protocols/3nstorage/owner/specs/get-root-status.js +72 -0
  81. package/build/tests/protocols/3nstorage/owner/specs/put-current-obj.d.ts +2 -0
  82. package/build/tests/protocols/3nstorage/owner/specs/put-current-obj.js +287 -0
  83. package/build/tests/protocols/3nstorage/owner/specs/put-current-root.d.ts +2 -0
  84. package/build/tests/protocols/3nstorage/owner/specs/put-current-root.js +274 -0
  85. package/build/tests/protocols/3nstorage/owner/specs/trans-cancel-root.d.ts +2 -0
  86. package/build/tests/protocols/3nstorage/owner/specs/trans-cancel-root.js +73 -0
  87. package/build/tests/protocols/3nstorage/owner/specs/trans-cancel.d.ts +2 -0
  88. package/build/tests/protocols/3nstorage/owner/specs/trans-cancel.js +72 -0
  89. package/build/tests/protocols/3nstorage/owner/test-utils.d.ts +14 -0
  90. package/build/tests/protocols/3nstorage/owner/test-utils.js +54 -0
  91. package/build/tests/protocols/3nstorage/owner.d.ts +1 -0
  92. package/build/tests/protocols/3nstorage/owner.js +138 -0
  93. package/build/tests/protocols/asmail/config.d.ts +1 -0
  94. package/build/tests/protocols/asmail/config.js +117 -0
  95. package/build/tests/protocols/asmail/delivery/specs/finalize-delivery.d.ts +2 -0
  96. package/build/tests/protocols/asmail/delivery/specs/finalize-delivery.js +60 -0
  97. package/build/tests/protocols/asmail/delivery/specs/provide-recipient-pubkey.d.ts +2 -0
  98. package/build/tests/protocols/asmail/delivery/specs/provide-recipient-pubkey.js +68 -0
  99. package/build/tests/protocols/asmail/delivery/specs/put-metadata.d.ts +2 -0
  100. package/build/tests/protocols/asmail/delivery/specs/put-metadata.js +83 -0
  101. package/build/tests/protocols/asmail/delivery/specs/put-obj.d.ts +2 -0
  102. package/build/tests/protocols/asmail/delivery/specs/put-obj.js +123 -0
  103. package/build/tests/protocols/asmail/delivery/specs/restart-session.d.ts +2 -0
  104. package/build/tests/protocols/asmail/delivery/specs/restart-session.js +79 -0
  105. package/build/tests/protocols/asmail/delivery/specs/start-session.d.ts +2 -0
  106. package/build/tests/protocols/asmail/delivery/specs/start-session.js +64 -0
  107. package/build/tests/protocols/asmail/delivery/test-utils.d.ts +16 -0
  108. package/build/tests/protocols/asmail/delivery/test-utils.js +46 -0
  109. package/build/tests/protocols/asmail/delivery.d.ts +1 -0
  110. package/build/tests/protocols/asmail/delivery.js +46 -0
  111. package/build/tests/protocols/asmail/retrieval/specs/events.d.ts +2 -0
  112. package/build/tests/protocols/asmail/retrieval/specs/events.js +62 -0
  113. package/build/tests/protocols/asmail/retrieval/specs/get-message-meta.d.ts +2 -0
  114. package/build/tests/protocols/asmail/retrieval/specs/get-message-meta.js +70 -0
  115. package/build/tests/protocols/asmail/retrieval/specs/get-message-obj.d.ts +2 -0
  116. package/build/tests/protocols/asmail/retrieval/specs/get-message-obj.js +166 -0
  117. package/build/tests/protocols/asmail/retrieval/specs/list-messages.d.ts +2 -0
  118. package/build/tests/protocols/asmail/retrieval/specs/list-messages.js +96 -0
  119. package/build/tests/protocols/asmail/retrieval/specs/remove-message.d.ts +2 -0
  120. package/build/tests/protocols/asmail/retrieval/specs/remove-message.js +66 -0
  121. package/build/tests/protocols/asmail/retrieval/test-utils.d.ts +17 -0
  122. package/build/tests/protocols/asmail/retrieval/test-utils.js +46 -0
  123. package/build/tests/protocols/asmail/retrieval.d.ts +1 -0
  124. package/build/tests/protocols/asmail/retrieval.js +92 -0
  125. package/build/tests/protocols/mailerid.d.ts +1 -0
  126. package/build/tests/protocols/mailerid.js +210 -0
  127. package/build/tests/shared-checks/check-mid-login.d.ts +2 -0
  128. package/build/tests/shared-checks/check-mid-login.js +131 -0
  129. package/build/tests/shared-checks/requests.d.ts +20 -0
  130. package/build/tests/shared-checks/requests.js +123 -0
  131. package/package.json +1 -1
  132. package/packing/create-deb.sh +57 -0
  133. package/packing/deb/lib/systemd/system/3nweb.service +11 -0
  134. package/packing/deb/postinst +44 -0
  135. package/packing/deb/usr/share/doc/3nweb-server/conf-for-postinstall.yaml +19 -0
  136. package/packing/deb/usr/share/doc/3nweb-server/copyright +22 -0
  137. package/publish-task.sh +10 -0
  138. package/push-to-github.sh +105 -0
  139. package/ts-code/3nstorage/3nstorage-app.ts +99 -0
  140. package/ts-code/3nstorage/owner.ts +178 -0
  141. package/ts-code/3nstorage/resources/sessions.ts +37 -0
  142. package/ts-code/3nstorage/resources/store.ts +896 -0
  143. package/ts-code/3nstorage/resources/users.ts +258 -0
  144. package/ts-code/3nstorage/routes/owner/archive-obj-version.ts +73 -0
  145. package/ts-code/3nstorage/routes/owner/cancel-trans.ts +58 -0
  146. package/ts-code/3nstorage/routes/owner/delete-obj.ts +103 -0
  147. package/ts-code/3nstorage/routes/owner/get-archived-obj-ver.ts +111 -0
  148. package/ts-code/3nstorage/routes/owner/get-current-obj.ts +122 -0
  149. package/ts-code/3nstorage/routes/owner/get-obj-status.ts +55 -0
  150. package/ts-code/3nstorage/routes/owner/param-getter.ts +51 -0
  151. package/ts-code/3nstorage/routes/owner/param-setter.ts +50 -0
  152. package/ts-code/3nstorage/routes/owner/put-current-obj.ts +284 -0
  153. package/ts-code/3nstorage/routes/owner/session-params.ts +49 -0
  154. package/ts-code/3nstorage/shared.ts +43 -0
  155. package/ts-code/asmail/asmail-app.ts +91 -0
  156. package/ts-code/asmail/config.ts +96 -0
  157. package/ts-code/asmail/delivery.ts +94 -0
  158. package/ts-code/asmail/resources/delivery-sessions.ts +118 -0
  159. package/ts-code/asmail/resources/inbox.ts +696 -0
  160. package/ts-code/asmail/resources/recipients.ts +495 -0
  161. package/ts-code/asmail/resources/sessions.ts +37 -0
  162. package/ts-code/asmail/retrieval.ts +96 -0
  163. package/ts-code/asmail/routes/config/param-getter.ts +49 -0
  164. package/ts-code/asmail/routes/config/param-setter.ts +49 -0
  165. package/ts-code/asmail/routes/delivery/finalize-delivery.ts +50 -0
  166. package/ts-code/asmail/routes/delivery/pre-flight.ts +132 -0
  167. package/ts-code/asmail/routes/delivery/provide-recipient-pubkey.ts +58 -0
  168. package/ts-code/asmail/routes/delivery/put-metadata.ts +94 -0
  169. package/ts-code/asmail/routes/delivery/put-obj.ts +166 -0
  170. package/ts-code/asmail/routes/delivery/restart-session.ts +130 -0
  171. package/ts-code/asmail/routes/delivery/sender-authorization.ts +81 -0
  172. package/ts-code/asmail/routes/delivery/start-session.ts +151 -0
  173. package/ts-code/asmail/routes/retrieval/get-message-meta.ts +53 -0
  174. package/ts-code/asmail/routes/retrieval/get-message-obj.ts +109 -0
  175. package/ts-code/asmail/routes/retrieval/list-messages.ts +70 -0
  176. package/ts-code/asmail/routes/retrieval/remove-message.ts +47 -0
  177. package/ts-code/cli/index.ts +82 -0
  178. package/ts-code/cli/run-cmd.ts +81 -0
  179. package/ts-code/cli/show-sample-config.ts +78 -0
  180. package/ts-code/cli/signup-cmd.ts +229 -0
  181. package/ts-code/cli/user-cmd.ts +68 -0
  182. package/ts-code/cli/utils.ts +105 -0
  183. package/ts-code/config/default-confs.ts +22 -0
  184. package/ts-code/config/from-yaml.ts +35 -0
  185. package/ts-code/config/letsencrypt.ts +77 -0
  186. package/ts-code/config/signup.ts +137 -0
  187. package/ts-code/lib-common/admin-api/signup.ts +120 -0
  188. package/ts-code/lib-common/assert.ts +22 -0
  189. package/ts-code/lib-common/async-fs-node.ts +656 -0
  190. package/ts-code/lib-common/buffer-utils.ts +124 -0
  191. package/ts-code/lib-common/byte-streaming/common.ts +166 -0
  192. package/ts-code/lib-common/bytes-equal.ts +25 -0
  193. package/ts-code/lib-common/canonical-address.ts +92 -0
  194. package/ts-code/lib-common/exceptions/error.ts +44 -0
  195. package/ts-code/lib-common/exceptions/file.ts +84 -0
  196. package/ts-code/lib-common/exceptions/http.ts +69 -0
  197. package/ts-code/lib-common/ipc/generic-ipc.ts +750 -0
  198. package/ts-code/lib-common/ipc/ws-ipc.ts +117 -0
  199. package/ts-code/lib-common/json-equal.ts +55 -0
  200. package/ts-code/lib-common/json-utils.ts +130 -0
  201. package/ts-code/lib-common/jwkeys.ts +246 -0
  202. package/ts-code/lib-common/map-of-sets.ts +60 -0
  203. package/ts-code/lib-common/mid-sigs-NaCl-Ed.ts +677 -0
  204. package/ts-code/lib-common/objs-on-disk/file-layout.ts +480 -0
  205. package/ts-code/lib-common/objs-on-disk/obj-file.ts +325 -0
  206. package/ts-code/lib-common/objs-on-disk/utils.ts +201 -0
  207. package/ts-code/lib-common/objs-on-disk/v1-obj-file-format.ts +329 -0
  208. package/ts-code/lib-common/processes.ts +501 -0
  209. package/ts-code/lib-common/random-node.ts +79 -0
  210. package/ts-code/lib-common/service-api/3nstorage/owner.ts +559 -0
  211. package/ts-code/lib-common/service-api/3nstorage/root-route.ts +22 -0
  212. package/ts-code/lib-common/service-api/asmail/config.ts +144 -0
  213. package/ts-code/lib-common/service-api/asmail/delivery.ts +250 -0
  214. package/ts-code/lib-common/service-api/asmail/retrieval.ts +238 -0
  215. package/ts-code/lib-common/service-api/asmail/root-route.ts +22 -0
  216. package/ts-code/lib-common/service-api/ipc-api.ts +44 -0
  217. package/ts-code/lib-common/service-api/locker.ts +44 -0
  218. package/ts-code/lib-common/service-api/mailer-id/login.ts +80 -0
  219. package/ts-code/lib-common/service-api/mailer-id/provisioning.ts +64 -0
  220. package/ts-code/lib-common/service-api/mailer-id/root-route.ts +25 -0
  221. package/ts-code/lib-common/service-api/pub-key-login.ts +75 -0
  222. package/ts-code/lib-common/service-api/web-socket-base.ts +87 -0
  223. package/ts-code/lib-common/session-encryptor.ts +54 -0
  224. package/ts-code/lib-common/time-window-cache.ts +74 -0
  225. package/ts-code/lib-common/transferable.d.ts +30 -0
  226. package/ts-code/lib-server/conf-util.ts +35 -0
  227. package/ts-code/lib-server/mid-access.ts +45 -0
  228. package/ts-code/lib-server/middleware/body-parsers.ts +248 -0
  229. package/ts-code/lib-server/middleware/error-handler.ts +79 -0
  230. package/ts-code/lib-server/pkl-access.ts +46 -0
  231. package/ts-code/lib-server/resources/dns.ts +151 -0
  232. package/ts-code/lib-server/resources/mailerid-authorizer.ts +115 -0
  233. package/ts-code/lib-server/resources/mem-backed-sessions-factory.ts +132 -0
  234. package/ts-code/lib-server/resources/server-data-folders.ts +160 -0
  235. package/ts-code/lib-server/resources/server-key-for-pkl-challenge.ts +41 -0
  236. package/ts-code/lib-server/resources/sessions.ts +232 -0
  237. package/ts-code/lib-server/resources/user-files.ts +147 -0
  238. package/ts-code/lib-server/routes/pub-key-login/complete-exchange.ts +63 -0
  239. package/ts-code/lib-server/routes/pub-key-login/start-exchange.ts +189 -0
  240. package/ts-code/lib-server/routes/sessions/close.ts +27 -0
  241. package/ts-code/lib-server/routes/sessions/mid-auth.ts +77 -0
  242. package/ts-code/lib-server/routes/sessions/start.ts +116 -0
  243. package/ts-code/lib-server/web-sockets/app.ts +339 -0
  244. package/ts-code/lib-server/web-sockets/server-events.ts +63 -0
  245. package/ts-code/lib.ts +29 -0
  246. package/ts-code/locker/locker-app.ts +60 -0
  247. package/ts-code/locker/resources/lockers.ts +17 -0
  248. package/ts-code/locker/resources/sessions.ts +37 -0
  249. package/ts-code/locker/routes/create-locker.ts +47 -0
  250. package/ts-code/mailerId/mailerId-app.ts +107 -0
  251. package/ts-code/mailerId/resources/certifier.ts +181 -0
  252. package/ts-code/mailerId/resources/sessions.ts +44 -0
  253. package/ts-code/mailerId/resources/users.ts +88 -0
  254. package/ts-code/mailerId/routes/certify.ts +68 -0
  255. package/ts-code/main.ts +304 -0
  256. package/ts-code/mock/dns.ts +106 -0
  257. package/ts-code/mock/mock-as-child-proc.ts +130 -0
  258. package/ts-code/mock/node-child-ipc.ts +69 -0
  259. package/ts-code/mock/run-in-proc.ts +111 -0
  260. package/ts-code/mock/tls-options.ts +73 -0
  261. package/ts-code/services.ts +138 -0
  262. package/ts-code/signup/resources/users.ts +429 -0
  263. package/ts-code/signup/routes/add.ts +65 -0
  264. package/ts-code/signup/routes/get-available-addresses.ts +49 -0
  265. package/ts-code/signup/routes/get-available-domains.ts +45 -0
  266. package/ts-code/signup/signup-app.ts +54 -0
  267. package/ts-code/signup/signup-tokens.ts +148 -0
  268. package/ts-code/tests/admin-proto/signup.ts +277 -0
  269. package/ts-code/tests/jasmine.ts +37 -0
  270. package/ts-code/tests/libs-for-tests/3nstorage.ts +144 -0
  271. package/ts-code/tests/libs-for-tests/asmail.ts +220 -0
  272. package/ts-code/tests/libs-for-tests/assert.ts +22 -0
  273. package/ts-code/tests/libs-for-tests/async-jasmine.ts +89 -0
  274. package/ts-code/tests/libs-for-tests/bytes-equal.ts +25 -0
  275. package/ts-code/tests/libs-for-tests/json-copy.ts +38 -0
  276. package/ts-code/tests/libs-for-tests/json-equal.ts +55 -0
  277. package/ts-code/tests/libs-for-tests/mailerid.ts +123 -0
  278. package/ts-code/tests/libs-for-tests/pkl.ts +127 -0
  279. package/ts-code/tests/libs-for-tests/server-components/3nstorage.ts +206 -0
  280. package/ts-code/tests/libs-for-tests/server-components/admin.ts +49 -0
  281. package/ts-code/tests/libs-for-tests/server-components/asmail.ts +152 -0
  282. package/ts-code/tests/libs-for-tests/server-components/component.ts +90 -0
  283. package/ts-code/tests/libs-for-tests/server-components/mailerid.ts +114 -0
  284. package/ts-code/tests/libs-for-tests/server-runner.ts +82 -0
  285. package/ts-code/tests/libs-for-tests/spec-assembly.ts +60 -0
  286. package/ts-code/tests/libs-for-tests/ws-utils.ts +61 -0
  287. package/ts-code/tests/libs-for-tests/xhr-utils.ts +179 -0
  288. package/ts-code/tests/protocols/3nstorage/owner/specs/archive-obj-ver.ts +100 -0
  289. package/ts-code/tests/protocols/3nstorage/owner/specs/archive-root-ver.ts +91 -0
  290. package/ts-code/tests/protocols/3nstorage/owner/specs/delete-archive-obj-ver.ts +99 -0
  291. package/ts-code/tests/protocols/3nstorage/owner/specs/delete-archive-root-ver.ts +90 -0
  292. package/ts-code/tests/protocols/3nstorage/owner/specs/delete-obj.ts +84 -0
  293. package/ts-code/tests/protocols/3nstorage/owner/specs/events.ts +125 -0
  294. package/ts-code/tests/protocols/3nstorage/owner/specs/get-current-obj.ts +298 -0
  295. package/ts-code/tests/protocols/3nstorage/owner/specs/get-current-root.ts +290 -0
  296. package/ts-code/tests/protocols/3nstorage/owner/specs/get-obj-status.ts +88 -0
  297. package/ts-code/tests/protocols/3nstorage/owner/specs/get-root-status.ts +80 -0
  298. package/ts-code/tests/protocols/3nstorage/owner/specs/put-current-obj.ts +366 -0
  299. package/ts-code/tests/protocols/3nstorage/owner/specs/put-current-root.ts +329 -0
  300. package/ts-code/tests/protocols/3nstorage/owner/specs/trans-cancel-root.ts +86 -0
  301. package/ts-code/tests/protocols/3nstorage/owner/specs/trans-cancel.ts +86 -0
  302. package/ts-code/tests/protocols/3nstorage/owner/test-utils.ts +72 -0
  303. package/ts-code/tests/protocols/3nstorage/owner.ts +198 -0
  304. package/ts-code/tests/protocols/asmail/config.ts +172 -0
  305. package/ts-code/tests/protocols/asmail/delivery/specs/finalize-delivery.ts +69 -0
  306. package/ts-code/tests/protocols/asmail/delivery/specs/provide-recipient-pubkey.ts +88 -0
  307. package/ts-code/tests/protocols/asmail/delivery/specs/put-metadata.ts +102 -0
  308. package/ts-code/tests/protocols/asmail/delivery/specs/put-obj.ts +156 -0
  309. package/ts-code/tests/protocols/asmail/delivery/specs/restart-session.ts +97 -0
  310. package/ts-code/tests/protocols/asmail/delivery/specs/start-session.ts +79 -0
  311. package/ts-code/tests/protocols/asmail/delivery/test-utils.ts +64 -0
  312. package/ts-code/tests/protocols/asmail/delivery.ts +56 -0
  313. package/ts-code/tests/protocols/asmail/retrieval/specs/events.ts +78 -0
  314. package/ts-code/tests/protocols/asmail/retrieval/specs/get-message-meta.ts +80 -0
  315. package/ts-code/tests/protocols/asmail/retrieval/specs/get-message-obj.ts +197 -0
  316. package/ts-code/tests/protocols/asmail/retrieval/specs/list-messages.ts +110 -0
  317. package/ts-code/tests/protocols/asmail/retrieval/specs/remove-message.ts +74 -0
  318. package/ts-code/tests/protocols/asmail/retrieval/test-utils.ts +60 -0
  319. package/ts-code/tests/protocols/asmail/retrieval.ts +115 -0
  320. package/ts-code/tests/protocols/mailerid.ts +271 -0
  321. package/ts-code/tests/shared-checks/check-mid-login.ts +164 -0
  322. package/ts-code/tests/shared-checks/requests.ts +135 -0
  323. package/ts-code/tsconfig.json +11 -0
  324. package/ts-code/web3n.d.ts +1068 -0
@@ -0,0 +1,696 @@
1
+ /*
2
+ Copyright (C) 2015 - 2017, 2019 - 2020, 2025 3NSoft Inc.
3
+
4
+ This program is free software: you can redistribute it and/or modify it under
5
+ the terms of the GNU General Public License as published by the Free Software
6
+ Foundation, either version 3 of the License, or (at your option) any later
7
+ version.
8
+
9
+ This program is distributed in the hope that it will be useful, but
10
+ WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
+ See the GNU General Public License for more details.
13
+
14
+ You should have received a copy of the GNU General Public License along with
15
+ this program. If not, see <http://www.gnu.org/licenses/>.
16
+ */
17
+
18
+ /**
19
+ * Inbox files are laid out on disk in the following way:
20
+ * (a) store is just a folder with stuff inside;
21
+ * (b) main store folder contains following folders:
22
+ * (b.1) messages - is a folder for message folders,
23
+ * (b.2) delivery - is a folder for messages, that are in a process of
24
+ * being delivered; complete messages are moved to
25
+ * 'messages' folder.
26
+ * (b.3) params - is a place for information files about this mail box;
27
+ * (c) message folder's name is message's id. Each message folder contains:
28
+ * (c.1) meta - is a file with plain-text JSON-form metadata for a message.
29
+ * (c.2) objects - is a folder with all object files, that are part of the
30
+ * message.
31
+ */
32
+
33
+ import * as fs from '../../lib-common/async-fs-node';
34
+ import { Readable } from 'stream';
35
+ import { isLikeSignedKeyCert } from '../../lib-common/jwkeys';
36
+ import * as random from '../../lib-common/random-node';
37
+ import * as deliveryApi from '../../lib-common/service-api/asmail/delivery';
38
+ import * as configApi from '../../lib-common/service-api/asmail/config';
39
+ import * as retrievalApi from '../../lib-common/service-api/asmail/retrieval';
40
+ import { UserFiles, SC as ufSC, ObjReader } from '../../lib-server/resources/user-files';
41
+ import { NamedProcs } from '../../lib-common/processes';
42
+ import { TimeWindowCache } from '../../lib-common/time-window-cache';
43
+ import { ObjVersionFile } from '../../lib-common/objs-on-disk/obj-file';
44
+ import { join } from 'path';
45
+ import { errWithCause } from '../../lib-common/exceptions/error';
46
+ import { chunksInOrderedStream, streamToObjFile, makeNoBaseObjPipe } from '../../lib-common/objs-on-disk/utils';
47
+
48
+ export { ObjPipe, ObjReader } from '../../lib-server/resources/user-files';
49
+
50
+ type InitPubKey = configApi.p.initPubKey.Certs;
51
+ type AnonSenderPolicy = configApi.p.anonSenderPolicy.Policy;
52
+ export type AuthSenderPolicy = configApi.p.authSenderPolicy.Policy;
53
+ type Whitelist = configApi.p.authSenderWhitelist.List;
54
+ type Blacklist = configApi.p.authSenderBlacklist.List;
55
+ type AuthSenderInvites = configApi.p.authSenderInvites.List;
56
+ type AnonSenderInvites = configApi.p.anonSenderInvites.List;
57
+
58
+ type MsgMeta = retrievalApi.MsgMeta;
59
+ export type MsgEvents = retrievalApi.msgMainObjRecieved.Event |
60
+ retrievalApi.msgRecievedCompletely.Event;
61
+
62
+ export type MailEventsSink = (
63
+ userId: string, channel: string, event: MsgEvents
64
+ ) => void;
65
+
66
+ export const SC = {
67
+ OBJ_EXIST: 'obj-already-exist',
68
+ USER_UNKNOWN: ufSC.USER_UNKNOWN,
69
+ MSG_UNKNOWN: 'msg-unknown',
70
+ OBJ_UNKNOWN: 'obj-unknown',
71
+ WRONG_OBJ_STATE: 'wrong-obj-state',
72
+ OBJ_FILE_INCOMPLETE: 'obj-file-incomplete'
73
+ };
74
+ Object.freeze(SC);
75
+
76
+ const META_FILE = 'meta.json';
77
+
78
+ const MSG_ID_LEN = 32;
79
+
80
+ /**
81
+ * This returns a promise, resolvable to generated msg id, when folder for a
82
+ * message is created in the delivery folder.
83
+ * @param delivPath
84
+ * @param msgsFolder is an additional folder, checked against id-collision
85
+ */
86
+ async function genMsgIdAndMakeFolder(
87
+ delivPath: string, msgsFolder: string
88
+ ): Promise<string> {
89
+ const msgId = await random.stringOfB64UrlSafeChars(MSG_ID_LEN);
90
+ // make msg folder among deliveries
91
+ try {
92
+ await fs.mkdir(join(delivPath, msgId));
93
+ } catch (exc) {
94
+ if ((<fs.FileException> exc).alreadyExists) {
95
+ return genMsgIdAndMakeFolder(delivPath, msgsFolder);
96
+ } else { throw exc; }
97
+ }
98
+ // ensure that msgId does not belong to any existing message
99
+ try {
100
+ await fs.stat(join(msgsFolder, msgId));
101
+ await fs.rmdir(join(delivPath, msgId));
102
+ return genMsgIdAndMakeFolder(delivPath, msgsFolder);
103
+ } catch (exc) {}
104
+ return msgId;
105
+ }
106
+
107
+ export interface InboxParams {
108
+ "pubkey": InitPubKey|null;
109
+ "anonymous/policy": AnonSenderPolicy;
110
+ "anonymous/invites": AnonSenderInvites;
111
+ "authenticated/policy": AuthSenderPolicy;
112
+ "authenticated/blacklist": Blacklist;
113
+ "authenticated/whitelist": Whitelist;
114
+ "authenticated/invites": AuthSenderInvites;
115
+ }
116
+
117
+
118
+ export class Inbox extends UserFiles<InboxParams> {
119
+
120
+ private metas = new MsgMetas(
121
+ 5*60*1000, join(this.path, 'delivery'), join(this.path, 'messages'));
122
+
123
+ private objFiles = new ObjFiles(
124
+ 5*60*1000, this.metas.deliveryFolder, this.metas.readyMsgsFolder);
125
+
126
+ private mailEventsSink: MailEventsSink;
127
+
128
+ constructor(
129
+ userId: string, path: string, mailEventsSink: MailEventsSink,
130
+ writeBufferSize?: string|number, readBufferSize?: string|number
131
+ ) {
132
+ super(userId, path, writeBufferSize, readBufferSize);
133
+ this.mailEventsSink = mailEventsSink;
134
+ Object.freeze(this);
135
+ }
136
+
137
+ static async make(
138
+ userFolder: string, userId: string, mailEventsSink: MailEventsSink,
139
+ writeBufferSize?: string|number, readBufferSize?: string|number
140
+ ): Promise<Inbox> {
141
+ const path = join(userFolder, 'mail');
142
+ const inbox = new Inbox(
143
+ userId, path, mailEventsSink, writeBufferSize, readBufferSize
144
+ );
145
+ await inbox.ensureUserExistsOnDisk();
146
+ return inbox;
147
+ }
148
+
149
+ /**
150
+ * @return a promise, resolvable to number bytes used by this inbox.
151
+ */
152
+ async usedSpace(): Promise<number> {
153
+ // XXX need to use space-tracker service!
154
+ // For now we return zero.
155
+ return 0;
156
+ }
157
+
158
+ /**
159
+ * @return a promise, resolvable to free space in bytes.
160
+ */
161
+ async freeSpace(): Promise<number> {
162
+ // XXX need to use space-tracker service!
163
+ const usedSpace = await this.usedSpace();
164
+ const quota = await this.getSpaceQuota();
165
+ return Math.max(0, quota - usedSpace);
166
+ }
167
+
168
+ /**
169
+ * This returns a promise, resolvable to message id, when a folder for new
170
+ * message has been created.
171
+ * @param extMeta is json object with message's meta info directly from
172
+ * sender.
173
+ * @param authSender is an address of sender, if such was authenticated.
174
+ * @param invite is an invitation token, if any were used.
175
+ */
176
+ async recordMsgMeta(
177
+ extMeta: deliveryApi.msgMeta.Request, authSender: string|undefined,
178
+ invite: string|undefined, maxMsgLength: number
179
+ ): Promise<string> {
180
+ const msgId = await genMsgIdAndMakeFolder(
181
+ this.metas.deliveryFolder, this.metas.readyMsgsFolder);
182
+ const meta: MsgMeta = {
183
+ extMeta, authSender, invite, maxMsgLength,
184
+ recipient: this.userId,
185
+ deliveryStart: Date.now(),
186
+ objs: {}
187
+ };
188
+ await this.metas.set(msgId, meta);
189
+ return msgId;
190
+ }
191
+
192
+ /**
193
+ * This returns a promise, resolvable to message metadata from disk, when it
194
+ * as been found on the disk.
195
+ * Rejected promise may pass a string error code from SC.
196
+ * @param msgId
197
+ * @param completeMsg flag, true for complete messages, and false for
198
+ * incomplete (in-delivery) messages.
199
+ */
200
+ async getMsgMeta(msgId: string, completeMsg: boolean): Promise<MsgMeta> {
201
+ return this.metas.get(msgId, completeMsg);
202
+ }
203
+
204
+ async startSavingObj(
205
+ msgId: string, objId: string, bytes: Readable, bytesLen: number,
206
+ opts: deliveryApi.PutObjFirstQueryOpts
207
+ ): Promise<void> {
208
+ // check meta
209
+ const meta = await this.metas.get(msgId, false);
210
+ if (meta.extMeta.objIds.indexOf(objId) < 0) { throw SC.OBJ_UNKNOWN; }
211
+ if (meta.objs[objId]) { throw SC.WRONG_OBJ_STATE; }
212
+
213
+ const file = await this.objFiles.forNewFile(msgId, objId);
214
+ const chunks = chunksInOrderedStream(bytesLen, opts.header, 0);
215
+ await streamToObjFile(file, chunks, bytes, this.fileWritingBufferSize);
216
+
217
+ // set obj status in meta
218
+ meta.objs[objId] = {
219
+ size: {
220
+ header: opts.header,
221
+ segments: bytesLen - opts.header
222
+ }
223
+ };
224
+ if (opts.last) {
225
+ if (file.isFileComplete()) {
226
+ meta.objs[objId].completed = true;
227
+ } else {
228
+ await this.metas.set(msgId, meta);
229
+ throw SC.OBJ_FILE_INCOMPLETE;
230
+ }
231
+ }
232
+ await this.metas.set(msgId, meta);
233
+ }
234
+
235
+ async continueSavingObj(
236
+ msgId: string, objId: string, bytes: Readable, bytesLen: number,
237
+ opts: deliveryApi.PutObjSecondQueryOpts
238
+ ): Promise<void> {
239
+ // check obj status
240
+ const meta = await this.metas.get(msgId, false);
241
+ const objStatus = meta.objs[objId];
242
+ if (objStatus) {
243
+ if (objStatus.completed) { throw SC.WRONG_OBJ_STATE; }
244
+ } else {
245
+ if (meta.extMeta.objIds.indexOf(objId) < 0) { throw SC.OBJ_UNKNOWN; }
246
+ else { throw SC.WRONG_OBJ_STATE; }
247
+ }
248
+
249
+ const file = await this.objFiles.forExistingFile(msgId, objId, true);
250
+ const chunks = chunksInOrderedStream(bytesLen, undefined, opts.ofs);
251
+ await streamToObjFile(file, chunks, bytes, this.fileWritingBufferSize);
252
+
253
+ // update meta
254
+ objStatus.size.segments! += bytesLen;
255
+ if (opts.last) {
256
+ if (file.isFileComplete()) {
257
+ objStatus.completed = true;
258
+ } else {
259
+ await this.metas.set(msgId, meta);
260
+ throw SC.OBJ_FILE_INCOMPLETE;
261
+ }
262
+ }
263
+ await this.metas.set(msgId, meta);
264
+ }
265
+
266
+ /**
267
+ * This returns a promise, resolvable, when a message has been moved from
268
+ * delivery to messages storing folder.
269
+ * Rejected promise may pass string error code from SC.
270
+ * @param msgId
271
+ */
272
+ async completeMsgDelivery(msgId: string): Promise<void> {
273
+ // indicate completion in meta
274
+ const meta = await this.metas.get(msgId, false);
275
+ if (!this.areAllMsgObjsComplete(msgId, meta)) {
276
+ throw SC.OBJ_FILE_INCOMPLETE;
277
+ }
278
+ meta.deliveryCompletion = Date.now();
279
+ await this.metas.set(msgId, meta);
280
+
281
+ // move message folder to a place with completed messages
282
+ const srcFolder = join(this.metas.deliveryFolder, msgId);
283
+ const dstFolder = join(this.metas.readyMsgsFolder, msgId);
284
+ await fs.rename(srcFolder, dstFolder);
285
+ this.objFiles.changeToReadingPathsInMsg(msgId);
286
+
287
+ // raise event about completion of receiving a message
288
+ this.mailEventsSink(this.userId,
289
+ retrievalApi.msgRecievedCompletely.EVENT_NAME,
290
+ { msgId });
291
+ }
292
+
293
+ private areAllMsgObjsComplete(
294
+ msgId: string, meta: retrievalApi.MsgMeta
295
+ ): boolean {
296
+ for (const status of Object.values(meta.objs)) {
297
+ if (!status.completed) { return false; }
298
+ }
299
+ return true;
300
+ }
301
+
302
+ /**
303
+ * @param fromTS
304
+ * @param toTS
305
+ * @return a promise, resolvable to a list of available message ids.
306
+ */
307
+ async getMsgIds(fromTS: number|undefined, toTS: number|undefined): Promise<retrievalApi.listMsgs.Reply> {
308
+ // XXX this isn't efficient, and needs sqlite-powered index
309
+ const lst = await fs.readdir(this.metas.readyMsgsFolder);
310
+ if ((fromTS === undefined) && (toTS === undefined)) {
311
+ return lst;
312
+ }
313
+ const filteredLst: string[] = [];
314
+ for (const msgId of lst) {
315
+ try {
316
+ const { deliveryStart } = await this.metas.get(msgId, true);
317
+ if (fromTS && (deliveryStart < fromTS)) {
318
+ continue;
319
+ }
320
+ if (toTS && (toTS < deliveryStart)) {
321
+ continue;
322
+ }
323
+ filteredLst.push(msgId);
324
+ } catch (exc) {}
325
+ }
326
+ return filteredLst;
327
+ }
328
+
329
+ /**
330
+ * This method returns parameters of an incomplete message, identified
331
+ * by a given id.
332
+ * @param msgId
333
+ */
334
+ async getIncompleteMsgParams(
335
+ msgId: string
336
+ ): Promise<{ maxMsgLength: number; currentMsgLength: number; }> {
337
+ const msgMeta = await this.metas.get(msgId, false);
338
+ let currentMsgLength = 0;
339
+ for (const obj of Object.values(msgMeta.objs)) {
340
+ currentMsgLength += obj.size.header + obj.size.segments!;
341
+ }
342
+ const maxMsgLength = msgMeta.maxMsgLength;
343
+ return { maxMsgLength, currentMsgLength };
344
+ }
345
+
346
+ /**
347
+ * This method removes message folder from the disk.
348
+ * @param msgId is an id of a message, that needs to be removed.
349
+ * @return promise, resolvable when a message folder is removed from
350
+ * the disk.
351
+ * Rejected promise may pass string error code from SC.
352
+ */
353
+ async rmMsg(msgId: string): Promise<void> {
354
+ this.metas.uncache(msgId);
355
+ this.objFiles.uncache(msgId);
356
+ try {
357
+ const msgPath = join(this.metas.readyMsgsFolder, msgId);
358
+ const rmPath = `${msgPath}~remove`;
359
+ await fs.rename(msgPath, rmPath);
360
+ await fs.rmDirWithContent(rmPath);
361
+ } catch (exc) {
362
+ if ((exc as fs.FileException).notFound) {
363
+ throw SC.MSG_UNKNOWN;
364
+ }
365
+ throw exc;
366
+ }
367
+ }
368
+
369
+ /**
370
+ * This method returns promise that resolves to obj reader.
371
+ * @param msgId
372
+ * @param objId
373
+ * @param header is a boolean flag that says if header bytes should be
374
+ * read
375
+ * @param segsOffset indicates offset from which segment bytes should be
376
+ * read
377
+ * @param segsLimit
378
+ */
379
+ async getObj(
380
+ msgId: string, objId: string,
381
+ header: boolean, segsOfs: number, segsLimit: number|undefined
382
+ ): Promise<ObjReader> {
383
+ const file = await this.objFiles.forExistingFile(msgId, objId);
384
+
385
+ // find total segments length
386
+ const segsLen = file.getTotalSegsLen();
387
+
388
+ // contain boundary parameters offsetIntoSegs and len for segment bytes
389
+ if (segsLen < segsOfs) {
390
+ segsOfs = segsLen;
391
+ }
392
+ let segBytesToRead: number;
393
+ if (segsLimit === undefined) {
394
+ segBytesToRead = segsLen - segsOfs;
395
+ } else if ((segsOfs+segsLimit) >= segsLen) {
396
+ segBytesToRead = segsLen - segsOfs;
397
+ } else {
398
+ segBytesToRead = segsLimit;
399
+ }
400
+
401
+ // construct reader
402
+ let reader: ObjReader;
403
+ if (header) {
404
+ const headerLen = file.getHeaderLen()!;
405
+ reader = {
406
+ len: (segBytesToRead + headerLen),
407
+ segsLen,
408
+ headerLen,
409
+ pipe: makeNoBaseObjPipe(file, true, segsOfs, segBytesToRead)
410
+ };
411
+ } else {
412
+ reader = {
413
+ len: segBytesToRead,
414
+ segsLen,
415
+ pipe: makeNoBaseObjPipe(file, false, segsOfs, segBytesToRead)
416
+ };
417
+ }
418
+ Object.freeze(reader);
419
+
420
+ return reader;
421
+ }
422
+
423
+ /**
424
+ * @param initKeyCerts
425
+ * @return a promise, resolvable to true, when certs are set, or
426
+ * resolvable to false, when given certs do not pass sanitization.
427
+ */
428
+ async setPubKey(initKeyCerts: InitPubKey|null): Promise<boolean> {
429
+ if ((initKeyCerts === null) || isValidIntroPKeyCerts(initKeyCerts)) {
430
+ await this.setParam('pubkey', initKeyCerts);
431
+ return true;
432
+ } else {
433
+ return false;
434
+ }
435
+ }
436
+
437
+ async setAnonSenderPolicy(policy: AnonSenderPolicy): Promise<boolean> {
438
+ if (isValidAnonSenderPolicy(policy)) {
439
+ await this.setParam('anonymous/policy', policy);
440
+ return true;
441
+ } else {
442
+ return false;
443
+ }
444
+ }
445
+
446
+ async setAnonSenderInvites(invites: AnonSenderInvites): Promise<boolean> {
447
+ if (isValidListWithMsgMaxSizes(invites)) {
448
+ await this.setParam('anonymous/invites', invites);
449
+ return true;
450
+ } else {
451
+ return false;
452
+ }
453
+ }
454
+
455
+ async setAuthSenderPolicy(policy: AuthSenderPolicy): Promise<boolean> {
456
+ if (isValidAuthSenderPolicy(policy)) {
457
+ await this.setParam('authenticated/policy', policy);
458
+ return true;
459
+ } else {
460
+ return false;
461
+ }
462
+ }
463
+
464
+ async setAuthSenderBlacklist(lst: Blacklist): Promise<boolean> {
465
+ if (isValidBlacklist(lst)) {
466
+ await this.setParam('authenticated/blacklist', lst);
467
+ return true;
468
+ } else {
469
+ return false;
470
+ }
471
+ }
472
+
473
+ async setAuthSenderWhitelist(lst: Whitelist): Promise<boolean> {
474
+ if (isValidListWithMsgMaxSizes(lst)) {
475
+ await this.setParam('authenticated/whitelist', lst);
476
+ return true;
477
+ } else {
478
+ return false;
479
+ }
480
+ }
481
+
482
+ async setAuthSenderInvites(invites: AuthSenderInvites): Promise<boolean> {
483
+ if (isValidListWithMsgMaxSizes(invites)) {
484
+ await this.setParam('authenticated/invites', invites);
485
+ return true;
486
+ } else {
487
+ return false;
488
+ }
489
+ }
490
+
491
+ }
492
+ Object.freeze(Inbox.prototype);
493
+ Object.freeze(Inbox);
494
+
495
+
496
+ function isValidIntroPKeyCerts(pkeyCerts: InitPubKey): boolean {
497
+ return (
498
+ (typeof pkeyCerts === 'object') && !!pkeyCerts &&
499
+ isLikeSignedKeyCert(pkeyCerts.pkeyCert) &&
500
+ isLikeSignedKeyCert(pkeyCerts.userCert) &&
501
+ isLikeSignedKeyCert(pkeyCerts.provCert)
502
+ );
503
+ }
504
+
505
+ function isValidAnonSenderPolicy(policy: AnonSenderPolicy): boolean {
506
+ return (
507
+ ('object' === typeof policy) && !!policy &&
508
+ ('boolean' === typeof policy.accept) &&
509
+ ('boolean' === typeof policy.acceptWithInvitesOnly) &&
510
+ ('number' === typeof policy.defaultMsgSize) &&
511
+ (policy.defaultMsgSize > 500)
512
+ );
513
+ }
514
+
515
+ function isValidAuthSenderPolicy(policy: AuthSenderPolicy): boolean {
516
+ return (
517
+ ('object' === typeof policy) && !!policy &&
518
+ ('boolean' === typeof policy.applyBlackList) &&
519
+ ('boolean' === typeof policy.acceptFromWhiteListOnly) &&
520
+ ('boolean' === typeof policy.acceptWithInvitesOnly) &&
521
+ ('number' === typeof policy.defaultMsgSize) &&
522
+ (policy.defaultMsgSize > 500)
523
+ );
524
+ }
525
+
526
+ function isValidListWithMsgMaxSizes(
527
+ lst: AuthSenderInvites|AnonSenderInvites|Whitelist
528
+ ): boolean {
529
+ const isOK = ('object' === typeof lst) && !!lst;
530
+ if (!isOK) { return false; }
531
+ for (const inviteOrAddr in lst) {
532
+ const msgMaxSize = lst[inviteOrAddr];
533
+ const isOK = ('number' === typeof msgMaxSize) && (msgMaxSize > 500);
534
+ if (!isOK) { return false; }
535
+ }
536
+ return true;
537
+ }
538
+
539
+ function isValidBlacklist(lst: Blacklist): boolean {
540
+ return ('object' === typeof lst) && !!lst;
541
+ }
542
+
543
+
544
+ class ObjFiles {
545
+
546
+ private cache: TimeWindowCache<string, Map<string, ObjVersionFile>>;
547
+
548
+ constructor(
549
+ cachePeriodMillis: number,
550
+ public deliveryFolder: string,
551
+ public readyMsgsFolder: string
552
+ ) {
553
+ this.cache = new TimeWindowCache(cachePeriodMillis);
554
+ Object.freeze(this);
555
+ }
556
+
557
+ private getCached(msgId: string, objId: string): ObjVersionFile|undefined {
558
+ const msgObjs = this.cache.get(msgId);
559
+ return (msgObjs ? msgObjs.get(objId) : undefined);
560
+ }
561
+
562
+ private setIntoCache(
563
+ msgId: string, objId: string, obj: ObjVersionFile
564
+ ): void {
565
+ let msgObjs = this.cache.get(msgId);
566
+ if (!msgObjs) {
567
+ msgObjs = new Map();
568
+ this.cache.set(msgId, msgObjs);
569
+ }
570
+ msgObjs.set(objId, obj);
571
+ }
572
+
573
+ async forNewFile(
574
+ msgId: string, objId: string
575
+ ): Promise<ObjVersionFile> {
576
+ const path = this.objFileWritingPath(msgId, objId);
577
+ const objFile = await ObjVersionFile.createNew(path)
578
+ .catch((exc: fs.FileException) => {
579
+ if (exc.alreadyExists) { throw SC.OBJ_EXIST; }
580
+ throw exc;
581
+ });
582
+ this.setIntoCache(msgId, objId, objFile);
583
+ return objFile;
584
+ }
585
+
586
+ async forExistingFile(
587
+ msgId: string, objId: string, forWriting = false
588
+ ): Promise<ObjVersionFile> {
589
+ let objFile = this.getCached(msgId, objId);
590
+ if (!objFile) {
591
+ const path = (forWriting ?
592
+ this.objFileWritingPath(msgId, objId) :
593
+ this.objFileReadingPath(msgId, objId));
594
+ objFile = await ObjVersionFile.forExisting(path)
595
+ .catch((exc: fs.FileException) => {
596
+ if (exc.notFound) { throw SC.OBJ_UNKNOWN; }
597
+ throw exc;
598
+ });
599
+ this.setIntoCache(msgId, objId, objFile);
600
+ }
601
+ return objFile;
602
+ }
603
+
604
+ private objFileWritingPath(msgId: string, objId: string): string {
605
+ return join(this.deliveryFolder, msgId, objId);
606
+ }
607
+
608
+ private objFileReadingPath(msgId: string, objId: string): string {
609
+ return join(this.readyMsgsFolder, msgId, objId);
610
+ }
611
+
612
+ changeToReadingPathsInMsg(msgId: string): void {
613
+ const msgObjs = this.cache.get(msgId);
614
+ if (!msgObjs) { return; }
615
+ for (const [ objId, obj ] of msgObjs.entries()) {
616
+ obj.changePathWithoutFileMove(this.objFileReadingPath(msgId, objId));
617
+ }
618
+ }
619
+
620
+ uncache(msgId: string): void {
621
+ this.cache.delete(msgId);
622
+ }
623
+
624
+ }
625
+ Object.freeze(ObjFiles.prototype);
626
+ Object.freeze(ObjFiles);
627
+
628
+ class MsgMetas {
629
+
630
+ private cache: TimeWindowCache<string|null, MsgMeta>;
631
+ private saveProcs = new NamedProcs();
632
+
633
+ constructor(
634
+ cachePeriodMillis: number,
635
+ public deliveryFolder: string,
636
+ public readyMsgsFolder: string
637
+ ) {
638
+ this.cache = new TimeWindowCache(cachePeriodMillis);
639
+ Object.freeze(this);
640
+ }
641
+
642
+ async get(msgId: string, completeMsg: boolean): Promise<MsgMeta> {
643
+ let meta = this.cache.get(msgId);
644
+ if (meta) {
645
+ if ((meta.deliveryCompletion && !completeMsg)
646
+ || (!meta.deliveryCompletion && completeMsg)) {
647
+ throw SC.MSG_UNKNOWN;
648
+ }
649
+ } else {
650
+ meta = await this.fromFile(msgId, completeMsg);
651
+ this.cache.set(msgId, meta);
652
+ }
653
+ return meta;
654
+ }
655
+
656
+ private async fromFile(
657
+ msgId: string, completeMsg: boolean
658
+ ): Promise<MsgMeta> {
659
+ const filePath = join(
660
+ (completeMsg ? this.readyMsgsFolder : this.deliveryFolder),
661
+ msgId, META_FILE);
662
+ const str = await fs.readFile(filePath, { encoding: 'utf8', flag: 'r' })
663
+ .catch((exc: fs.FileException) => {
664
+ if (exc.notFound) {
665
+ throw SC.MSG_UNKNOWN;
666
+ }
667
+ throw exc;
668
+ });
669
+ try {
670
+ return JSON.parse(str) as MsgMeta;
671
+ } catch (err) {
672
+ throw errWithCause(err, `Can't parse content of message meta file`);
673
+ }
674
+ }
675
+
676
+ async set(msgId: string, meta: MsgMeta): Promise<void> {
677
+ this.cache.set(msgId, meta);
678
+ await this.saveToFile(msgId, meta);
679
+ }
680
+
681
+ private async saveToFile(msgId: string, meta: MsgMeta): Promise<void> {
682
+ const filePath = join(this.deliveryFolder, msgId, META_FILE);
683
+ await this.saveProcs.startOrChain(msgId, () => fs.writeFile(
684
+ filePath, JSON.stringify(meta), { encoding: 'utf8', flag: 'w' }));
685
+ }
686
+
687
+ uncache(msgId: string): void {
688
+ this.cache.delete(msgId);
689
+ }
690
+
691
+ }
692
+ Object.freeze(MsgMetas.prototype);
693
+ Object.freeze(MsgMetas);
694
+
695
+
696
+ Object.freeze(exports);