@protontech/drive-sdk 0.0.13 → 0.1.1

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 (496) hide show
  1. package/dist/cache/index.d.ts +1 -0
  2. package/dist/cache/index.js +3 -1
  3. package/dist/cache/index.js.map +1 -1
  4. package/dist/cache/memoryCache.d.ts +1 -1
  5. package/dist/cache/memoryCache.js +0 -1
  6. package/dist/cache/memoryCache.js.map +1 -1
  7. package/dist/cache/memoryCache.test.js +2 -4
  8. package/dist/cache/memoryCache.test.js.map +1 -1
  9. package/dist/cache/nullCache.d.ts +14 -0
  10. package/dist/cache/nullCache.js +36 -0
  11. package/dist/cache/nullCache.js.map +1 -0
  12. package/dist/config.d.ts +16 -1
  13. package/dist/config.js +1 -1
  14. package/dist/config.js.map +1 -1
  15. package/dist/crypto/driveCrypto.d.ts +2 -5
  16. package/dist/crypto/driveCrypto.js +7 -12
  17. package/dist/crypto/driveCrypto.js.map +1 -1
  18. package/dist/crypto/driveCrypto.test.js +14 -14
  19. package/dist/crypto/openPGPCrypto.js +5 -3
  20. package/dist/crypto/openPGPCrypto.js.map +1 -1
  21. package/dist/diagnostic/eventsGenerator.d.ts +14 -0
  22. package/dist/diagnostic/eventsGenerator.js +49 -0
  23. package/dist/diagnostic/eventsGenerator.js.map +1 -0
  24. package/dist/diagnostic/httpClient.d.ts +16 -0
  25. package/dist/diagnostic/httpClient.js +81 -0
  26. package/dist/diagnostic/httpClient.js.map +1 -0
  27. package/dist/diagnostic/index.d.ts +10 -0
  28. package/dist/diagnostic/index.js +35 -0
  29. package/dist/diagnostic/index.js.map +1 -0
  30. package/dist/diagnostic/integrityVerificationStream.d.ts +21 -0
  31. package/dist/diagnostic/integrityVerificationStream.js +56 -0
  32. package/dist/diagnostic/integrityVerificationStream.js.map +1 -0
  33. package/dist/diagnostic/interface.d.ts +102 -0
  34. package/dist/diagnostic/interface.js +3 -0
  35. package/dist/diagnostic/interface.js.map +1 -0
  36. package/dist/diagnostic/sdkDiagnostic.d.ts +22 -0
  37. package/dist/diagnostic/sdkDiagnostic.js +222 -0
  38. package/dist/diagnostic/sdkDiagnostic.js.map +1 -0
  39. package/dist/diagnostic/sdkDiagnosticFull.d.ts +18 -0
  40. package/dist/diagnostic/sdkDiagnosticFull.js +35 -0
  41. package/dist/diagnostic/sdkDiagnosticFull.js.map +1 -0
  42. package/dist/diagnostic/telemetry.d.ts +25 -0
  43. package/dist/diagnostic/telemetry.js +70 -0
  44. package/dist/diagnostic/telemetry.js.map +1 -0
  45. package/dist/diagnostic/zipGenerators.d.ts +9 -0
  46. package/dist/diagnostic/zipGenerators.js +64 -0
  47. package/dist/diagnostic/zipGenerators.js.map +1 -0
  48. package/dist/diagnostic/zipGenerators.test.js +144 -0
  49. package/dist/diagnostic/zipGenerators.test.js.map +1 -0
  50. package/dist/errors.d.ts +2 -1
  51. package/dist/errors.js +3 -1
  52. package/dist/errors.js.map +1 -1
  53. package/dist/interface/config.d.ts +26 -0
  54. package/dist/interface/config.js +3 -0
  55. package/dist/interface/config.js.map +1 -0
  56. package/dist/interface/download.d.ts +2 -2
  57. package/dist/interface/events.d.ts +58 -20
  58. package/dist/interface/events.js +11 -1
  59. package/dist/interface/events.js.map +1 -1
  60. package/dist/interface/httpClient.d.ts +0 -14
  61. package/dist/interface/index.d.ts +11 -7
  62. package/dist/interface/index.js +2 -2
  63. package/dist/interface/index.js.map +1 -1
  64. package/dist/interface/nodes.d.ts +9 -0
  65. package/dist/interface/nodes.js.map +1 -1
  66. package/dist/interface/result.js.map +1 -1
  67. package/dist/interface/sharing.d.ts +2 -0
  68. package/dist/interface/sharing.js.map +1 -1
  69. package/dist/interface/telemetry.js +0 -8
  70. package/dist/interface/telemetry.js.map +1 -1
  71. package/dist/interface/thumbnail.js.map +1 -1
  72. package/dist/interface/upload.d.ts +7 -1
  73. package/dist/internal/apiService/apiService.d.ts +1 -1
  74. package/dist/internal/apiService/apiService.js +7 -11
  75. package/dist/internal/apiService/apiService.js.map +1 -1
  76. package/dist/internal/apiService/apiService.test.js +55 -48
  77. package/dist/internal/apiService/apiService.test.js.map +1 -1
  78. package/dist/internal/apiService/coreTypes.d.ts +2356 -2356
  79. package/dist/internal/apiService/driveTypes.d.ts +1680 -1680
  80. package/dist/internal/apiService/errors.js +14 -8
  81. package/dist/internal/apiService/errors.js.map +1 -1
  82. package/dist/internal/apiService/errors.test.js +17 -12
  83. package/dist/internal/apiService/errors.test.js.map +1 -1
  84. package/dist/internal/apiService/transformers.d.ts +1 -1
  85. package/dist/internal/apiService/transformers.js +1 -1
  86. package/dist/internal/asyncIteratorMap.test.js +2 -2
  87. package/dist/internal/asyncIteratorMap.test.js.map +1 -1
  88. package/dist/internal/asyncIteratorRace.d.ts +13 -0
  89. package/dist/internal/asyncIteratorRace.js +59 -0
  90. package/dist/internal/asyncIteratorRace.js.map +1 -0
  91. package/dist/internal/asyncIteratorRace.test.d.ts +1 -0
  92. package/dist/internal/asyncIteratorRace.test.js +119 -0
  93. package/dist/internal/asyncIteratorRace.test.js.map +1 -0
  94. package/dist/internal/batch.d.ts +1 -0
  95. package/dist/internal/batch.js +12 -0
  96. package/dist/internal/batch.js.map +1 -0
  97. package/dist/internal/batch.test.d.ts +1 -0
  98. package/dist/internal/batch.test.js +41 -0
  99. package/dist/internal/batch.test.js.map +1 -0
  100. package/dist/internal/batchLoading.js.map +1 -1
  101. package/dist/internal/batchLoading.test.js +13 -13
  102. package/dist/internal/batchLoading.test.js.map +1 -1
  103. package/dist/internal/devices/apiService.d.ts +3 -3
  104. package/dist/internal/devices/apiService.js +2 -2
  105. package/dist/internal/devices/apiService.js.map +1 -1
  106. package/dist/internal/devices/cryptoService.js +1 -2
  107. package/dist/internal/devices/cryptoService.js.map +1 -1
  108. package/dist/internal/devices/index.d.ts +5 -5
  109. package/dist/internal/devices/index.js.map +1 -1
  110. package/dist/internal/devices/interface.d.ts +3 -3
  111. package/dist/internal/devices/manager.js +2 -2
  112. package/dist/internal/devices/manager.js.map +1 -1
  113. package/dist/internal/devices/manager.test.js +38 -7
  114. package/dist/internal/devices/manager.test.js.map +1 -1
  115. package/dist/internal/download/apiService.d.ts +4 -4
  116. package/dist/internal/download/apiService.js +32 -32
  117. package/dist/internal/download/apiService.js.map +1 -1
  118. package/dist/internal/download/cryptoService.d.ts +4 -4
  119. package/dist/internal/download/cryptoService.js +6 -5
  120. package/dist/internal/download/cryptoService.js.map +1 -1
  121. package/dist/internal/download/fileDownloader.d.ts +6 -6
  122. package/dist/internal/download/fileDownloader.js +3 -2
  123. package/dist/internal/download/fileDownloader.js.map +1 -1
  124. package/dist/internal/download/fileDownloader.test.js +1 -1
  125. package/dist/internal/download/fileDownloader.test.js.map +1 -1
  126. package/dist/internal/download/index.d.ts +5 -5
  127. package/dist/internal/download/index.js +5 -5
  128. package/dist/internal/download/index.js.map +1 -1
  129. package/dist/internal/download/interface.d.ts +3 -4
  130. package/dist/internal/download/telemetry.d.ts +3 -3
  131. package/dist/internal/download/telemetry.js +4 -2
  132. package/dist/internal/download/telemetry.js.map +1 -1
  133. package/dist/internal/download/telemetry.test.js +8 -8
  134. package/dist/internal/download/telemetry.test.js.map +1 -1
  135. package/dist/internal/download/thumbnailDownloader.d.ts +4 -4
  136. package/dist/internal/download/thumbnailDownloader.js +6 -6
  137. package/dist/internal/download/thumbnailDownloader.js.map +1 -1
  138. package/dist/internal/download/thumbnailDownloader.test.js.map +1 -1
  139. package/dist/internal/errors.d.ts +1 -1
  140. package/dist/internal/errors.js +1 -3
  141. package/dist/internal/errors.js.map +1 -1
  142. package/dist/internal/events/apiService.d.ts +5 -7
  143. package/dist/internal/events/apiService.js +19 -22
  144. package/dist/internal/events/apiService.js.map +1 -1
  145. package/dist/internal/events/coreEventManager.d.ts +9 -12
  146. package/dist/internal/events/coreEventManager.js +19 -36
  147. package/dist/internal/events/coreEventManager.js.map +1 -1
  148. package/dist/internal/events/coreEventManager.test.d.ts +1 -0
  149. package/dist/internal/events/coreEventManager.test.js +87 -0
  150. package/dist/internal/events/coreEventManager.test.js.map +1 -0
  151. package/dist/internal/events/eventManager.d.ts +11 -36
  152. package/dist/internal/events/eventManager.js +59 -106
  153. package/dist/internal/events/eventManager.js.map +1 -1
  154. package/dist/internal/events/eventManager.test.js +177 -83
  155. package/dist/internal/events/eventManager.test.js.map +1 -1
  156. package/dist/internal/events/index.d.ts +16 -36
  157. package/dist/internal/events/index.js +56 -72
  158. package/dist/internal/events/index.js.map +1 -1
  159. package/dist/internal/events/interface.d.ts +59 -14
  160. package/dist/internal/events/interface.js +12 -3
  161. package/dist/internal/events/interface.js.map +1 -1
  162. package/dist/internal/events/volumeEventManager.d.ts +9 -19
  163. package/dist/internal/events/volumeEventManager.js +58 -45
  164. package/dist/internal/events/volumeEventManager.js.map +1 -1
  165. package/dist/internal/events/volumeEventManager.test.d.ts +1 -0
  166. package/dist/internal/events/volumeEventManager.test.js +203 -0
  167. package/dist/internal/events/volumeEventManager.test.js.map +1 -0
  168. package/dist/internal/nodes/apiService.d.ts +4 -3
  169. package/dist/internal/nodes/apiService.js +36 -15
  170. package/dist/internal/nodes/apiService.js.map +1 -1
  171. package/dist/internal/nodes/apiService.test.js +60 -41
  172. package/dist/internal/nodes/apiService.test.js.map +1 -1
  173. package/dist/internal/nodes/cache.d.ts +14 -5
  174. package/dist/internal/nodes/cache.js +31 -7
  175. package/dist/internal/nodes/cache.js.map +1 -1
  176. package/dist/internal/nodes/cache.test.js +31 -9
  177. package/dist/internal/nodes/cache.test.js.map +1 -1
  178. package/dist/internal/nodes/cryptoCache.d.ts +2 -2
  179. package/dist/internal/nodes/cryptoCache.js.map +1 -1
  180. package/dist/internal/nodes/cryptoCache.test.js +24 -4
  181. package/dist/internal/nodes/cryptoCache.test.js.map +1 -1
  182. package/dist/internal/nodes/cryptoService.d.ts +4 -4
  183. package/dist/internal/nodes/cryptoService.js +11 -17
  184. package/dist/internal/nodes/cryptoService.js.map +1 -1
  185. package/dist/internal/nodes/cryptoService.test.js +320 -241
  186. package/dist/internal/nodes/cryptoService.test.js.map +1 -1
  187. package/dist/internal/nodes/events.d.ts +8 -84
  188. package/dist/internal/nodes/events.js +43 -217
  189. package/dist/internal/nodes/events.js.map +1 -1
  190. package/dist/internal/nodes/events.test.js +35 -279
  191. package/dist/internal/nodes/events.test.js.map +1 -1
  192. package/dist/internal/nodes/extendedAttributes.d.ts +1 -1
  193. package/dist/internal/nodes/extendedAttributes.js +3 -1
  194. package/dist/internal/nodes/extendedAttributes.js.map +1 -1
  195. package/dist/internal/nodes/extendedAttributes.test.js +7 -10
  196. package/dist/internal/nodes/extendedAttributes.test.js.map +1 -1
  197. package/dist/internal/nodes/index.d.ts +12 -13
  198. package/dist/internal/nodes/index.js +5 -5
  199. package/dist/internal/nodes/index.js.map +1 -1
  200. package/dist/internal/nodes/index.test.js +24 -32
  201. package/dist/internal/nodes/index.test.js.map +1 -1
  202. package/dist/internal/nodes/interface.d.ts +2 -2
  203. package/dist/internal/nodes/nodesAccess.d.ts +22 -7
  204. package/dist/internal/nodes/nodesAccess.js +65 -16
  205. package/dist/internal/nodes/nodesAccess.js.map +1 -1
  206. package/dist/internal/nodes/nodesAccess.test.js +165 -101
  207. package/dist/internal/nodes/nodesAccess.test.js.map +1 -1
  208. package/dist/internal/nodes/nodesManagement.d.ts +7 -9
  209. package/dist/internal/nodes/nodesManagement.js +21 -33
  210. package/dist/internal/nodes/nodesManagement.js.map +1 -1
  211. package/dist/internal/nodes/nodesManagement.test.js +42 -21
  212. package/dist/internal/nodes/nodesManagement.test.js.map +1 -1
  213. package/dist/internal/nodes/nodesRevisions.d.ts +4 -4
  214. package/dist/internal/nodes/nodesRevisions.js.map +1 -1
  215. package/dist/internal/photos/albums.d.ts +3 -3
  216. package/dist/internal/photos/albums.js.map +1 -1
  217. package/dist/internal/photos/apiService.d.ts +1 -1
  218. package/dist/internal/photos/apiService.js +3 -6
  219. package/dist/internal/photos/apiService.js.map +1 -1
  220. package/dist/internal/photos/cache.d.ts +1 -1
  221. package/dist/internal/photos/index.d.ts +5 -5
  222. package/dist/internal/photos/index.js.map +1 -1
  223. package/dist/internal/photos/interface.d.ts +2 -2
  224. package/dist/internal/photos/photosTimeline.d.ts +3 -3
  225. package/dist/internal/photos/photosTimeline.js +1 -2
  226. package/dist/internal/photos/photosTimeline.js.map +1 -1
  227. package/dist/internal/sdkEvents.d.ts +1 -1
  228. package/dist/internal/sdkEvents.js +2 -7
  229. package/dist/internal/sdkEvents.js.map +1 -1
  230. package/dist/internal/sdkEvents.test.js +8 -8
  231. package/dist/internal/shares/apiService.d.ts +2 -2
  232. package/dist/internal/shares/apiService.js +5 -3
  233. package/dist/internal/shares/apiService.js.map +1 -1
  234. package/dist/internal/shares/cache.d.ts +4 -2
  235. package/dist/internal/shares/cache.js +14 -6
  236. package/dist/internal/shares/cache.js.map +1 -1
  237. package/dist/internal/shares/cache.test.js.map +1 -1
  238. package/dist/internal/shares/cryptoCache.d.ts +2 -2
  239. package/dist/internal/shares/cryptoCache.test.js +8 -2
  240. package/dist/internal/shares/cryptoCache.test.js.map +1 -1
  241. package/dist/internal/shares/cryptoService.d.ts +3 -3
  242. package/dist/internal/shares/cryptoService.js.map +1 -1
  243. package/dist/internal/shares/cryptoService.test.js +42 -42
  244. package/dist/internal/shares/cryptoService.test.js.map +1 -1
  245. package/dist/internal/shares/index.d.ts +4 -4
  246. package/dist/internal/shares/index.js.map +1 -1
  247. package/dist/internal/shares/interface.d.ts +2 -2
  248. package/dist/internal/shares/manager.d.ts +8 -7
  249. package/dist/internal/shares/manager.js +3 -0
  250. package/dist/internal/shares/manager.js.map +1 -1
  251. package/dist/internal/shares/manager.test.js +71 -63
  252. package/dist/internal/shares/manager.test.js.map +1 -1
  253. package/dist/internal/sharing/apiService.d.ts +4 -4
  254. package/dist/internal/sharing/apiService.js +5 -3
  255. package/dist/internal/sharing/apiService.js.map +1 -1
  256. package/dist/internal/sharing/cache.d.ts +1 -1
  257. package/dist/internal/sharing/cache.test.js +33 -33
  258. package/dist/internal/sharing/cryptoService.d.ts +3 -3
  259. package/dist/internal/sharing/cryptoService.js +3 -4
  260. package/dist/internal/sharing/cryptoService.js.map +1 -1
  261. package/dist/internal/sharing/cryptoService.test.js +39 -39
  262. package/dist/internal/sharing/cryptoService.test.js.map +1 -1
  263. package/dist/internal/sharing/events.d.ts +24 -56
  264. package/dist/internal/sharing/events.js +45 -138
  265. package/dist/internal/sharing/events.js.map +1 -1
  266. package/dist/internal/sharing/events.test.js +85 -189
  267. package/dist/internal/sharing/events.test.js.map +1 -1
  268. package/dist/internal/sharing/index.d.ts +8 -9
  269. package/dist/internal/sharing/index.js +5 -5
  270. package/dist/internal/sharing/index.js.map +1 -1
  271. package/dist/internal/sharing/interface.d.ts +8 -4
  272. package/dist/internal/sharing/sharingAccess.d.ts +6 -6
  273. package/dist/internal/sharing/sharingAccess.js +8 -4
  274. package/dist/internal/sharing/sharingAccess.js.map +1 -1
  275. package/dist/internal/sharing/sharingAccess.test.js +45 -39
  276. package/dist/internal/sharing/sharingAccess.test.js.map +1 -1
  277. package/dist/internal/sharing/sharingManagement.d.ts +5 -6
  278. package/dist/internal/sharing/sharingManagement.js +12 -16
  279. package/dist/internal/sharing/sharingManagement.js.map +1 -1
  280. package/dist/internal/sharing/sharingManagement.test.js +305 -286
  281. package/dist/internal/sharing/sharingManagement.test.js.map +1 -1
  282. package/dist/internal/uids.js.map +1 -1
  283. package/dist/internal/upload/apiService.d.ts +5 -6
  284. package/dist/internal/upload/apiService.js +8 -5
  285. package/dist/internal/upload/apiService.js.map +1 -1
  286. package/dist/internal/upload/blockVerifier.d.ts +3 -3
  287. package/dist/internal/upload/blockVerifier.js +1 -1
  288. package/dist/internal/upload/blockVerifier.js.map +1 -1
  289. package/dist/internal/upload/chunkStreamReader.test.js +6 -6
  290. package/dist/internal/upload/cryptoService.d.ts +4 -4
  291. package/dist/internal/upload/cryptoService.js +4 -4
  292. package/dist/internal/upload/cryptoService.js.map +1 -1
  293. package/dist/internal/upload/digests.js.map +1 -1
  294. package/dist/internal/upload/fileUploader.d.ts +6 -6
  295. package/dist/internal/upload/fileUploader.js.map +1 -1
  296. package/dist/internal/upload/fileUploader.test.js.map +1 -1
  297. package/dist/internal/upload/index.d.ts +6 -6
  298. package/dist/internal/upload/index.js +3 -3
  299. package/dist/internal/upload/index.js.map +1 -1
  300. package/dist/internal/upload/interface.d.ts +5 -3
  301. package/dist/internal/upload/manager.d.ts +8 -8
  302. package/dist/internal/upload/manager.js +23 -52
  303. package/dist/internal/upload/manager.js.map +1 -1
  304. package/dist/internal/upload/manager.test.js +185 -147
  305. package/dist/internal/upload/manager.test.js.map +1 -1
  306. package/dist/internal/upload/streamUploader.d.ts +6 -6
  307. package/dist/internal/upload/streamUploader.js +9 -8
  308. package/dist/internal/upload/streamUploader.js.map +1 -1
  309. package/dist/internal/upload/streamUploader.test.js +17 -12
  310. package/dist/internal/upload/streamUploader.test.js.map +1 -1
  311. package/dist/internal/upload/telemetry.d.ts +3 -3
  312. package/dist/internal/upload/telemetry.js +5 -3
  313. package/dist/internal/upload/telemetry.js.map +1 -1
  314. package/dist/internal/upload/telemetry.test.js +8 -8
  315. package/dist/internal/upload/telemetry.test.js.map +1 -1
  316. package/dist/protonDriveClient.d.ts +27 -170
  317. package/dist/protonDriveClient.js +37 -198
  318. package/dist/protonDriveClient.js.map +1 -1
  319. package/dist/protonDrivePhotosClient.js +3 -2
  320. package/dist/protonDrivePhotosClient.js.map +1 -1
  321. package/dist/telemetry.js +18 -15
  322. package/dist/telemetry.js.map +1 -1
  323. package/dist/tests/logger.js.map +1 -1
  324. package/dist/tests/telemetry.d.ts +1 -1
  325. package/dist/transformers.js +4 -2
  326. package/dist/transformers.js.map +1 -1
  327. package/package.json +3 -3
  328. package/src/cache/index.ts +1 -0
  329. package/src/cache/interface.ts +22 -22
  330. package/src/cache/memoryCache.test.ts +7 -7
  331. package/src/cache/memoryCache.ts +5 -5
  332. package/src/cache/nullCache.ts +38 -0
  333. package/src/config.ts +17 -2
  334. package/src/crypto/driveCrypto.test.ts +15 -15
  335. package/src/crypto/driveCrypto.ts +120 -156
  336. package/src/crypto/hmac.ts +1 -1
  337. package/src/crypto/interface.ts +63 -72
  338. package/src/crypto/openPGPCrypto.ts +76 -94
  339. package/src/crypto/utils.ts +1 -1
  340. package/src/diagnostic/eventsGenerator.ts +48 -0
  341. package/src/diagnostic/httpClient.ts +84 -0
  342. package/src/diagnostic/index.ts +40 -0
  343. package/src/diagnostic/integrityVerificationStream.ts +55 -0
  344. package/src/diagnostic/interface.ts +158 -0
  345. package/src/diagnostic/sdkDiagnostic.ts +249 -0
  346. package/src/diagnostic/sdkDiagnosticFull.ts +37 -0
  347. package/src/diagnostic/telemetry.ts +74 -0
  348. package/src/diagnostic/zipGenerators.test.ts +177 -0
  349. package/src/diagnostic/zipGenerators.ts +70 -0
  350. package/src/errors.ts +25 -22
  351. package/src/index.ts +3 -3
  352. package/src/interface/account.ts +10 -10
  353. package/src/interface/author.ts +6 -6
  354. package/src/interface/config.ts +28 -0
  355. package/src/interface/devices.ts +6 -6
  356. package/src/interface/download.ts +12 -9
  357. package/src/interface/events.ts +76 -25
  358. package/src/interface/httpClient.ts +11 -27
  359. package/src/interface/index.ts +81 -20
  360. package/src/interface/nodes.ts +67 -60
  361. package/src/interface/result.ts +1 -3
  362. package/src/interface/sharing.ts +60 -56
  363. package/src/interface/telemetry.ts +74 -74
  364. package/src/interface/thumbnail.ts +5 -6
  365. package/src/interface/upload.ts +25 -11
  366. package/src/internal/apiService/apiService.test.ts +109 -76
  367. package/src/internal/apiService/apiService.ts +40 -26
  368. package/src/internal/apiService/coreTypes.ts +2474 -2463
  369. package/src/internal/apiService/driveTypes.ts +1868 -1822
  370. package/src/internal/apiService/errorCodes.ts +4 -4
  371. package/src/internal/apiService/errors.test.ts +25 -23
  372. package/src/internal/apiService/errors.ts +15 -9
  373. package/src/internal/apiService/index.ts +1 -1
  374. package/src/internal/apiService/transformers.ts +2 -2
  375. package/src/internal/asyncIteratorMap.test.ts +4 -4
  376. package/src/internal/asyncIteratorMap.ts +1 -1
  377. package/src/internal/asyncIteratorRace.test.ts +149 -0
  378. package/src/internal/asyncIteratorRace.ts +79 -0
  379. package/src/internal/batch.test.ts +50 -0
  380. package/src/internal/batch.ts +9 -0
  381. package/src/internal/batchLoading.test.ts +13 -14
  382. package/src/internal/batchLoading.ts +8 -8
  383. package/src/internal/devices/apiService.ts +58 -51
  384. package/src/internal/devices/cryptoService.ts +22 -17
  385. package/src/internal/devices/index.ts +17 -10
  386. package/src/internal/devices/interface.ts +21 -12
  387. package/src/internal/devices/manager.test.ts +40 -9
  388. package/src/internal/devices/manager.ts +3 -3
  389. package/src/internal/download/apiService.ts +72 -52
  390. package/src/internal/download/cryptoService.ts +34 -18
  391. package/src/internal/download/fileDownloader.test.ts +25 -9
  392. package/src/internal/download/fileDownloader.ts +38 -20
  393. package/src/internal/download/index.ts +19 -19
  394. package/src/internal/download/interface.ts +19 -20
  395. package/src/internal/download/queue.ts +3 -3
  396. package/src/internal/download/telemetry.test.ts +11 -11
  397. package/src/internal/download/telemetry.ts +24 -14
  398. package/src/internal/download/thumbnailDownloader.test.ts +11 -6
  399. package/src/internal/download/thumbnailDownloader.ts +43 -32
  400. package/src/internal/errors.ts +7 -5
  401. package/src/internal/events/apiService.ts +46 -36
  402. package/src/internal/events/coreEventManager.test.ts +101 -0
  403. package/src/internal/events/coreEventManager.ts +26 -48
  404. package/src/internal/events/eventManager.test.ts +211 -93
  405. package/src/internal/events/eventManager.ts +72 -117
  406. package/src/internal/events/index.ts +71 -91
  407. package/src/internal/events/interface.ts +92 -29
  408. package/src/internal/events/volumeEventManager.test.ts +239 -0
  409. package/src/internal/events/volumeEventManager.ts +68 -57
  410. package/src/internal/nodes/apiService.test.ts +197 -147
  411. package/src/internal/nodes/apiService.ts +288 -174
  412. package/src/internal/nodes/cache.test.ts +48 -20
  413. package/src/internal/nodes/cache.ts +79 -45
  414. package/src/internal/nodes/cryptoCache.test.ts +34 -14
  415. package/src/internal/nodes/cryptoCache.ts +10 -5
  416. package/src/internal/nodes/cryptoService.test.ts +492 -351
  417. package/src/internal/nodes/cryptoService.ts +171 -89
  418. package/src/internal/nodes/events.test.ts +48 -344
  419. package/src/internal/nodes/events.ts +48 -254
  420. package/src/internal/nodes/extendedAttributes.test.ts +28 -24
  421. package/src/internal/nodes/extendedAttributes.ts +20 -15
  422. package/src/internal/nodes/index.test.ts +51 -55
  423. package/src/internal/nodes/index.ts +32 -22
  424. package/src/internal/nodes/interface.ts +44 -31
  425. package/src/internal/nodes/nodesAccess.test.ts +237 -130
  426. package/src/internal/nodes/nodesAccess.ts +113 -50
  427. package/src/internal/nodes/nodesManagement.test.ts +64 -39
  428. package/src/internal/nodes/nodesManagement.ts +51 -62
  429. package/src/internal/nodes/nodesRevisions.ts +7 -7
  430. package/src/internal/nodes/validations.ts +2 -2
  431. package/src/internal/photos/albums.ts +5 -5
  432. package/src/internal/photos/apiService.ts +4 -7
  433. package/src/internal/photos/cache.ts +1 -1
  434. package/src/internal/photos/index.ts +8 -8
  435. package/src/internal/photos/interface.ts +2 -2
  436. package/src/internal/photos/photosTimeline.ts +4 -5
  437. package/src/internal/sdkEvents.test.ts +10 -10
  438. package/src/internal/sdkEvents.ts +5 -13
  439. package/src/internal/shares/apiService.ts +44 -33
  440. package/src/internal/shares/cache.test.ts +6 -4
  441. package/src/internal/shares/cache.ts +25 -14
  442. package/src/internal/shares/cryptoCache.test.ts +17 -11
  443. package/src/internal/shares/cryptoCache.ts +4 -4
  444. package/src/internal/shares/cryptoService.test.ts +72 -74
  445. package/src/internal/shares/cryptoService.ts +48 -23
  446. package/src/internal/shares/index.ts +23 -11
  447. package/src/internal/shares/interface.ts +8 -8
  448. package/src/internal/shares/manager.test.ts +88 -80
  449. package/src/internal/shares/manager.ts +27 -23
  450. package/src/internal/sharing/apiService.ts +283 -175
  451. package/src/internal/sharing/cache.test.ts +35 -35
  452. package/src/internal/sharing/cache.ts +3 -3
  453. package/src/internal/sharing/cryptoService.test.ts +58 -46
  454. package/src/internal/sharing/cryptoService.ts +121 -83
  455. package/src/internal/sharing/events.test.ts +97 -207
  456. package/src/internal/sharing/events.ts +46 -157
  457. package/src/internal/sharing/index.ts +24 -16
  458. package/src/internal/sharing/interface.ts +46 -42
  459. package/src/internal/sharing/sharingAccess.test.ts +71 -65
  460. package/src/internal/sharing/sharingAccess.ts +39 -21
  461. package/src/internal/sharing/sharingManagement.test.ts +405 -335
  462. package/src/internal/sharing/sharingManagement.ts +144 -75
  463. package/src/internal/uids.ts +1 -1
  464. package/src/internal/upload/apiService.ts +168 -119
  465. package/src/internal/upload/blockVerifier.ts +8 -6
  466. package/src/internal/upload/chunkStreamReader.test.ts +7 -7
  467. package/src/internal/upload/cryptoService.ts +42 -36
  468. package/src/internal/upload/digests.ts +2 -2
  469. package/src/internal/upload/fileUploader.test.ts +15 -3
  470. package/src/internal/upload/fileUploader.ts +39 -17
  471. package/src/internal/upload/index.ts +17 -18
  472. package/src/internal/upload/interface.ts +79 -77
  473. package/src/internal/upload/manager.test.ts +222 -175
  474. package/src/internal/upload/manager.ts +74 -80
  475. package/src/internal/upload/queue.ts +3 -3
  476. package/src/internal/upload/streamUploader.test.ts +40 -27
  477. package/src/internal/upload/streamUploader.ts +87 -71
  478. package/src/internal/upload/telemetry.test.ts +11 -11
  479. package/src/internal/upload/telemetry.ts +25 -15
  480. package/src/internal/wait.test.ts +1 -1
  481. package/src/internal/wait.ts +3 -3
  482. package/src/protonDriveClient.ts +189 -276
  483. package/src/protonDrivePhotosClient.ts +20 -13
  484. package/src/telemetry.ts +60 -52
  485. package/src/tests/logger.ts +1 -1
  486. package/src/tests/telemetry.ts +2 -2
  487. package/src/transformers.ts +27 -21
  488. package/src/version.ts +0 -1
  489. package/dist/internal/events/cache.d.ts +0 -28
  490. package/dist/internal/events/cache.js +0 -67
  491. package/dist/internal/events/cache.js.map +0 -1
  492. package/dist/internal/events/cache.test.js +0 -43
  493. package/dist/internal/events/cache.test.js.map +0 -1
  494. package/src/internal/events/cache.test.ts +0 -47
  495. package/src/internal/events/cache.ts +0 -80
  496. /package/dist/{internal/events/cache.test.d.ts → diagnostic/zipGenerators.test.d.ts} +0 -0
@@ -1,139 +1,257 @@
1
- import { getMockLogger } from "../../tests/logger";
2
- import { NotFoundAPIError } from "../apiService";
3
- import { EventManager } from "./eventManager";
1
+ import { getMockLogger } from '../../tests/logger';
2
+ import { EventManager } from './eventManager';
3
+ import { DriveEvent, DriveEventType, EventSubscription, UnsubscribeFromEventsSourceError } from './interface';
4
4
 
5
5
  jest.useFakeTimers();
6
6
 
7
- describe("EventManager", () => {
8
- let manager: EventManager<string>;
9
-
10
- const getLastEventIdMock = jest.fn();
7
+ const POLLING_INTERVAL = 1;
8
+
9
+ describe('EventManager', () => {
10
+ let manager: EventManager<DriveEvent>;
11
+
12
+ const getLatestEventIdMock = jest.fn();
11
13
  const getEventsMock = jest.fn();
12
- const updateLatestEventIdMock = jest.fn();
13
14
  const listenerMock = jest.fn();
15
+ const mockLogger = getMockLogger();
16
+ const subscriptions: EventSubscription[] = [];
14
17
 
15
18
  beforeEach(() => {
16
- jest.clearAllMocks();
19
+ const mockEventManager = {
20
+ getLogger: () => mockLogger,
21
+ getLatestEventId: getLatestEventIdMock,
22
+ getEvents: getEventsMock,
23
+ };
17
24
 
18
- getLastEventIdMock.mockImplementation(() => Promise.resolve("eventId1"));
19
- getEventsMock.mockImplementation(() => Promise.resolve({
20
- lastEventId: "eventId2",
21
- more: false,
22
- refresh: false,
23
- events: ["event1", "event2"],
24
- }));
25
-
26
- manager = new EventManager(
27
- getMockLogger(),
28
- getLastEventIdMock,
29
- getEventsMock,
30
- updateLatestEventIdMock,
31
- );
32
- manager.addListener(listenerMock);
25
+ manager = new EventManager(mockEventManager as any, POLLING_INTERVAL, null);
26
+ const subscription = manager.addListener(listenerMock);
27
+ subscriptions.push(subscription);
33
28
  });
34
29
 
35
30
  afterEach(async () => {
36
31
  await manager.stop();
32
+ while (subscriptions.length > 0) {
33
+ const subscription = subscriptions.pop();
34
+ subscription?.dispose();
35
+ }
36
+ jest.clearAllMocks();
37
37
  });
38
38
 
39
- it("should get latest event ID on first run only", async () => {
40
- await manager.start();
41
- expect(getLastEventIdMock).toHaveBeenCalledTimes(1);
39
+ it('should start polling when started', async () => {
40
+ getLatestEventIdMock.mockResolvedValue('EventId1');
41
+
42
+ const mockEvents: DriveEvent[][] = [
43
+ [
44
+ {
45
+ type: DriveEventType.FastForward,
46
+ treeEventScopeId: 'volume1',
47
+ eventId: 'EventId2',
48
+ },
49
+ ],
50
+ [
51
+ {
52
+ type: DriveEventType.FastForward,
53
+ treeEventScopeId: 'volume1',
54
+ eventId: 'EventId3',
55
+ },
56
+ ],
57
+ ];
58
+
59
+ getEventsMock
60
+ .mockImplementationOnce(async function* () {
61
+ yield* mockEvents[0];
62
+ })
63
+ .mockImplementationOnce(async function* () {
64
+ yield* mockEvents[1];
65
+ })
66
+ .mockImplementationOnce(async function* () {});
67
+
68
+ expect(getLatestEventIdMock).toHaveBeenCalledTimes(0);
42
69
  expect(getEventsMock).toHaveBeenCalledTimes(0);
43
- expect(listenerMock).toHaveBeenCalledTimes(0);
44
- expect(updateLatestEventIdMock).toHaveBeenCalledTimes(1);
45
- expect(updateLatestEventIdMock).toHaveBeenCalledWith('eventId1');
70
+
71
+ expect(await manager.start()).toBeUndefined();
72
+
73
+ expect(getLatestEventIdMock).toHaveBeenCalledTimes(1);
74
+ expect(getEventsMock).toHaveBeenCalledWith('EventId1');
75
+
76
+ await jest.runOnlyPendingTimersAsync();
77
+ expect(getEventsMock).toHaveBeenCalledTimes(2);
78
+ expect(getEventsMock).toHaveBeenCalledWith('EventId2');
46
79
  });
47
80
 
48
- it("should notify about events in the next run", async () => {
81
+ it('should stop polling when stopped', async () => {
82
+ getLatestEventIdMock.mockResolvedValue('eventId1');
83
+ getEventsMock.mockImplementation(async function* () {
84
+ yield {
85
+ type: DriveEventType.FastForward,
86
+ treeEventScopeId: 'volume1',
87
+ eventId: 'eventId1',
88
+ };
89
+ });
90
+
49
91
  await manager.start();
50
- expect(getLastEventIdMock).toHaveBeenCalledTimes(1);
51
- expect(getEventsMock).toHaveBeenCalledTimes(0);
52
- expect(listenerMock).toHaveBeenCalledTimes(0);
53
- expect(updateLatestEventIdMock).toHaveBeenCalledTimes(1);
54
- expect(updateLatestEventIdMock).toHaveBeenCalledWith('eventId1');
55
- updateLatestEventIdMock.mockClear();
56
92
  await jest.runOnlyPendingTimersAsync();
57
- expect(getEventsMock).toHaveBeenCalledTimes(1);
93
+
94
+ const callsBeforeStop = getEventsMock.mock.calls.length;
95
+ await manager.stop();
96
+ await jest.runOnlyPendingTimersAsync();
97
+
98
+ // Should not have made additional calls after stopping
99
+ expect(getEventsMock).toHaveBeenCalledTimes(callsBeforeStop);
100
+ });
101
+
102
+ it('should notify all listeners when getting events', async () => {
103
+ getLatestEventIdMock.mockResolvedValue('eventId1');
104
+
105
+ const mockEvents: DriveEvent[] = [
106
+ {
107
+ type: DriveEventType.NodeCreated,
108
+ nodeUid: 'node1',
109
+ parentNodeUid: 'parent1',
110
+ isTrashed: false,
111
+ isShared: false,
112
+ treeEventScopeId: 'volume1',
113
+ eventId: 'eventId2',
114
+ },
115
+ ];
116
+
117
+ getEventsMock
118
+ .mockImplementationOnce(async function* () {
119
+ yield* mockEvents;
120
+ })
121
+ .mockImplementation(async function* () {});
122
+
123
+ expect(await manager.start()).toBeUndefined();
124
+ await jest.runOnlyPendingTimersAsync();
58
125
  expect(listenerMock).toHaveBeenCalledTimes(1);
59
- expect(updateLatestEventIdMock).toHaveBeenCalledTimes(1);
60
- expect(updateLatestEventIdMock).toHaveBeenCalledWith('eventId2');
126
+ expect(listenerMock).toHaveBeenNthCalledWith(1, mockEvents[0]);
127
+ });
128
+
129
+ it('should propagate unsubscription errors', async () => {
130
+ getLatestEventIdMock.mockImplementation(() => {
131
+ throw new UnsubscribeFromEventsSourceError('Not found');
132
+ });
133
+
134
+ await expect(manager.start()).rejects.toThrow(UnsubscribeFromEventsSourceError);
135
+
136
+ expect(getLatestEventIdMock).toHaveBeenCalledTimes(1);
137
+ expect(listenerMock).toHaveBeenCalledTimes(0);
138
+ expect(getEventsMock).toHaveBeenCalledTimes(0);
61
139
  });
62
140
 
63
- it("should continue with more events", async () => {
64
- getEventsMock.mockImplementation((lastEventId: string) => Promise.resolve({
65
- lastEventId: lastEventId === "eventId1" ? "eventId2" : "eventId3",
66
- more: lastEventId === "eventId1" ? true : false,
67
- refresh: false,
68
- events: lastEventId === "eventId1" ? ["event1", "event2"] : ["event3"],
69
- }));
141
+ it('should continue processing multiple events', async () => {
142
+ getLatestEventIdMock.mockResolvedValue('eventId1');
143
+
144
+ const mockEvents: DriveEvent[] = [
145
+ {
146
+ type: DriveEventType.NodeCreated,
147
+ nodeUid: 'node1',
148
+ parentNodeUid: 'parent1',
149
+ isTrashed: false,
150
+ isShared: false,
151
+ treeEventScopeId: 'volume1',
152
+ eventId: 'eventId2',
153
+ },
154
+ {
155
+ type: DriveEventType.NodeCreated,
156
+ nodeUid: 'node2',
157
+ parentNodeUid: 'parent1',
158
+ isTrashed: false,
159
+ isShared: false,
160
+ treeEventScopeId: 'volume1',
161
+ eventId: 'eventId3',
162
+ },
163
+ ];
164
+
165
+ getEventsMock
166
+ .mockImplementationOnce(async function* () {
167
+ yield* mockEvents;
168
+ })
169
+ .mockImplementation(async function* () {
170
+ // Empty generator for subsequent calls
171
+ });
172
+
70
173
  await manager.start();
71
174
  await jest.runOnlyPendingTimersAsync();
72
- expect(getEventsMock).toHaveBeenCalledTimes(2);
175
+
73
176
  expect(listenerMock).toHaveBeenCalledTimes(2);
74
- expect(listenerMock).toHaveBeenCalledWith(["event1", "event2"], false);
75
- expect(listenerMock).toHaveBeenCalledWith(["event3"], false);
76
- expect(updateLatestEventIdMock).toHaveBeenCalledTimes(3);
77
- expect(updateLatestEventIdMock).toHaveBeenCalledWith('eventId1');
78
- expect(updateLatestEventIdMock).toHaveBeenCalledWith('eventId2');
79
- expect(updateLatestEventIdMock).toHaveBeenCalledWith('eventId3');
80
- });
177
+ expect(listenerMock).toHaveBeenNthCalledWith(1, mockEvents[0]);
178
+ expect(listenerMock).toHaveBeenNthCalledWith(2, mockEvents[1]);
81
179
 
82
- it("should refresh if event does not exist", async () => {
83
- getEventsMock.mockImplementation(() => Promise.reject(new NotFoundAPIError('Event not found', 2501)));
84
- await manager.start();
180
+ getEventsMock.mockImplementationOnce(async function* () {
181
+ yield* mockEvents;
182
+ });
85
183
  await jest.runOnlyPendingTimersAsync();
86
- expect(getLastEventIdMock).toHaveBeenCalledTimes(2);
87
- expect(listenerMock).toHaveBeenCalledTimes(1);
88
- expect(listenerMock).toHaveBeenCalledWith([], true);
89
- expect(updateLatestEventIdMock).toHaveBeenCalledTimes(1);
90
- expect(updateLatestEventIdMock).toHaveBeenCalledWith('eventId1');
184
+ expect(listenerMock).toHaveBeenCalledTimes(4);
185
+ expect(listenerMock).toHaveBeenNthCalledWith(1, mockEvents[0]);
186
+ expect(listenerMock).toHaveBeenNthCalledWith(2, mockEvents[1]);
91
187
  });
92
188
 
93
- it("should retry on error", async () => {
94
- let index = 0;
95
- getEventsMock.mockImplementation(() => {
96
- index++;
97
- if (index <= 3) {
98
- return Promise.reject(new Error("Error"));
189
+ it('should retry on error with exponential backoff', async () => {
190
+ getLatestEventIdMock.mockResolvedValue('eventId1');
191
+
192
+ let callCount = 0;
193
+ getEventsMock.mockImplementation(async function* () {
194
+ callCount++;
195
+ if (callCount <= 3) {
196
+ throw new Error('Network error');
99
197
  }
100
- return Promise.resolve({
101
- lastEventId: "eventId2",
102
- more: false,
103
- refresh: false,
104
- events: ["event1", "event2"],
105
- });
198
+ yield {
199
+ type: DriveEventType.FastForward,
200
+ treeEventScopeId: 'volume1',
201
+ eventId: 'eventId3',
202
+ };
106
203
  });
107
- await manager.start();
108
- updateLatestEventIdMock.mockClear();
109
204
 
110
- // First failure.
111
- await jest.runOnlyPendingTimersAsync();
112
- expect(listenerMock).toHaveBeenCalledTimes(0);
113
- expect(manager.nextPollTimeout).toBe(30000);
205
+ expect(manager['retryIndex']).toEqual(0);
206
+
207
+ expect(await manager.start()).toBeUndefined();
208
+ expect(getEventsMock).toHaveBeenCalledTimes(1);
209
+ expect(manager['retryIndex']).toEqual(1);
114
210
 
115
- // Second failure.
116
211
  await jest.runOnlyPendingTimersAsync();
117
- expect(listenerMock).toHaveBeenCalledTimes(0);
118
- expect(manager.nextPollTimeout).toBe(60000);
212
+ expect(getEventsMock).toHaveBeenCalledTimes(2);
213
+ expect(manager['retryIndex']).toEqual(2);
119
214
 
120
- // Third failure.
121
215
  await jest.runOnlyPendingTimersAsync();
216
+ expect(manager['retryIndex']).toEqual(3);
217
+
122
218
  expect(listenerMock).toHaveBeenCalledTimes(0);
123
- expect(manager.nextPollTimeout).toBe(90000);
124
219
 
125
- // And now it passes.
126
220
  await jest.runOnlyPendingTimersAsync();
127
221
  expect(listenerMock).toHaveBeenCalledTimes(1);
128
- expect(listenerMock).toHaveBeenCalledWith(["event1", "event2"], false);
129
- expect(updateLatestEventIdMock).toHaveBeenCalledTimes(1);
130
- expect(updateLatestEventIdMock).toHaveBeenCalledWith('eventId2');
222
+ // After success, retry index should reset
223
+ expect(manager['retryIndex']).toEqual(0);
131
224
  });
132
225
 
133
- it("should stop polling", async () => {
134
- await manager.start();
226
+ it('should stop polling when stopped immediately', async () => {
227
+ getLatestEventIdMock.mockResolvedValue('eventId1');
228
+ getEventsMock.mockImplementation(async function* () {
229
+ yield {
230
+ type: DriveEventType.FastForward,
231
+ treeEventScopeId: 'volume1',
232
+ eventId: 'eventId1',
233
+ };
234
+ });
235
+
236
+ expect(await manager.start()).toBeUndefined();
237
+ expect(getEventsMock).toHaveBeenCalledTimes(1);
135
238
  await manager.stop();
136
239
  await jest.runOnlyPendingTimersAsync();
137
- expect(getEventsMock).toHaveBeenCalledTimes(0);
240
+
241
+ // getEvents should have been called once during start, but not again after stop
242
+ expect(getEventsMock).toHaveBeenCalledTimes(1);
243
+ });
244
+
245
+ it('should handle empty event streams', async () => {
246
+ getLatestEventIdMock.mockResolvedValue('eventId1');
247
+
248
+ getEventsMock.mockImplementation(async function* () {
249
+ // Empty generator - no events
250
+ });
251
+
252
+ await manager.start();
253
+ await jest.runOnlyPendingTimersAsync();
254
+
255
+ expect(listenerMock).toHaveBeenCalledTimes(0);
138
256
  });
139
257
  });
@@ -1,168 +1,123 @@
1
- import { Logger } from "../../interface";
2
- import { NotFoundAPIError } from "../apiService";
3
- import { Events } from "./interface";
1
+ import { Logger } from '../../interface';
2
+ import { EventManagerInterface, Event, EventSubscription } from './interface';
4
3
 
5
- const DEFAULT_POLLING_INTERVAL_IN_SECONDS = 30;
6
4
  const FIBONACCI_LIST = [1, 1, 2, 3, 5, 8, 13];
7
5
 
8
- /**
9
- * `fullRefresh` is true when the event manager has requested a full
10
- * refresh of the data. That can happen if there is too many events
11
- * to be processed or the last event ID is too old.
12
- */
13
- type Listener<T> = (events: T[], fullRefresh: boolean) => Promise<void>;
6
+ type Listener<T> = (event: T) => Promise<void>;
14
7
 
15
8
  /**
16
9
  * Event manager general helper that is responsible for fetching events
17
10
  * from the server and notifying listeners about the events.
18
- *
11
+ *
19
12
  * The specific implementation of fetching the events from the API must
20
13
  * be passed as dependency and can be used for any type of events that
21
14
  * supports the same structure.
22
- *
15
+ *
23
16
  * The manager will not start fetching events until the `start` method is
24
17
  * called. Once started, the manager will fetch events in a loop with
25
18
  * a timeout between each fetch. The default timeout is 30 seconds and
26
19
  * additional jitter is used in case of failure.
27
- *
28
- * Example of usage:
29
- *
30
- * ```typescript
31
- * const manager = new EventManager(
32
- * logger,
33
- * () => apiService.getLatestEventId(),
34
- * (eventId) => apiService.getEvents(eventId),
35
- * );
36
- *
37
- * manager.addListener((events, fullRefresh) => {
38
- * // Process the events
39
- * });
40
- *
41
- * manager.start();
42
- * ```
43
20
  */
44
- export class EventManager<T> {
21
+ export class EventManager<T extends Event> {
22
+ private logger: Logger;
45
23
  private latestEventId?: string;
46
24
  private timeoutHandle?: ReturnType<typeof setTimeout>;
47
25
  private processPromise?: Promise<void>;
48
26
  private listeners: Listener<T>[] = [];
49
27
  private retryIndex: number = 0;
50
28
 
51
- pollingIntervalInSeconds = DEFAULT_POLLING_INTERVAL_IN_SECONDS;
52
-
53
29
  constructor(
54
- private logger: Logger,
55
- private getLatestEventId: () => Promise<string>,
56
- private getEvents: (eventId: string) => Promise<Events<T>>,
57
- private updateLatestEventId: (lastEventId: string) => Promise<void>,
30
+ private specializedEventManager: EventManagerInterface<T>,
31
+ private pollingIntervalInSeconds: number,
32
+ latestEventId: string | null,
58
33
  ) {
59
- this.logger = logger;
60
- this.getLatestEventId = getLatestEventId;
61
- this.getEvents = getEvents;
62
- this.updateLatestEventId = updateLatestEventId;
34
+ if (latestEventId !== null) {
35
+ this.latestEventId = latestEventId;
36
+ }
37
+ this.logger = specializedEventManager.getLogger();
63
38
  }
64
39
 
65
- addListener(callback: Listener<T>): void {
40
+ async start(): Promise<void> {
41
+ if (this.latestEventId === undefined) {
42
+ this.latestEventId = await this.specializedEventManager.getLatestEventId();
43
+ }
44
+ this.processPromise = this.processEvents();
45
+ }
46
+
47
+ addListener(callback: Listener<T>): EventSubscription {
66
48
  this.listeners.push(callback);
49
+ return {
50
+ dispose: (): void => {
51
+ const index = this.listeners.indexOf(callback);
52
+ this.listeners.splice(index, 1);
53
+ },
54
+ };
67
55
  }
68
56
 
69
- async start(): Promise<void> {
70
- this.logger.info(`Starting event manager with polling interval ${this.pollingIntervalInSeconds} seconds`);
71
- await this.stop();
72
- this.processPromise = this.processEvents();
57
+ setPollingInterval(pollingIntervalInSeconds: number): void {
58
+ this.pollingIntervalInSeconds = pollingIntervalInSeconds;
59
+ }
60
+
61
+ async stop(): Promise<void> {
62
+ if (this.processPromise) {
63
+ this.logger.info(`Stopping event manager`);
64
+ try {
65
+ await this.processPromise;
66
+ } catch (error) {
67
+ this.logger.warn(`Failed to stop cleanly: ${error instanceof Error ? error.message : error}`);
68
+ }
69
+ }
70
+
71
+ if (!this.timeoutHandle) {
72
+ return;
73
+ }
74
+
75
+ clearTimeout(this.timeoutHandle);
76
+ this.timeoutHandle = undefined;
77
+ }
78
+
79
+ private async notifyListeners(event: T): Promise<void> {
80
+ for (const listener of this.listeners) {
81
+ await listener(event);
82
+ }
73
83
  }
74
84
 
75
85
  private async processEvents() {
86
+ let listenerError;
76
87
  try {
77
- if (!this.latestEventId) {
78
- this.latestEventId = await this.getLatestEventId();
79
- await this.updateLatestEventId(this.latestEventId);
80
- } else {
81
- while (true) {
82
- let result;
83
- try {
84
- result = await this.getEvents(this.latestEventId);
85
- } catch (error: unknown) {
86
- // If last event ID is not found, we need to refresh the data.
87
- // Caller is notified via standard event update with refresh flag.
88
- if (error instanceof NotFoundAPIError) {
89
- this.logger.warn(`Last event ID not found, refreshing data`);
90
- result = {
91
- lastEventId: await this.getLatestEventId(),
92
- more: false,
93
- refresh: true,
94
- events: [],
95
- };
96
- } else {
97
- // Any other error is considered as a failure and we will retry
98
- // with backoff policy.
99
- throw error;
100
- }
101
- }
102
- await this.notifyListeners(result);
103
- if (result.lastEventId !== this.latestEventId) {
104
- await this.updateLatestEventId(result.lastEventId);
105
- this.latestEventId = result.lastEventId;
106
- }
107
- if (!result.more) {
108
- break;
109
- }
88
+ const events = this.specializedEventManager.getEvents(this.latestEventId!);
89
+ for await (const event of events) {
90
+ try {
91
+ await this.notifyListeners(event);
92
+ } catch (internalListenerError) {
93
+ listenerError = internalListenerError;
94
+ break;
110
95
  }
96
+ this.latestEventId = event.eventId;
111
97
  }
112
98
  this.retryIndex = 0;
113
99
  } catch (error: unknown) {
114
- this.logger.error(`Failed to process events: ${error instanceof Error ? error.message : error} (retry ${this.retryIndex}, last event ID: ${this.latestEventId})`);
100
+ // This could be improved to catch api specific errors and let the listener errors bubble up directly
101
+ this.logger.error(
102
+ `Failed to process events: ${error instanceof Error ? error.message : error} (retry ${this.retryIndex}, last event ID: ${this.latestEventId})`,
103
+ );
115
104
  this.retryIndex++;
116
105
  }
106
+ if (listenerError) {
107
+ throw listenerError;
108
+ }
117
109
 
118
110
  this.timeoutHandle = setTimeout(() => {
119
111
  this.processPromise = this.processEvents();
120
112
  }, this.nextPollTimeout);
121
- };
122
-
123
- private async notifyListeners(result: Events<T>): Promise<void> {
124
- if (result.events.length === 0 && !result.refresh) {
125
- return;
126
- }
127
- if (!this.listeners.length) {
128
- return;
129
- }
130
-
131
- this.logger.debug(`Notifying listeners about ${result.events.length} events`);
132
-
133
- for (const listener of this.listeners) {
134
- try {
135
- await listener(result.events, result.refresh);
136
- } catch (error: unknown) {
137
- this.logger.error(`Failed to process events: ${error instanceof Error ? error.message : error} (last event ID: ${result.lastEventId}, refresh: ${result.refresh})`);
138
- throw error;
139
- }
140
- }
141
113
  }
142
114
 
143
115
  /**
144
116
  * Polling timeout is using exponential backoff with Fibonacci sequence.
145
- *
146
- * The timeout is public for testing purposes only.
147
117
  */
148
- get nextPollTimeout(): number {
118
+ private get nextPollTimeout(): number {
149
119
  const retryIndex = Math.min(this.retryIndex, FIBONACCI_LIST.length - 1);
120
+ // FIXME jitter
150
121
  return this.pollingIntervalInSeconds * 1000 * FIBONACCI_LIST[retryIndex];
151
122
  }
152
-
153
- async stop(): Promise<void> {
154
- if (this.processPromise) {
155
- this.logger.info(`Stopping event manager`);
156
- try {
157
- await this.processPromise;
158
- } catch {}
159
- }
160
-
161
- if (!this.timeoutHandle) {
162
- return;
163
- }
164
-
165
- clearTimeout(this.timeoutHandle);
166
- this.timeoutHandle = undefined;
167
- }
168
123
  }