@protontech/drive-sdk 0.0.10

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 (594) hide show
  1. package/README.md +17 -0
  2. package/dist/cache/index.d.ts +2 -0
  3. package/dist/cache/index.js +6 -0
  4. package/dist/cache/index.js.map +1 -0
  5. package/dist/cache/interface.d.ts +105 -0
  6. package/dist/cache/interface.js +3 -0
  7. package/dist/cache/interface.js.map +1 -0
  8. package/dist/cache/memoryCache.d.ts +18 -0
  9. package/dist/cache/memoryCache.js +78 -0
  10. package/dist/cache/memoryCache.js.map +1 -0
  11. package/dist/cache/memoryCache.test.d.ts +1 -0
  12. package/dist/cache/memoryCache.test.js +121 -0
  13. package/dist/cache/memoryCache.test.js.map +1 -0
  14. package/dist/config.d.ts +2 -0
  15. package/dist/config.js +11 -0
  16. package/dist/config.js.map +1 -0
  17. package/dist/crypto/driveCrypto.d.ts +209 -0
  18. package/dist/crypto/driveCrypto.js +364 -0
  19. package/dist/crypto/driveCrypto.js.map +1 -0
  20. package/dist/crypto/driveCrypto.test.d.ts +1 -0
  21. package/dist/crypto/driveCrypto.test.js +42 -0
  22. package/dist/crypto/driveCrypto.test.js.map +1 -0
  23. package/dist/crypto/hmac.d.ts +22 -0
  24. package/dist/crypto/hmac.js +44 -0
  25. package/dist/crypto/hmac.js.map +1 -0
  26. package/dist/crypto/index.d.ts +6 -0
  27. package/dist/crypto/index.js +13 -0
  28. package/dist/crypto/index.js.map +1 -0
  29. package/dist/crypto/interface.d.ts +125 -0
  30. package/dist/crypto/interface.js +10 -0
  31. package/dist/crypto/interface.js.map +1 -0
  32. package/dist/crypto/openPGPCrypto.d.ts +145 -0
  33. package/dist/crypto/openPGPCrypto.js +250 -0
  34. package/dist/crypto/openPGPCrypto.js.map +1 -0
  35. package/dist/crypto/utils.d.ts +2 -0
  36. package/dist/crypto/utils.js +35 -0
  37. package/dist/crypto/utils.js.map +1 -0
  38. package/dist/errors.d.ts +138 -0
  39. package/dist/errors.js +163 -0
  40. package/dist/errors.js.map +1 -0
  41. package/dist/index.d.ts +24 -0
  42. package/dist/index.js +48 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/interface/account.d.ts +36 -0
  45. package/dist/interface/account.js +3 -0
  46. package/dist/interface/account.js.map +1 -0
  47. package/dist/interface/author.d.ts +26 -0
  48. package/dist/interface/author.js +3 -0
  49. package/dist/interface/author.js.map +1 -0
  50. package/dist/interface/devices.d.ts +18 -0
  51. package/dist/interface/devices.js +10 -0
  52. package/dist/interface/devices.js.map +1 -0
  53. package/dist/interface/download.d.ts +29 -0
  54. package/dist/interface/download.js +3 -0
  55. package/dist/interface/download.js.map +1 -0
  56. package/dist/interface/events.d.ts +26 -0
  57. package/dist/interface/events.js +11 -0
  58. package/dist/interface/events.js.map +1 -0
  59. package/dist/interface/httpClient.d.ts +38 -0
  60. package/dist/interface/httpClient.js +3 -0
  61. package/dist/interface/httpClient.js.map +1 -0
  62. package/dist/interface/index.d.ts +43 -0
  63. package/dist/interface/index.js +22 -0
  64. package/dist/interface/index.js.map +1 -0
  65. package/dist/interface/nodes.d.ts +161 -0
  66. package/dist/interface/nodes.js +21 -0
  67. package/dist/interface/nodes.js.map +1 -0
  68. package/dist/interface/result.d.ts +9 -0
  69. package/dist/interface/result.js +11 -0
  70. package/dist/interface/result.js.map +1 -0
  71. package/dist/interface/sharing.d.ts +73 -0
  72. package/dist/interface/sharing.js +9 -0
  73. package/dist/interface/sharing.js.map +1 -0
  74. package/dist/interface/telemetry.d.ts +61 -0
  75. package/dist/interface/telemetry.js +18 -0
  76. package/dist/interface/telemetry.js.map +1 -0
  77. package/dist/interface/thumbnail.d.ts +17 -0
  78. package/dist/interface/thumbnail.js +9 -0
  79. package/dist/interface/thumbnail.js.map +1 -0
  80. package/dist/interface/upload.d.ts +16 -0
  81. package/dist/interface/upload.js +3 -0
  82. package/dist/interface/upload.js.map +1 -0
  83. package/dist/internal/apiService/apiService.d.ts +51 -0
  84. package/dist/internal/apiService/apiService.js +305 -0
  85. package/dist/internal/apiService/apiService.js.map +1 -0
  86. package/dist/internal/apiService/apiService.test.d.ts +1 -0
  87. package/dist/internal/apiService/apiService.test.js +237 -0
  88. package/dist/internal/apiService/apiService.test.js.map +1 -0
  89. package/dist/internal/apiService/coreTypes.d.ts +24438 -0
  90. package/dist/internal/apiService/coreTypes.js +7 -0
  91. package/dist/internal/apiService/coreTypes.js.map +1 -0
  92. package/dist/internal/apiService/driveTypes.d.ts +11840 -0
  93. package/dist/internal/apiService/driveTypes.js +7 -0
  94. package/dist/internal/apiService/driveTypes.js.map +1 -0
  95. package/dist/internal/apiService/errorCodes.d.ts +30 -0
  96. package/dist/internal/apiService/errorCodes.js +11 -0
  97. package/dist/internal/apiService/errorCodes.js.map +1 -0
  98. package/dist/internal/apiService/errors.d.ts +19 -0
  99. package/dist/internal/apiService/errors.js +76 -0
  100. package/dist/internal/apiService/errors.js.map +1 -0
  101. package/dist/internal/apiService/errors.test.d.ts +1 -0
  102. package/dist/internal/apiService/errors.test.js +69 -0
  103. package/dist/internal/apiService/errors.test.js.map +1 -0
  104. package/dist/internal/apiService/index.d.ts +7 -0
  105. package/dist/internal/apiService/index.js +30 -0
  106. package/dist/internal/apiService/index.js.map +1 -0
  107. package/dist/internal/apiService/observerStream.d.ts +3 -0
  108. package/dist/internal/apiService/observerStream.js +15 -0
  109. package/dist/internal/apiService/observerStream.js.map +1 -0
  110. package/dist/internal/apiService/transformers.d.ts +4 -0
  111. package/dist/internal/apiService/transformers.js +48 -0
  112. package/dist/internal/apiService/transformers.js.map +1 -0
  113. package/dist/internal/batchLoading.d.ts +34 -0
  114. package/dist/internal/batchLoading.js +68 -0
  115. package/dist/internal/batchLoading.js.map +1 -0
  116. package/dist/internal/batchLoading.test.d.ts +1 -0
  117. package/dist/internal/batchLoading.test.js +50 -0
  118. package/dist/internal/batchLoading.test.js.map +1 -0
  119. package/dist/internal/devices/apiService.d.ts +38 -0
  120. package/dist/internal/devices/apiService.js +105 -0
  121. package/dist/internal/devices/apiService.js.map +1 -0
  122. package/dist/internal/devices/cryptoService.d.ts +30 -0
  123. package/dist/internal/devices/cryptoService.js +47 -0
  124. package/dist/internal/devices/cryptoService.js.map +1 -0
  125. package/dist/internal/devices/index.d.ts +15 -0
  126. package/dist/internal/devices/index.js +22 -0
  127. package/dist/internal/devices/index.js.map +1 -0
  128. package/dist/internal/devices/interface.d.ts +31 -0
  129. package/dist/internal/devices/interface.js +3 -0
  130. package/dist/internal/devices/interface.js.map +1 -0
  131. package/dist/internal/devices/manager.d.ts +18 -0
  132. package/dist/internal/devices/manager.js +103 -0
  133. package/dist/internal/devices/manager.js.map +1 -0
  134. package/dist/internal/devices/manager.test.d.ts +1 -0
  135. package/dist/internal/devices/manager.test.js +100 -0
  136. package/dist/internal/devices/manager.test.js.map +1 -0
  137. package/dist/internal/download/apiService.d.ts +27 -0
  138. package/dist/internal/download/apiService.js +110 -0
  139. package/dist/internal/download/apiService.js.map +1 -0
  140. package/dist/internal/download/controller.d.ts +8 -0
  141. package/dist/internal/download/controller.js +22 -0
  142. package/dist/internal/download/controller.js.map +1 -0
  143. package/dist/internal/download/cryptoService.d.ts +17 -0
  144. package/dist/internal/download/cryptoService.js +82 -0
  145. package/dist/internal/download/cryptoService.js.map +1 -0
  146. package/dist/internal/download/fileDownloader.d.ts +33 -0
  147. package/dist/internal/download/fileDownloader.js +226 -0
  148. package/dist/internal/download/fileDownloader.js.map +1 -0
  149. package/dist/internal/download/fileDownloader.test.d.ts +1 -0
  150. package/dist/internal/download/fileDownloader.test.js +324 -0
  151. package/dist/internal/download/fileDownloader.test.js.map +1 -0
  152. package/dist/internal/download/index.d.ts +10 -0
  153. package/dist/internal/download/index.js +82 -0
  154. package/dist/internal/download/index.js.map +1 -0
  155. package/dist/internal/download/interface.d.ts +35 -0
  156. package/dist/internal/download/interface.js +3 -0
  157. package/dist/internal/download/interface.js.map +1 -0
  158. package/dist/internal/download/queue.d.ts +5 -0
  159. package/dist/internal/download/queue.js +31 -0
  160. package/dist/internal/download/queue.js.map +1 -0
  161. package/dist/internal/download/telemetry.d.ts +14 -0
  162. package/dist/internal/download/telemetry.js +106 -0
  163. package/dist/internal/download/telemetry.js.map +1 -0
  164. package/dist/internal/download/telemetry.test.d.ts +1 -0
  165. package/dist/internal/download/telemetry.test.js +111 -0
  166. package/dist/internal/download/telemetry.test.js.map +1 -0
  167. package/dist/internal/download/thumbnailDownloader.d.ts +19 -0
  168. package/dist/internal/download/thumbnailDownloader.js +198 -0
  169. package/dist/internal/download/thumbnailDownloader.js.map +1 -0
  170. package/dist/internal/download/thumbnailDownloader.test.d.ts +1 -0
  171. package/dist/internal/download/thumbnailDownloader.test.js +179 -0
  172. package/dist/internal/download/thumbnailDownloader.test.js.map +1 -0
  173. package/dist/internal/errors.d.ts +6 -0
  174. package/dist/internal/errors.js +28 -0
  175. package/dist/internal/errors.js.map +1 -0
  176. package/dist/internal/errors.test.d.ts +1 -0
  177. package/dist/internal/errors.test.js +22 -0
  178. package/dist/internal/errors.test.js.map +1 -0
  179. package/dist/internal/events/apiService.d.ts +18 -0
  180. package/dist/internal/events/apiService.js +81 -0
  181. package/dist/internal/events/apiService.js.map +1 -0
  182. package/dist/internal/events/cache.d.ts +28 -0
  183. package/dist/internal/events/cache.js +67 -0
  184. package/dist/internal/events/cache.js.map +1 -0
  185. package/dist/internal/events/cache.test.d.ts +1 -0
  186. package/dist/internal/events/cache.test.js +43 -0
  187. package/dist/internal/events/cache.test.js.map +1 -0
  188. package/dist/internal/events/coreEventManager.d.ts +25 -0
  189. package/dist/internal/events/coreEventManager.js +63 -0
  190. package/dist/internal/events/coreEventManager.js.map +1 -0
  191. package/dist/internal/events/eventManager.d.ts +62 -0
  192. package/dist/internal/events/eventManager.js +159 -0
  193. package/dist/internal/events/eventManager.js.map +1 -0
  194. package/dist/internal/events/eventManager.test.d.ts +1 -0
  195. package/dist/internal/events/eventManager.test.js +120 -0
  196. package/dist/internal/events/eventManager.test.js.map +1 -0
  197. package/dist/internal/events/index.d.ts +50 -0
  198. package/dist/internal/events/index.js +117 -0
  199. package/dist/internal/events/index.js.map +1 -0
  200. package/dist/internal/events/interface.d.ts +47 -0
  201. package/dist/internal/events/interface.js +12 -0
  202. package/dist/internal/events/interface.js.map +1 -0
  203. package/dist/internal/events/volumeEventManager.d.ts +27 -0
  204. package/dist/internal/events/volumeEventManager.js +69 -0
  205. package/dist/internal/events/volumeEventManager.js.map +1 -0
  206. package/dist/internal/nodes/apiService.d.ts +54 -0
  207. package/dist/internal/nodes/apiService.js +308 -0
  208. package/dist/internal/nodes/apiService.js.map +1 -0
  209. package/dist/internal/nodes/apiService.test.d.ts +1 -0
  210. package/dist/internal/nodes/apiService.test.js +344 -0
  211. package/dist/internal/nodes/apiService.test.js.map +1 -0
  212. package/dist/internal/nodes/cache.d.ts +57 -0
  213. package/dist/internal/nodes/cache.js +226 -0
  214. package/dist/internal/nodes/cache.js.map +1 -0
  215. package/dist/internal/nodes/cache.test.d.ts +1 -0
  216. package/dist/internal/nodes/cache.test.js +160 -0
  217. package/dist/internal/nodes/cache.test.js.map +1 -0
  218. package/dist/internal/nodes/cryptoCache.d.ts +16 -0
  219. package/dist/internal/nodes/cryptoCache.js +50 -0
  220. package/dist/internal/nodes/cryptoCache.js.map +1 -0
  221. package/dist/internal/nodes/cryptoCache.test.d.ts +1 -0
  222. package/dist/internal/nodes/cryptoCache.test.js +79 -0
  223. package/dist/internal/nodes/cryptoCache.test.js.map +1 -0
  224. package/dist/internal/nodes/cryptoService.d.ts +75 -0
  225. package/dist/internal/nodes/cryptoService.js +409 -0
  226. package/dist/internal/nodes/cryptoService.js.map +1 -0
  227. package/dist/internal/nodes/cryptoService.test.d.ts +1 -0
  228. package/dist/internal/nodes/cryptoService.test.js +698 -0
  229. package/dist/internal/nodes/cryptoService.test.js.map +1 -0
  230. package/dist/internal/nodes/events.d.ts +91 -0
  231. package/dist/internal/nodes/events.js +243 -0
  232. package/dist/internal/nodes/events.js.map +1 -0
  233. package/dist/internal/nodes/events.test.d.ts +1 -0
  234. package/dist/internal/nodes/events.test.js +318 -0
  235. package/dist/internal/nodes/events.test.js.map +1 -0
  236. package/dist/internal/nodes/extendedAttributes.d.ts +23 -0
  237. package/dist/internal/nodes/extendedAttributes.js +117 -0
  238. package/dist/internal/nodes/extendedAttributes.js.map +1 -0
  239. package/dist/internal/nodes/extendedAttributes.test.d.ts +1 -0
  240. package/dist/internal/nodes/extendedAttributes.test.js +176 -0
  241. package/dist/internal/nodes/extendedAttributes.test.js.map +1 -0
  242. package/dist/internal/nodes/index.d.ts +26 -0
  243. package/dist/internal/nodes/index.js +40 -0
  244. package/dist/internal/nodes/index.js.map +1 -0
  245. package/dist/internal/nodes/index.test.d.ts +1 -0
  246. package/dist/internal/nodes/index.test.js +112 -0
  247. package/dist/internal/nodes/index.test.js.map +1 -0
  248. package/dist/internal/nodes/interface.d.ts +135 -0
  249. package/dist/internal/nodes/interface.js +3 -0
  250. package/dist/internal/nodes/interface.js.map +1 -0
  251. package/dist/internal/nodes/mediaTypes.d.ts +2 -0
  252. package/dist/internal/nodes/mediaTypes.js +13 -0
  253. package/dist/internal/nodes/mediaTypes.js.map +1 -0
  254. package/dist/internal/nodes/nodesAccess.d.ts +49 -0
  255. package/dist/internal/nodes/nodesAccess.js +332 -0
  256. package/dist/internal/nodes/nodesAccess.js.map +1 -0
  257. package/dist/internal/nodes/nodesAccess.test.d.ts +1 -0
  258. package/dist/internal/nodes/nodesAccess.test.js +487 -0
  259. package/dist/internal/nodes/nodesAccess.test.js.map +1 -0
  260. package/dist/internal/nodes/nodesManagement.d.ts +33 -0
  261. package/dist/internal/nodes/nodesManagement.js +222 -0
  262. package/dist/internal/nodes/nodesManagement.js.map +1 -0
  263. package/dist/internal/nodes/nodesManagement.test.d.ts +1 -0
  264. package/dist/internal/nodes/nodesManagement.test.js +178 -0
  265. package/dist/internal/nodes/nodesManagement.test.js.map +1 -0
  266. package/dist/internal/nodes/nodesRevisions.d.ts +18 -0
  267. package/dist/internal/nodes/nodesRevisions.js +55 -0
  268. package/dist/internal/nodes/nodesRevisions.js.map +1 -0
  269. package/dist/internal/nodes/validations.d.ts +4 -0
  270. package/dist/internal/nodes/validations.js +21 -0
  271. package/dist/internal/nodes/validations.js.map +1 -0
  272. package/dist/internal/photos/albums.d.ts +13 -0
  273. package/dist/internal/photos/albums.js +30 -0
  274. package/dist/internal/photos/albums.js.map +1 -0
  275. package/dist/internal/photos/apiService.d.ts +8 -0
  276. package/dist/internal/photos/apiService.js +18 -0
  277. package/dist/internal/photos/apiService.js.map +1 -0
  278. package/dist/internal/photos/cache.d.ts +6 -0
  279. package/dist/internal/photos/cache.js +15 -0
  280. package/dist/internal/photos/cache.js.map +1 -0
  281. package/dist/internal/photos/index.d.ts +9 -0
  282. package/dist/internal/photos/index.js +18 -0
  283. package/dist/internal/photos/index.js.map +1 -0
  284. package/dist/internal/photos/interface.d.ts +6 -0
  285. package/dist/internal/photos/interface.js +3 -0
  286. package/dist/internal/photos/interface.js.map +1 -0
  287. package/dist/internal/photos/photosTimeline.d.ts +10 -0
  288. package/dist/internal/photos/photosTimeline.js +20 -0
  289. package/dist/internal/photos/photosTimeline.js.map +1 -0
  290. package/dist/internal/sdkEvents.d.ts +12 -0
  291. package/dist/internal/sdkEvents.js +44 -0
  292. package/dist/internal/sdkEvents.js.map +1 -0
  293. package/dist/internal/sdkEvents.test.d.ts +1 -0
  294. package/dist/internal/sdkEvents.test.js +45 -0
  295. package/dist/internal/sdkEvents.test.js.map +1 -0
  296. package/dist/internal/shares/apiService.d.ts +51 -0
  297. package/dist/internal/shares/apiService.js +128 -0
  298. package/dist/internal/shares/apiService.js.map +1 -0
  299. package/dist/internal/shares/cache.d.ts +15 -0
  300. package/dist/internal/shares/cache.js +63 -0
  301. package/dist/internal/shares/cache.js.map +1 -0
  302. package/dist/internal/shares/cache.test.d.ts +1 -0
  303. package/dist/internal/shares/cache.test.js +54 -0
  304. package/dist/internal/shares/cache.test.js.map +1 -0
  305. package/dist/internal/shares/cryptoCache.d.ts +20 -0
  306. package/dist/internal/shares/cryptoCache.js +35 -0
  307. package/dist/internal/shares/cryptoCache.js.map +1 -0
  308. package/dist/internal/shares/cryptoCache.test.d.ts +1 -0
  309. package/dist/internal/shares/cryptoCache.test.js +58 -0
  310. package/dist/internal/shares/cryptoCache.test.js.map +1 -0
  311. package/dist/internal/shares/cryptoService.d.ts +42 -0
  312. package/dist/internal/shares/cryptoService.js +126 -0
  313. package/dist/internal/shares/cryptoService.js.map +1 -0
  314. package/dist/internal/shares/cryptoService.test.d.ts +1 -0
  315. package/dist/internal/shares/cryptoService.test.js +120 -0
  316. package/dist/internal/shares/cryptoService.test.js.map +1 -0
  317. package/dist/internal/shares/index.d.ts +15 -0
  318. package/dist/internal/shares/index.js +26 -0
  319. package/dist/internal/shares/index.js.map +1 -0
  320. package/dist/internal/shares/interface.d.ts +94 -0
  321. package/dist/internal/shares/interface.js +11 -0
  322. package/dist/internal/shares/interface.js.map +1 -0
  323. package/dist/internal/shares/manager.d.ts +68 -0
  324. package/dist/internal/shares/manager.js +186 -0
  325. package/dist/internal/shares/manager.js.map +1 -0
  326. package/dist/internal/shares/manager.test.d.ts +1 -0
  327. package/dist/internal/shares/manager.test.js +176 -0
  328. package/dist/internal/shares/manager.test.js.map +1 -0
  329. package/dist/internal/sharing/apiService.d.ts +80 -0
  330. package/dist/internal/sharing/apiService.js +325 -0
  331. package/dist/internal/sharing/apiService.js.map +1 -0
  332. package/dist/internal/sharing/cache.d.ts +37 -0
  333. package/dist/internal/sharing/cache.js +105 -0
  334. package/dist/internal/sharing/cache.js.map +1 -0
  335. package/dist/internal/sharing/cache.test.d.ts +1 -0
  336. package/dist/internal/sharing/cache.test.js +82 -0
  337. package/dist/internal/sharing/cache.test.js.map +1 -0
  338. package/dist/internal/sharing/cryptoService.d.ts +112 -0
  339. package/dist/internal/sharing/cryptoService.js +269 -0
  340. package/dist/internal/sharing/cryptoService.js.map +1 -0
  341. package/dist/internal/sharing/events.d.ts +57 -0
  342. package/dist/internal/sharing/events.js +153 -0
  343. package/dist/internal/sharing/events.js.map +1 -0
  344. package/dist/internal/sharing/events.test.d.ts +1 -0
  345. package/dist/internal/sharing/events.test.js +246 -0
  346. package/dist/internal/sharing/events.test.js.map +1 -0
  347. package/dist/internal/sharing/index.d.ts +20 -0
  348. package/dist/internal/sharing/index.js +30 -0
  349. package/dist/internal/sharing/index.js.map +1 -0
  350. package/dist/internal/sharing/interface.d.ts +169 -0
  351. package/dist/internal/sharing/interface.js +9 -0
  352. package/dist/internal/sharing/interface.js.map +1 -0
  353. package/dist/internal/sharing/sharingAccess.d.ts +32 -0
  354. package/dist/internal/sharing/sharingAccess.js +119 -0
  355. package/dist/internal/sharing/sharingAccess.js.map +1 -0
  356. package/dist/internal/sharing/sharingAccess.test.d.ts +1 -0
  357. package/dist/internal/sharing/sharingAccess.test.js +84 -0
  358. package/dist/internal/sharing/sharingAccess.test.js.map +1 -0
  359. package/dist/internal/sharing/sharingManagement.d.ts +43 -0
  360. package/dist/internal/sharing/sharingManagement.js +439 -0
  361. package/dist/internal/sharing/sharingManagement.js.map +1 -0
  362. package/dist/internal/sharing/sharingManagement.test.d.ts +1 -0
  363. package/dist/internal/sharing/sharingManagement.test.js +788 -0
  364. package/dist/internal/sharing/sharingManagement.test.js.map +1 -0
  365. package/dist/internal/uids.d.ts +38 -0
  366. package/dist/internal/uids.js +85 -0
  367. package/dist/internal/uids.js.map +1 -0
  368. package/dist/internal/upload/apiService.d.ts +65 -0
  369. package/dist/internal/upload/apiService.js +137 -0
  370. package/dist/internal/upload/apiService.js.map +1 -0
  371. package/dist/internal/upload/blockVerifier.d.ts +16 -0
  372. package/dist/internal/upload/blockVerifier.js +33 -0
  373. package/dist/internal/upload/blockVerifier.js.map +1 -0
  374. package/dist/internal/upload/chunkStreamReader.d.ts +13 -0
  375. package/dist/internal/upload/chunkStreamReader.js +46 -0
  376. package/dist/internal/upload/chunkStreamReader.js.map +1 -0
  377. package/dist/internal/upload/chunkStreamReader.test.d.ts +1 -0
  378. package/dist/internal/upload/chunkStreamReader.test.js +75 -0
  379. package/dist/internal/upload/chunkStreamReader.test.js.map +1 -0
  380. package/dist/internal/upload/controller.d.ts +8 -0
  381. package/dist/internal/upload/controller.js +25 -0
  382. package/dist/internal/upload/controller.js.map +1 -0
  383. package/dist/internal/upload/cryptoService.d.ts +29 -0
  384. package/dist/internal/upload/cryptoService.js +104 -0
  385. package/dist/internal/upload/cryptoService.js.map +1 -0
  386. package/dist/internal/upload/digests.d.ts +8 -0
  387. package/dist/internal/upload/digests.js +22 -0
  388. package/dist/internal/upload/digests.js.map +1 -0
  389. package/dist/internal/upload/fileUploader.d.ts +65 -0
  390. package/dist/internal/upload/fileUploader.js +463 -0
  391. package/dist/internal/upload/fileUploader.js.map +1 -0
  392. package/dist/internal/upload/fileUploader.test.d.ts +1 -0
  393. package/dist/internal/upload/fileUploader.test.js +393 -0
  394. package/dist/internal/upload/fileUploader.test.js.map +1 -0
  395. package/dist/internal/upload/index.d.ts +16 -0
  396. package/dist/internal/upload/index.js +77 -0
  397. package/dist/internal/upload/index.js.map +1 -0
  398. package/dist/internal/upload/interface.d.ts +117 -0
  399. package/dist/internal/upload/interface.js +3 -0
  400. package/dist/internal/upload/interface.js.map +1 -0
  401. package/dist/internal/upload/manager.d.ts +31 -0
  402. package/dist/internal/upload/manager.js +250 -0
  403. package/dist/internal/upload/manager.js.map +1 -0
  404. package/dist/internal/upload/manager.test.d.ts +1 -0
  405. package/dist/internal/upload/manager.test.js +349 -0
  406. package/dist/internal/upload/manager.test.js.map +1 -0
  407. package/dist/internal/upload/queue.d.ts +5 -0
  408. package/dist/internal/upload/queue.js +32 -0
  409. package/dist/internal/upload/queue.js.map +1 -0
  410. package/dist/internal/upload/telemetry.d.ts +15 -0
  411. package/dist/internal/upload/telemetry.js +111 -0
  412. package/dist/internal/upload/telemetry.js.map +1 -0
  413. package/dist/internal/upload/telemetry.test.d.ts +1 -0
  414. package/dist/internal/upload/telemetry.test.js +107 -0
  415. package/dist/internal/upload/telemetry.test.js.map +1 -0
  416. package/dist/internal/utils.d.ts +1 -0
  417. package/dist/internal/utils.js +13 -0
  418. package/dist/internal/utils.js.map +1 -0
  419. package/dist/internal/wait.d.ts +3 -0
  420. package/dist/internal/wait.js +28 -0
  421. package/dist/internal/wait.js.map +1 -0
  422. package/dist/internal/wait.test.d.ts +1 -0
  423. package/dist/internal/wait.test.js +21 -0
  424. package/dist/internal/wait.test.js.map +1 -0
  425. package/dist/protonDriveClient.d.ts +593 -0
  426. package/dist/protonDriveClient.js +768 -0
  427. package/dist/protonDriveClient.js.map +1 -0
  428. package/dist/protonDrivePhotosClient.d.ts +16 -0
  429. package/dist/protonDrivePhotosClient.js +46 -0
  430. package/dist/protonDrivePhotosClient.js.map +1 -0
  431. package/dist/telemetry.d.ts +187 -0
  432. package/dist/telemetry.js +297 -0
  433. package/dist/telemetry.js.map +1 -0
  434. package/dist/tests/logger.d.ts +2 -0
  435. package/dist/tests/logger.js +12 -0
  436. package/dist/tests/logger.js.map +1 -0
  437. package/dist/tests/telemetry.d.ts +2 -0
  438. package/dist/tests/telemetry.js +11 -0
  439. package/dist/tests/telemetry.js.map +1 -0
  440. package/dist/transformers.d.ts +17 -0
  441. package/dist/transformers.js +77 -0
  442. package/dist/transformers.js.map +1 -0
  443. package/dist/version.d.ts +1 -0
  444. package/dist/version.js +6 -0
  445. package/dist/version.js.map +1 -0
  446. package/package.json +49 -0
  447. package/src/cache/index.ts +2 -0
  448. package/src/cache/interface.ts +104 -0
  449. package/src/cache/memoryCache.test.ts +150 -0
  450. package/src/cache/memoryCache.ts +85 -0
  451. package/src/config.ts +9 -0
  452. package/src/crypto/driveCrypto.test.ts +45 -0
  453. package/src/crypto/driveCrypto.ts +696 -0
  454. package/src/crypto/hmac.ts +46 -0
  455. package/src/crypto/index.ts +6 -0
  456. package/src/crypto/interface.ts +230 -0
  457. package/src/crypto/openPGPCrypto.ts +398 -0
  458. package/src/crypto/utils.ts +40 -0
  459. package/src/errors.ts +168 -0
  460. package/src/index.ts +30 -0
  461. package/src/interface/account.ts +38 -0
  462. package/src/interface/author.ts +29 -0
  463. package/src/interface/devices.ts +21 -0
  464. package/src/interface/download.ts +32 -0
  465. package/src/interface/events.ts +30 -0
  466. package/src/interface/httpClient.ts +42 -0
  467. package/src/interface/index.ts +46 -0
  468. package/src/interface/nodes.ts +168 -0
  469. package/src/interface/result.ts +11 -0
  470. package/src/interface/sharing.ts +87 -0
  471. package/src/interface/telemetry.ts +107 -0
  472. package/src/interface/thumbnail.ts +14 -0
  473. package/src/interface/upload.ts +19 -0
  474. package/src/internal/apiService/apiService.test.ts +285 -0
  475. package/src/internal/apiService/apiService.ts +353 -0
  476. package/src/internal/apiService/coreTypes.ts +24439 -0
  477. package/src/internal/apiService/driveTypes.ts +11841 -0
  478. package/src/internal/apiService/errorCodes.ts +38 -0
  479. package/src/internal/apiService/errors.test.ts +63 -0
  480. package/src/internal/apiService/errors.ts +91 -0
  481. package/src/internal/apiService/index.ts +7 -0
  482. package/src/internal/apiService/observerStream.ts +10 -0
  483. package/src/internal/apiService/transformers.ts +45 -0
  484. package/src/internal/batchLoading.test.ts +58 -0
  485. package/src/internal/batchLoading.ts +74 -0
  486. package/src/internal/devices/apiService.ts +142 -0
  487. package/src/internal/devices/cryptoService.ts +65 -0
  488. package/src/internal/devices/index.ts +31 -0
  489. package/src/internal/devices/interface.ts +28 -0
  490. package/src/internal/devices/manager.test.ts +129 -0
  491. package/src/internal/devices/manager.ts +113 -0
  492. package/src/internal/download/apiService.ts +145 -0
  493. package/src/internal/download/controller.ts +22 -0
  494. package/src/internal/download/cryptoService.ts +96 -0
  495. package/src/internal/download/fileDownloader.test.ts +381 -0
  496. package/src/internal/download/fileDownloader.ts +266 -0
  497. package/src/internal/download/index.ts +122 -0
  498. package/src/internal/download/interface.ts +38 -0
  499. package/src/internal/download/queue.ts +30 -0
  500. package/src/internal/download/telemetry.test.ts +134 -0
  501. package/src/internal/download/telemetry.ts +115 -0
  502. package/src/internal/download/thumbnailDownloader.test.ts +226 -0
  503. package/src/internal/download/thumbnailDownloader.ts +250 -0
  504. package/src/internal/errors.test.ts +21 -0
  505. package/src/internal/errors.ts +28 -0
  506. package/src/internal/events/apiService.ts +87 -0
  507. package/src/internal/events/cache.test.ts +47 -0
  508. package/src/internal/events/cache.ts +80 -0
  509. package/src/internal/events/coreEventManager.ts +69 -0
  510. package/src/internal/events/eventManager.test.ts +139 -0
  511. package/src/internal/events/eventManager.ts +168 -0
  512. package/src/internal/events/index.ts +131 -0
  513. package/src/internal/events/interface.ts +51 -0
  514. package/src/internal/events/volumeEventManager.ts +74 -0
  515. package/src/internal/nodes/apiService.test.ts +394 -0
  516. package/src/internal/nodes/apiService.ts +455 -0
  517. package/src/internal/nodes/cache.test.ts +197 -0
  518. package/src/internal/nodes/cache.ts +240 -0
  519. package/src/internal/nodes/cryptoCache.test.ts +92 -0
  520. package/src/internal/nodes/cryptoCache.ts +47 -0
  521. package/src/internal/nodes/cryptoService.test.ts +814 -0
  522. package/src/internal/nodes/cryptoService.ts +550 -0
  523. package/src/internal/nodes/events.test.ts +383 -0
  524. package/src/internal/nodes/events.ts +271 -0
  525. package/src/internal/nodes/extendedAttributes.test.ts +177 -0
  526. package/src/internal/nodes/extendedAttributes.ts +180 -0
  527. package/src/internal/nodes/index.test.ts +135 -0
  528. package/src/internal/nodes/index.ts +52 -0
  529. package/src/internal/nodes/interface.ts +152 -0
  530. package/src/internal/nodes/mediaTypes.ts +10 -0
  531. package/src/internal/nodes/nodesAccess.test.ts +555 -0
  532. package/src/internal/nodes/nodesAccess.ts +360 -0
  533. package/src/internal/nodes/nodesManagement.test.ts +221 -0
  534. package/src/internal/nodes/nodesManagement.ts +272 -0
  535. package/src/internal/nodes/nodesRevisions.ts +58 -0
  536. package/src/internal/nodes/validations.ts +26 -0
  537. package/src/internal/photos/albums.ts +29 -0
  538. package/src/internal/photos/apiService.ts +16 -0
  539. package/src/internal/photos/cache.ts +11 -0
  540. package/src/internal/photos/index.ts +23 -0
  541. package/src/internal/photos/interface.ts +7 -0
  542. package/src/internal/photos/photosTimeline.ts +18 -0
  543. package/src/internal/sdkEvents.test.ts +55 -0
  544. package/src/internal/sdkEvents.ts +52 -0
  545. package/src/internal/shares/apiService.ts +176 -0
  546. package/src/internal/shares/cache.test.ts +58 -0
  547. package/src/internal/shares/cache.ts +64 -0
  548. package/src/internal/shares/cryptoCache.test.ts +70 -0
  549. package/src/internal/shares/cryptoCache.ts +35 -0
  550. package/src/internal/shares/cryptoService.test.ts +137 -0
  551. package/src/internal/shares/cryptoService.ts +143 -0
  552. package/src/internal/shares/index.ts +35 -0
  553. package/src/internal/shares/interface.ts +104 -0
  554. package/src/internal/shares/manager.test.ts +210 -0
  555. package/src/internal/shares/manager.ts +213 -0
  556. package/src/internal/sharing/apiService.ts +483 -0
  557. package/src/internal/sharing/cache.test.ts +99 -0
  558. package/src/internal/sharing/cache.ts +109 -0
  559. package/src/internal/sharing/cryptoService.ts +378 -0
  560. package/src/internal/sharing/events.test.ts +268 -0
  561. package/src/internal/sharing/events.ts +166 -0
  562. package/src/internal/sharing/index.ts +43 -0
  563. package/src/internal/sharing/interface.ts +177 -0
  564. package/src/internal/sharing/sharingAccess.test.ts +102 -0
  565. package/src/internal/sharing/sharingAccess.ts +133 -0
  566. package/src/internal/sharing/sharingManagement.test.ts +895 -0
  567. package/src/internal/sharing/sharingManagement.ts +521 -0
  568. package/src/internal/uids.ts +83 -0
  569. package/src/internal/upload/apiService.ts +243 -0
  570. package/src/internal/upload/blockVerifier.ts +40 -0
  571. package/src/internal/upload/chunkStreamReader.test.ts +89 -0
  572. package/src/internal/upload/chunkStreamReader.ts +49 -0
  573. package/src/internal/upload/controller.ts +25 -0
  574. package/src/internal/upload/cryptoService.ts +162 -0
  575. package/src/internal/upload/digests.ts +18 -0
  576. package/src/internal/upload/fileUploader.test.ts +513 -0
  577. package/src/internal/upload/fileUploader.ts +576 -0
  578. package/src/internal/upload/index.ts +126 -0
  579. package/src/internal/upload/interface.ts +128 -0
  580. package/src/internal/upload/manager.test.ts +390 -0
  581. package/src/internal/upload/manager.ts +320 -0
  582. package/src/internal/upload/queue.ts +31 -0
  583. package/src/internal/upload/telemetry.test.ts +129 -0
  584. package/src/internal/upload/telemetry.ts +121 -0
  585. package/src/internal/utils.ts +9 -0
  586. package/src/internal/wait.test.ts +21 -0
  587. package/src/internal/wait.ts +26 -0
  588. package/src/protonDriveClient.ts +861 -0
  589. package/src/protonDrivePhotosClient.ts +56 -0
  590. package/src/telemetry.ts +346 -0
  591. package/src/tests/logger.ts +10 -0
  592. package/src/tests/telemetry.ts +9 -0
  593. package/src/transformers.ts +98 -0
  594. package/src/version.ts +4 -0
@@ -0,0 +1,320 @@
1
+ import { c } from "ttag";
2
+
3
+ import { Logger, MemberRole, NodeType, ProtonDriveTelemetry, resultOk, Revision, RevisionState, UploadMetadata } from "../../interface";
4
+ import { ValidationError, NodeAlreadyExistsValidationError } from "../../errors";
5
+ import { ErrorCode } from "../apiService";
6
+ import { DecryptedNode, generateFileExtendedAttributes } from "../nodes";
7
+ import { UploadAPIService } from "./apiService";
8
+ import { UploadCryptoService } from "./cryptoService";
9
+ import { NodeRevisionDraft, NodesService, NodesEvents, NodeCrypto } from "./interface";
10
+
11
+ /**
12
+ * UploadManager is responsible for creating and deleting draft nodes
13
+ * on the server. It handles the creation of draft nodes, including
14
+ * generating the necessary cryptographic keys and metadata.
15
+ */
16
+ export class UploadManager {
17
+ private logger: Logger;
18
+
19
+ constructor(
20
+ telemetry: ProtonDriveTelemetry,
21
+ private apiService: UploadAPIService,
22
+ private cryptoService: UploadCryptoService,
23
+ private nodesService: NodesService,
24
+ private nodesEvents: NodesEvents,
25
+ ) {
26
+ this.logger = telemetry.getLogger('upload');
27
+ this.apiService = apiService;
28
+ this.cryptoService = cryptoService;
29
+ this.nodesService = nodesService;
30
+ }
31
+
32
+ async createDraftNode(parentFolderUid: string, name: string, metadata: UploadMetadata): Promise<NodeRevisionDraft> {
33
+ const parentKeys = await this.nodesService.getNodeKeys(parentFolderUid);
34
+ if (!parentKeys.hashKey) {
35
+ throw new ValidationError(c('Error').t`Creating files in non-folders is not allowed`);
36
+ }
37
+
38
+ const generatedNodeCrypto = await this.cryptoService.generateFileCrypto(
39
+ parentFolderUid,
40
+ { key: parentKeys.key, hashKey: parentKeys.hashKey },
41
+ name,
42
+ );
43
+
44
+ const { nodeUid, nodeRevisionUid } = await this.createDraftOnAPI(
45
+ parentFolderUid,
46
+ parentKeys.hashKey,
47
+ name,
48
+ metadata,
49
+ generatedNodeCrypto,
50
+ );
51
+
52
+ return {
53
+ nodeUid,
54
+ nodeRevisionUid,
55
+ nodeKeys: {
56
+ key: generatedNodeCrypto.nodeKeys.decrypted.key,
57
+ contentKeyPacketSessionKey: generatedNodeCrypto.contentKey.decrypted.contentKeyPacketSessionKey,
58
+ signatureAddress: generatedNodeCrypto.signatureAddress,
59
+ },
60
+ newNodeInfo: {
61
+ parentUid: parentFolderUid,
62
+ name,
63
+ encryptedName: generatedNodeCrypto.encryptedNode.encryptedName,
64
+ hash: generatedNodeCrypto.encryptedNode.hash,
65
+ },
66
+ };
67
+ }
68
+
69
+ private async createDraftOnAPI(
70
+ parentFolderUid: string,
71
+ parentHashKey: Uint8Array,
72
+ name: string,
73
+ metadata: UploadMetadata,
74
+ generatedNodeCrypto: NodeCrypto,
75
+ ): Promise<{
76
+ nodeUid: string,
77
+ nodeRevisionUid: string,
78
+ }> {
79
+ try {
80
+ const result = await this.apiService.createDraft(parentFolderUid, {
81
+ armoredEncryptedName: generatedNodeCrypto.encryptedNode.encryptedName,
82
+ hash: generatedNodeCrypto.encryptedNode.hash,
83
+ mediaType: metadata.mediaType,
84
+ intendedUploadSize: metadata.expectedSize,
85
+ armoredNodeKey: generatedNodeCrypto.nodeKeys.encrypted.armoredKey,
86
+ armoredNodePassphrase: generatedNodeCrypto.nodeKeys.encrypted.armoredPassphrase,
87
+ armoredNodePassphraseSignature: generatedNodeCrypto.nodeKeys.encrypted.armoredPassphraseSignature,
88
+ base64ContentKeyPacket: generatedNodeCrypto.contentKey.encrypted.base64ContentKeyPacket,
89
+ armoredContentKeyPacketSignature: generatedNodeCrypto.contentKey.encrypted.armoredContentKeyPacketSignature,
90
+ signatureEmail: generatedNodeCrypto.signatureAddress.email,
91
+ // FIXME: client UID
92
+ });
93
+ return result;
94
+ } catch (error: unknown) {
95
+ if (error instanceof ValidationError) {
96
+ if (error.code === ErrorCode.ALREADY_EXISTS) {
97
+ this.logger.info(`Node with given name already exists`);
98
+ const availableName = await this.findAvailableName(
99
+ parentFolderUid,
100
+ parentHashKey,
101
+ name,
102
+ generatedNodeCrypto.encryptedNode.hash,
103
+ );
104
+
105
+ // If there is existing draft created by this client,
106
+ // automatically delete it and try to create a new one
107
+ // with the same name again.
108
+ if (availableName.existingDraftNodeUid) {
109
+ let deleteFailed = false;
110
+ try {
111
+ this.logger.warn(`Deleting existing draft node ${availableName.existingDraftNodeUid}`);
112
+ await this.apiService.deleteDraft(availableName.existingDraftNodeUid);
113
+ } catch (deleteDraftError: unknown) {
114
+ // Do not throw, let return the next available name to the client.
115
+ deleteFailed = true;
116
+ this.logger.error('Failed to delete existing draft node', deleteDraftError);
117
+ }
118
+ if (!deleteFailed) {
119
+ return this.createDraftOnAPI(parentFolderUid, parentHashKey, name, metadata, generatedNodeCrypto);
120
+ }
121
+ }
122
+
123
+ // If there is existing node, return special error
124
+ // that includes the available name the client can use.
125
+ throw new NodeAlreadyExistsValidationError(
126
+ error.message,
127
+ error.code,
128
+ availableName.availableName,
129
+ );
130
+ }
131
+ }
132
+ throw error;
133
+ }
134
+ }
135
+
136
+ private async findAvailableName(parentFolderUid: string, parentHashKey: Uint8Array, name: string, nameHash: string): Promise<{
137
+ availableName: string,
138
+ existingDraftNodeUid?: string,
139
+ }> {
140
+ const [namePart, extension] = splitExtension(name);
141
+
142
+ const batchSize = 10;
143
+ let startIndex = 1;
144
+ while (true) {
145
+ const namesToCheck = [];
146
+ for (let i = startIndex; i < startIndex + batchSize; i++) {
147
+ namesToCheck.push(joinNameAndExtension(namePart, i, extension));
148
+ }
149
+
150
+ const hashesToCheck = await this.cryptoService.generateNameHashes(parentHashKey, namesToCheck);
151
+
152
+ const { pendingHashes, availalbleHashes } = await this.apiService.checkAvailableHashes(
153
+ parentFolderUid,
154
+ [
155
+ ...hashesToCheck.map(({ hash }) => hash),
156
+ // Adding the current name hash to get the existing draft
157
+ // node UID if it exists.
158
+ ...startIndex ? [nameHash] : [],
159
+ ],
160
+ );
161
+
162
+ if (!availalbleHashes.length) {
163
+ startIndex += batchSize;
164
+ continue;
165
+ }
166
+
167
+ const availableHash = hashesToCheck.find(({ hash }) => hash === availalbleHashes[0]);
168
+ if (!availableHash) {
169
+ throw Error('Backend returned unexpected hash');
170
+ }
171
+
172
+ // FIXME: use client UID to ensure its own pending draft
173
+ const ownPendingHash = pendingHashes.find(({ hash }) => hash === nameHash);
174
+ return {
175
+ availableName: availableHash.name,
176
+ existingDraftNodeUid: ownPendingHash?.nodeUid,
177
+ }
178
+ }
179
+ }
180
+
181
+ async deleteDraftNode(nodeUid: string): Promise<void> {
182
+ try {
183
+ await this.apiService.deleteDraft(nodeUid);
184
+ } catch (error: unknown) {
185
+ // Only log the error but do not fail the operation as we are
186
+ // deleting draft only when somethign fails and original error
187
+ // will bubble up.
188
+ this.logger.error('Failed to delete draft node', error);
189
+ }
190
+ }
191
+
192
+ async createDraftRevision(nodeUid: string, metadata: UploadMetadata): Promise<NodeRevisionDraft> {
193
+ const node = await this.nodesService.getNode(nodeUid);
194
+ const nodeKeys = await this.nodesService.getNodeKeys(nodeUid);
195
+
196
+ if (!node.activeRevision?.ok || !nodeKeys.contentKeyPacketSessionKey) {
197
+ throw new ValidationError(c('Error').t`Creating revisions in non-files is not allowed`);
198
+ }
199
+
200
+ const signatureAddress = await this.nodesService.getRootNodeEmailKey(nodeUid);
201
+
202
+ const { nodeRevisionUid } = await this.apiService.createDraftRevision(nodeUid, {
203
+ currentRevisionUid: node.activeRevision.value.uid,
204
+ intendedUploadSize: metadata.expectedSize,
205
+ });
206
+
207
+ return {
208
+ nodeUid,
209
+ nodeRevisionUid,
210
+ nodeKeys: {
211
+ key: nodeKeys.key,
212
+ contentKeyPacketSessionKey: nodeKeys.contentKeyPacketSessionKey,
213
+ signatureAddress: signatureAddress,
214
+ },
215
+ }
216
+ }
217
+
218
+ async deleteDraftRevision(nodeRevisionUid: string): Promise<void> {
219
+ try {
220
+ await this.apiService.deleteDraftRevision(nodeRevisionUid);
221
+ } catch (error: unknown) {
222
+ // Only log the error but do not fail the operation as we are
223
+ // deleting draft only when somethign fails and original error
224
+ // will bubble up.
225
+ this.logger.error('Failed to delete draft node revision', error);
226
+ }
227
+ }
228
+
229
+ async commitDraft(
230
+ nodeRevisionDraft: NodeRevisionDraft,
231
+ manifest: Uint8Array,
232
+ metadata: UploadMetadata,
233
+ extendedAttributes: {
234
+ modificationTime?: Date,
235
+ size?: number,
236
+ blockSizes?: number[],
237
+ digests?: {
238
+ sha1?: string,
239
+ },
240
+ },
241
+ encryptedSize: number,
242
+ ): Promise<void> {
243
+ const generatedExtendedAttributes = generateFileExtendedAttributes(extendedAttributes);
244
+ const nodeCommitCrypto = await this.cryptoService.commitFile(nodeRevisionDraft.nodeKeys, manifest, generatedExtendedAttributes);
245
+ await this.apiService.commitDraftRevision(nodeRevisionDraft.nodeRevisionUid, nodeCommitCrypto);
246
+
247
+ const activeRevision = resultOk<Revision, Error>({
248
+ uid: nodeRevisionDraft.nodeRevisionUid,
249
+ state: RevisionState.Active,
250
+ creationTime: new Date(),
251
+ storageSize: encryptedSize,
252
+ contentAuthor: resultOk(nodeCommitCrypto.signatureEmail),
253
+ claimedSize: metadata.expectedSize,
254
+ claimedModificationTime: extendedAttributes.modificationTime,
255
+ claimedDigests: {
256
+ sha1: extendedAttributes.digests?.sha1,
257
+ },
258
+ });
259
+ if (nodeRevisionDraft.newNodeInfo) {
260
+ const node: DecryptedNode = {
261
+ // Internal metadata
262
+ hash: nodeRevisionDraft.newNodeInfo.hash,
263
+ encryptedName: nodeRevisionDraft.newNodeInfo.encryptedName,
264
+
265
+ // Basic node metadata
266
+ uid: nodeRevisionDraft.nodeUid,
267
+ parentUid: nodeRevisionDraft.newNodeInfo.parentUid,
268
+ type: NodeType.File,
269
+ mediaType: metadata.mediaType,
270
+ creationTime: new Date(),
271
+ totalStorageSize: encryptedSize,
272
+
273
+ // Share node metadata
274
+ isShared: false,
275
+ directMemberRole: MemberRole.Inherited,
276
+
277
+ // Decrypted metadata
278
+ isStale: false,
279
+ keyAuthor: resultOk(nodeRevisionDraft.nodeKeys.signatureAddress.email),
280
+ nameAuthor: resultOk(nodeRevisionDraft.nodeKeys.signatureAddress.email),
281
+ name: resultOk(nodeRevisionDraft.newNodeInfo.name),
282
+
283
+ activeRevision,
284
+ }
285
+ await this.nodesEvents.nodeCreated(node);
286
+ } else {
287
+ await this.nodesEvents.nodeUpdated({
288
+ uid: nodeRevisionDraft.nodeUid,
289
+ activeRevision,
290
+ });
291
+ }
292
+ }
293
+ }
294
+
295
+ /**
296
+ * Split a filename into `[name, extension]`
297
+ */
298
+ function splitExtension(filename = ''): [string, string] {
299
+ const endIdx = filename.lastIndexOf('.');
300
+ if (endIdx === -1 || endIdx === filename.length-1) {
301
+ return [filename, ''];
302
+ }
303
+ return [filename.slice(0, endIdx), filename.slice(endIdx + 1)];
304
+ };
305
+
306
+ /**
307
+ * Join a filename into `name (index).extension`
308
+ */
309
+ function joinNameAndExtension(name: string, index: number, extension: string): string {
310
+ if (!name && !extension) {
311
+ return `(${index})`;
312
+ }
313
+ if (!name) {
314
+ return `(${index}).${extension}`;
315
+ }
316
+ if (!extension) {
317
+ return `${name} (${index})`;
318
+ }
319
+ return `${name} (${index}).${extension}`;
320
+ }
@@ -0,0 +1,31 @@
1
+ import { waitForCondition } from '../wait';
2
+
3
+ /**
4
+ * A queue that limits the number of concurrent uploads.
5
+ *
6
+ * This is used to limit the number of concurrent uploads to avoid
7
+ * overloading the server, or get rate limited.
8
+ *
9
+ * Each file upload consumes memory and is limited by the number of
10
+ * concurrent block uploads for each file.
11
+ *
12
+ * This queue is straitforward and does not have any priority mechanism
13
+ * or other features, such as limiting total number of blocks being
14
+ * uploaded. That is something we want to add in the future to be
15
+ * more performant for many small file uploads.
16
+ */
17
+ const MAX_CONCURRENT_UPLOADS = 5;
18
+
19
+ export class UploadQueue {
20
+ private capacity = 0;
21
+
22
+ // TODO: use expected size to control the size of the queue
23
+ async waitForCapacity(signal?: AbortSignal) {
24
+ await waitForCondition(() => this.capacity < MAX_CONCURRENT_UPLOADS, signal);
25
+ this.capacity++;
26
+ }
27
+
28
+ releaseCapacity() {
29
+ this.capacity--;
30
+ }
31
+ }
@@ -0,0 +1,129 @@
1
+ import { RateLimitedError, ValidationError, IntegrityError } from '../../errors';
2
+ import { ProtonDriveTelemetry } from '../../interface';
3
+ import { APIHTTPError } from '../apiService';
4
+ import { SharesService } from './interface';
5
+ import { UploadTelemetry } from './telemetry';
6
+
7
+ describe('UploadTelemetry', () => {
8
+ let mockTelemetry: jest.Mocked<ProtonDriveTelemetry>;
9
+ let sharesService: jest.Mocked<SharesService>;
10
+ let uploadTelemetry: UploadTelemetry;
11
+
12
+ const parentNodeUid = 'volumeId~parentNodeId';
13
+ const revisionUid = 'volumeId~nodeId~revisionId';
14
+
15
+ beforeEach(() => {
16
+ mockTelemetry = {
17
+ logEvent: jest.fn(),
18
+ getLogger: jest.fn().mockReturnValue({
19
+ info: jest.fn(),
20
+ warn: jest.fn(),
21
+ error: jest.fn(),
22
+ debug: jest.fn(),
23
+ }),
24
+ } as unknown as jest.Mocked<ProtonDriveTelemetry>;
25
+
26
+ sharesService = {
27
+ getVolumeMetricContext: jest.fn().mockResolvedValue('own_volume'),
28
+ }
29
+
30
+ uploadTelemetry = new UploadTelemetry(mockTelemetry, sharesService);
31
+ });
32
+
33
+ it('should log failure during init (excludes uploaded size)', async () => {
34
+ await uploadTelemetry.uploadInitFailed(parentNodeUid, new Error('Failed'), 1000);
35
+
36
+ expect(mockTelemetry.logEvent).toHaveBeenCalledWith({
37
+ eventName: "upload",
38
+ context: "own_volume",
39
+ uploadedSize: 0,
40
+ expectedSize: 1000,
41
+ error: "unknown",
42
+ });
43
+ });
44
+
45
+ it('should log failure upload', async () => {
46
+ await uploadTelemetry.uploadFailed(revisionUid, new Error('Failed'), 500, 1000);
47
+
48
+ expect(mockTelemetry.logEvent).toHaveBeenCalledWith({
49
+ eventName: "upload",
50
+ context: "own_volume",
51
+ uploadedSize: 500,
52
+ expectedSize: 1000,
53
+ error: "unknown",
54
+ });
55
+ });
56
+
57
+ it('should log successful upload (excludes error)', async () => {
58
+ await uploadTelemetry.uploadFinished(revisionUid, 1000);
59
+
60
+ expect(mockTelemetry.logEvent).toHaveBeenCalledWith({
61
+ eventName: "upload",
62
+ context: "own_volume",
63
+ uploadedSize: 1000,
64
+ expectedSize: 1000,
65
+ });
66
+ });
67
+
68
+ describe('detect error category', () => {
69
+ const verifyErrorCategory = (error: string) => {
70
+ expect(mockTelemetry.logEvent).toHaveBeenCalledWith(
71
+ expect.objectContaining({
72
+ error,
73
+ })
74
+ );
75
+ };
76
+
77
+ it('should ignore ValidationError', async () => {
78
+ const error = new ValidationError('Validation error');
79
+ await uploadTelemetry.uploadFailed(revisionUid, error, 500, 1000);
80
+ expect(mockTelemetry.logEvent).not.toHaveBeenCalled();
81
+ });
82
+
83
+ it('should ignore AbortError', async () => {
84
+ const error = new Error('Aborted');
85
+ error.name = 'AbortError';
86
+ await uploadTelemetry.uploadFailed(revisionUid, error, 500, 1000);
87
+
88
+ expect(mockTelemetry.logEvent).not.toHaveBeenCalled();
89
+ });
90
+
91
+ it('should detect "rate_limited" error for RateLimitedError', async () => {
92
+ const error = new RateLimitedError('Rate limited');
93
+ await uploadTelemetry.uploadFailed(revisionUid, error, 500, 1000);
94
+ verifyErrorCategory('rate_limited');
95
+ });
96
+
97
+ it('should detect "integrity_error" for IntegrityError', async () => {
98
+ const error = new IntegrityError('Integrity check failed');
99
+ await uploadTelemetry.uploadFailed(revisionUid, error, 500, 1000);
100
+ verifyErrorCategory('integrity_error');
101
+ });
102
+
103
+ it('should detect "4xx" error for APIHTTPError with 4xx status code', async () => {
104
+ const error = new APIHTTPError('Client error', 404);
105
+ await uploadTelemetry.uploadFailed(revisionUid, error, 500, 1000);
106
+ verifyErrorCategory('4xx');
107
+ });
108
+
109
+ it('should detect "5xx" error for APIHTTPError with 5xx status code', async () => {
110
+ const error = new APIHTTPError('Server error', 500);
111
+ await uploadTelemetry.uploadFailed(revisionUid, error, 500, 1000);
112
+ verifyErrorCategory('5xx');
113
+ });
114
+
115
+ it('should detect "server_error" for TimeoutError', async () => {
116
+ const error = new Error('Timeout');
117
+ error.name = 'TimeoutError';
118
+ await uploadTelemetry.uploadFailed(revisionUid, error, 500, 1000);
119
+ verifyErrorCategory('server_error');
120
+ });
121
+
122
+ it('should detect "network_error" for NetworkError', async () => {
123
+ const error = new Error('Network error');
124
+ error.name = 'NetworkError';
125
+ await uploadTelemetry.uploadFailed(revisionUid, error, 500, 1000);
126
+ verifyErrorCategory('network_error');
127
+ });
128
+ });
129
+ });
@@ -0,0 +1,121 @@
1
+ import { RateLimitedError, ValidationError, IntegrityError } from "../../errors";
2
+ import { ProtonDriveTelemetry, MetricsUploadErrorType, Logger } from "../../interface";
3
+ import { LoggerWithPrefix } from "../../telemetry";
4
+ import { APIHTTPError } from '../apiService';
5
+ import { splitNodeUid, splitNodeRevisionUid } from "../uids";
6
+ import { SharesService } from "./interface";
7
+
8
+ export class UploadTelemetry {
9
+ private logger: Logger;
10
+
11
+ constructor(private telemetry: ProtonDriveTelemetry, private sharesService: SharesService) {
12
+ this.telemetry = telemetry;
13
+ this.logger = this.telemetry.getLogger("download");
14
+ this.sharesService = sharesService;
15
+ }
16
+
17
+ getLoggerForRevision(revisionUid: string) {
18
+ const logger = this.telemetry.getLogger("upload");
19
+ return new LoggerWithPrefix(logger, `revision ${revisionUid}`);
20
+ }
21
+
22
+ logBlockVerificationError(retryHelped: boolean) {
23
+ this.telemetry.logEvent({
24
+ eventName: 'blockVerificationError',
25
+ retryHelped,
26
+ });
27
+ }
28
+
29
+ async uploadInitFailed(parentFolderUid: string, error: unknown, expectedSize: number) {
30
+ const { volumeId } = splitNodeUid(parentFolderUid);
31
+ const errorCategory = getErrorCategory(error);
32
+
33
+ // No error category means ignored error from telemetry.
34
+ // For example, aborted request.
35
+ if (!errorCategory) {
36
+ return;
37
+ }
38
+
39
+ await this.sendTelemetry(volumeId, {
40
+ uploadedSize: 0,
41
+ expectedSize,
42
+ error: errorCategory,
43
+ });
44
+ }
45
+
46
+ async uploadFailed(revisionUid: string, error: unknown, uploadedSize: number, expectedSize: number) {
47
+ const { volumeId } = splitNodeRevisionUid(revisionUid);
48
+ const errorCategory = getErrorCategory(error);
49
+
50
+ // No error category means ignored error from telemetry.
51
+ // For example, aborted request.
52
+ if (!errorCategory) {
53
+ return;
54
+ }
55
+
56
+ await this.sendTelemetry(volumeId, {
57
+ uploadedSize,
58
+ expectedSize,
59
+ error: errorCategory,
60
+ });
61
+ }
62
+
63
+ async uploadFinished(revisionUid: string, uploadedSize: number) {
64
+ const { volumeId } = splitNodeRevisionUid(revisionUid);
65
+ await this.sendTelemetry(volumeId, {
66
+ uploadedSize,
67
+ expectedSize: uploadedSize,
68
+ });
69
+ }
70
+
71
+ private async sendTelemetry(volumeId: string, options: {
72
+ uploadedSize: number,
73
+ expectedSize: number,
74
+ error?: MetricsUploadErrorType,
75
+ }) {
76
+ let context;
77
+ try {
78
+ context = await this.sharesService.getVolumeMetricContext(volumeId);
79
+ } catch (error: unknown) {
80
+ this.logger.error('Failed to get metric context', error);
81
+ }
82
+
83
+ this.telemetry.logEvent({
84
+ eventName: 'upload',
85
+ context,
86
+ ...options,
87
+ });
88
+ }
89
+ }
90
+
91
+ function getErrorCategory(error: unknown): MetricsUploadErrorType | undefined {
92
+ if (error instanceof ValidationError) {
93
+ return undefined;
94
+ }
95
+ if (error instanceof RateLimitedError) {
96
+ return 'rate_limited';
97
+ }
98
+ if (error instanceof IntegrityError) {
99
+ return 'integrity_error';
100
+ }
101
+ if (error instanceof APIHTTPError) {
102
+ if (error.statusCode >= 400 && error.statusCode < 500) {
103
+ return '4xx';
104
+ }
105
+ if (error.statusCode >= 500) {
106
+ return '5xx';
107
+ }
108
+ }
109
+ if (error instanceof Error) {
110
+ if (error.name === 'TimeoutError') {
111
+ return 'server_error';
112
+ }
113
+ if (error.name === 'OfflineError' || error.name === 'NetworkError' || error.message?.toLowerCase() === 'network error') {
114
+ return 'network_error';
115
+ }
116
+ if (error.name === 'AbortError') {
117
+ return undefined;
118
+ }
119
+ }
120
+ return 'unknown';
121
+ }
@@ -0,0 +1,9 @@
1
+ export function mergeUint8Arrays(arrays: Uint8Array[]) {
2
+ const length = arrays.reduce((sum, arr) => sum + arr.length, 0);
3
+ const chunksAll = new Uint8Array(length);
4
+ arrays.reduce((position, arr) => {
5
+ chunksAll.set(arr, position);
6
+ return position + arr.length;
7
+ }, 0);
8
+ return chunksAll;
9
+ }
@@ -0,0 +1,21 @@
1
+ import { waitForCondition } from "./wait";
2
+
3
+ describe('waitForCondition', () => {
4
+ it('should resolve immediately if condition is met', async () => {
5
+ const callback = jest.fn().mockReturnValue(true);
6
+ await waitForCondition(callback);
7
+ expect(callback).toHaveBeenCalled();
8
+ });
9
+
10
+ it('should resolve after condition is met', async () => {
11
+ const callback = jest.fn().mockReturnValueOnce(false).mockReturnValueOnce(true);
12
+ await waitForCondition(callback);
13
+ expect(callback).toHaveBeenCalledTimes(2);
14
+ });
15
+
16
+ it('should reject if signal is aborted', async () => {
17
+ const signal = { aborted: true } as any as AbortSignal;
18
+ const callback = jest.fn().mockReturnValue(false);
19
+ await expect(waitForCondition(callback, signal)).rejects.toThrow('aborted');
20
+ });
21
+ });
@@ -0,0 +1,26 @@
1
+ import { AbortError } from "../errors";
2
+
3
+ const WAIT_TIME = 50;
4
+
5
+ export function waitForCondition(callback: () => boolean, signal?: AbortSignal) {
6
+ return new Promise<void>((resolve, reject) => {
7
+ const waitForCondition = () => {
8
+ if (signal?.aborted) {
9
+ return reject(new AbortError());
10
+ }
11
+ if (callback()) {
12
+ return resolve();
13
+ }
14
+ setTimeout(waitForCondition, WAIT_TIME);
15
+ };
16
+ waitForCondition();
17
+ });
18
+ }
19
+
20
+ export async function waitSeconds(seconds: number){
21
+ return wait(seconds * 1000);
22
+ }
23
+
24
+ export async function wait(miliseconds: number){
25
+ return new Promise<void>((resolve) => setTimeout(resolve, miliseconds));
26
+ }