@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,455 @@
1
+ import { c } from "ttag";
2
+
3
+ import { ProtonDriveError, ValidationError } from "../../errors";
4
+ import { Logger, NodeResult } from "../../interface";
5
+ import { RevisionState } from "../../interface/nodes";
6
+ import { DriveAPIService, drivePaths, isCodeOk, nodeTypeNumberToNodeType, permissionsToDirectMemberRole } from "../apiService";
7
+ import { splitNodeUid, makeNodeUid, makeNodeRevisionUid, splitNodeRevisionUid, makeNodeThumbnailUid } from "../uids";
8
+ import { EncryptedNode, EncryptedRevision, Thumbnail } from "./interface";
9
+
10
+ type PostLoadLinksMetadataRequest = Extract<drivePaths['/drive/v2/volumes/{volumeID}/links']['post']['requestBody'], { 'content': object }>['content']['application/json'];
11
+ type PostLoadLinksMetadataResponse = drivePaths['/drive/v2/volumes/{volumeID}/links']['post']['responses']['200']['content']['application/json'];
12
+
13
+ type GetChildrenResponse = drivePaths['/drive/v2/volumes/{volumeID}/folders/{linkID}/children']['get']['responses']['200']['content']['application/json'];
14
+
15
+ type GetTrashedNodesResponse = drivePaths['/drive/volumes/{volumeID}/trash']['get']['responses']['200']['content']['application/json'];
16
+
17
+ type PutRenameNodeRequest = Extract<drivePaths['/drive/v2/volumes/{volumeID}/links/{linkID}/rename']['put']['requestBody'], { 'content': object }>['content']['application/json'];
18
+ type PutRenameNodeResponse = drivePaths['/drive/v2/volumes/{volumeID}/links/{linkID}/rename']['put']['responses']['200']['content']['application/json'];
19
+
20
+ type PutMoveNodeRequest = Extract<drivePaths['/drive/v2/volumes/{volumeID}/links/{linkID}/move']['put']['requestBody'], { 'content': object }>['content']['application/json'];
21
+ type PutMoveNodeResponse = drivePaths['/drive/v2/volumes/{volumeID}/links/{linkID}/move']['put']['responses']['200']['content']['application/json'];
22
+
23
+ type PostTrashNodesRequest = Extract<drivePaths['/drive/v2/volumes/{volumeID}/trash_multiple']['post']['requestBody'], { 'content': object }>['content']['application/json'];
24
+ type PostTrashNodesResponse = drivePaths['/drive/v2/volumes/{volumeID}/trash_multiple']['post']['responses']['200']['content']['application/json'];
25
+
26
+ type PutRestoreNodesRequest = Extract<drivePaths['/drive/v2/volumes/{volumeID}/trash/restore_multiple']['put']['requestBody'], { 'content': object }>['content']['application/json'];
27
+ type PutRestoreNodesResponse = drivePaths['/drive/v2/volumes/{volumeID}/trash/restore_multiple']['put']['responses']['200']['content']['application/json'];
28
+
29
+ type PostDeleteNodesRequest = Extract<drivePaths['/drive/v2/volumes/{volumeID}/trash/delete_multiple']['post']['requestBody'], { 'content': object }>['content']['application/json'];
30
+ type PostDeleteNodesResponse = drivePaths['/drive/v2/volumes/{volumeID}/trash/delete_multiple']['post']['responses']['200']['content']['application/json'];
31
+
32
+ type PostCreateFolderRequest = Extract<drivePaths['/drive/v2/volumes/{volumeID}/folders']['post']['requestBody'], { 'content': object }>['content']['application/json'];
33
+ type PostCreateFolderResponse = drivePaths['/drive/v2/volumes/{volumeID}/folders']['post']['responses']['200']['content']['application/json'];
34
+
35
+ type GetRevisionResponse = drivePaths['/drive/v2/volumes/{volumeID}/files/{linkID}/revisions/{revisionID}']['get']['responses']['200']['content']['application/json'];
36
+ type GetRevisionsResponse = drivePaths['/drive/v2/volumes/{volumeID}/files/{linkID}/revisions']['get']['responses']['200']['content']['application/json'];
37
+ enum APIRevisionState {
38
+ Draft = 0,
39
+ Active = 1,
40
+ Obsolete = 2,
41
+ }
42
+
43
+ type PostRestoreRevisionResponse = drivePaths['/drive/v2/volumes/{volumeID}/files/{linkID}/revisions/{revisionID}/restore']['post']['responses']['202']['content']['application/json'];
44
+
45
+ type DeleteRevisionResponse = drivePaths['/drive/v2/volumes/{volumeID}/files/{linkID}/revisions/{revisionID}']['delete']['responses']['200']['content']['application/json'];
46
+
47
+ /**
48
+ * Provides API communication for fetching and manipulating nodes metadata.
49
+ *
50
+ * The service is responsible for transforming local objects to API payloads
51
+ * and vice versa. It should not contain any business logic.
52
+ */
53
+ export class NodeAPIService {
54
+ constructor(private logger: Logger, private apiService: DriveAPIService) {
55
+ this.logger = logger;
56
+ this.apiService = apiService;
57
+ }
58
+
59
+ async getNode(nodeUid: string, signal?: AbortSignal): Promise<EncryptedNode> {
60
+ const nodesGenerator = this.iterateNodes([nodeUid], signal);
61
+ const result = await nodesGenerator.next();
62
+ await nodesGenerator.return("finish");
63
+ return result.value;
64
+ }
65
+
66
+ // Improvement requested: split into multiple calls for many nodes.
67
+ async* iterateNodes(nodeUids: string[], signal?: AbortSignal): AsyncGenerator<EncryptedNode> {
68
+ const allNodeIds = nodeUids.map(splitNodeUid);
69
+
70
+ const nodeIdsByVolumeId = new Map<string, string[]>();
71
+ for (const { volumeId, nodeId } of allNodeIds) {
72
+ if (!nodeIdsByVolumeId.has(volumeId)) {
73
+ nodeIdsByVolumeId.set(volumeId, []);
74
+ }
75
+ nodeIdsByVolumeId.get(volumeId)?.push(nodeId);
76
+ }
77
+
78
+ // If the API returns node that is not recognised, it is returned as
79
+ // an error, but first all nodes that are recognised are yielded.
80
+ // Thus we capture all errors and throw them at the end of iteration.
81
+ const errors = [];
82
+
83
+ for (const [volumeId, nodeIds] of nodeIdsByVolumeId.entries()) {
84
+ const response = await this.apiService.post<PostLoadLinksMetadataRequest, PostLoadLinksMetadataResponse>(`drive/v2/volumes/${volumeId}/links`, {
85
+ LinkIDs: nodeIds,
86
+ }, signal);
87
+
88
+ for (const link of response.Links) {
89
+ try {
90
+ yield linkToEncryptedNode(this.logger, volumeId, link);
91
+ } catch (error: unknown) {
92
+ this.logger.error(`Failed to transform node ${link.Link.LinkID}`, error);
93
+ errors.push(error);
94
+ }
95
+ }
96
+ }
97
+
98
+
99
+ if (errors.length) {
100
+ this.logger.warn(`Failed to load ${errors.length} nodes`);
101
+ throw new ProtonDriveError(c('Error').t`Failed to load some nodes`, { cause: errors });
102
+ }
103
+ }
104
+
105
+ // Improvement requested: load next page sooner before all IDs are yielded.
106
+ async *iterateChildrenNodeUids(parentNodeUid: string, signal?: AbortSignal): AsyncGenerator<string> {
107
+ const { volumeId, nodeId } = splitNodeUid(parentNodeUid);
108
+
109
+ let anchor = "";
110
+ while (true) {
111
+ const response = await this.apiService.get<GetChildrenResponse>(`drive/v2/volumes/${volumeId}/folders/${nodeId}/children?${anchor ? `AnchorID=${anchor}` : ''}`, signal);
112
+ for (const linkID of response.LinkIDs) {
113
+ yield makeNodeUid(volumeId, linkID);
114
+ }
115
+
116
+ if (!response.More || !response.AnchorID) {
117
+ break;
118
+ }
119
+ anchor = response.AnchorID;
120
+ }
121
+ }
122
+
123
+ // Improvement requested: load next page sooner before all IDs are yielded.
124
+ async *iterateTrashedNodeUids(volumeId: string, signal?: AbortSignal): AsyncGenerator<string> {
125
+ let page = 0;
126
+ while (true) {
127
+ const response = await this.apiService.get<GetTrashedNodesResponse>(`drive/volumes/${volumeId}/trash?Page=${page}`, signal);
128
+
129
+ // The API returns items per shares which is not straightforward to
130
+ // count if there is another page. We had mistakes in the past, thus
131
+ // we rather end when the page is fully empty.
132
+ // The new API endpoint should not split per shares anymore and adopt
133
+ // the new pagination model with More/Anchor. For now, this is not
134
+ // the most efficient way, but should be with us only for a short time.
135
+ let hasItems = false;
136
+
137
+ for (const linksPerShare of response.Trash) {
138
+ for (const linkId of linksPerShare.LinkIDs) {
139
+ yield makeNodeUid(volumeId, linkId);
140
+ hasItems = true;
141
+ }
142
+ }
143
+
144
+ if (!hasItems) {
145
+ break;
146
+ }
147
+ page++;
148
+ }
149
+ }
150
+
151
+ async renameNode(
152
+ nodeUid: string,
153
+ originalNode: {
154
+ hash?: string,
155
+ },
156
+ newNode: {
157
+ encryptedName: string,
158
+ nameSignatureEmail: string,
159
+ hash?: string,
160
+ },
161
+ signal?: AbortSignal,
162
+ ): Promise<void> {
163
+ const { volumeId, nodeId } = splitNodeUid(nodeUid);
164
+
165
+ await this.apiService.put<
166
+ Omit<PutRenameNodeRequest, "SignatureAddress" | "MIMEType">,
167
+ PutRenameNodeResponse
168
+ >(`drive/v2/volumes/${volumeId}/links/${nodeId}/rename`, {
169
+ Name: newNode.encryptedName,
170
+ NameSignatureEmail: newNode.nameSignatureEmail,
171
+ Hash: newNode.hash,
172
+ OriginalHash: originalNode.hash || null,
173
+ }, signal);
174
+ }
175
+
176
+ async moveNode(
177
+ nodeUid: string,
178
+ oldNode: {
179
+ hash: string,
180
+ },
181
+ newNode: {
182
+ parentUid: string,
183
+ armoredNodePassphrase: string,
184
+ armoredNodePassphraseSignature?: string,
185
+ signatureEmail?: string,
186
+ encryptedName: string,
187
+ nameSignatureEmail?: string,
188
+ hash: string,
189
+ contentHash?: string,
190
+ },
191
+ signal?: AbortSignal,
192
+ ): Promise<void> {
193
+ const { volumeId, nodeId } = splitNodeUid(nodeUid);
194
+ const { nodeId: newParentNodeId } = splitNodeUid(newNode.parentUid);
195
+
196
+ await this.apiService.put<
197
+ Omit<PutMoveNodeRequest, "SignatureAddress" | "MIMEType">,
198
+ PutMoveNodeResponse
199
+ >(`drive/v2/volumes/${volumeId}/links/${nodeId}/move`, {
200
+ ParentLinkID: newParentNodeId,
201
+ NodePassphrase: newNode.armoredNodePassphrase,
202
+ // @ts-expect-error: API accepts NodePassphraseSignature as optional.
203
+ NodePassphraseSignature: newNode.armoredNodePassphraseSignature,
204
+ // @ts-expect-error: API accepts SignatureEmail as optional.
205
+ SignatureEmail: newNode.signatureEmail,
206
+ Name: newNode.encryptedName,
207
+ // @ts-expect-error: API accepts NameSignatureEmail as optional.
208
+ NameSignatureEmail: newNode.nameSignatureEmail,
209
+ Hash: newNode.hash,
210
+ OriginalHash: oldNode.hash,
211
+ ContentHash: newNode.contentHash || null,
212
+ }, signal);
213
+ }
214
+
215
+ // Improvement requested: split into multiple calls for many nodes.
216
+ async* trashNodes(nodeUids: string[], signal?: AbortSignal): AsyncGenerator<NodeResult> {
217
+ const nodeIds = nodeUids.map(splitNodeUid);
218
+ const volumeId = assertAndGetSingleVolumeId(c('Operation').t`Trashing items`, nodeIds);
219
+
220
+ const response = await this.apiService.post<
221
+ PostTrashNodesRequest,
222
+ PostTrashNodesResponse
223
+ >(`drive/v2/volumes/${volumeId}/trash_multiple`, {
224
+ LinkIDs: nodeIds.map(({ nodeId }) => nodeId),
225
+ }, signal);
226
+
227
+ // TODO: remove `as` when backend fixes OpenAPI schema.
228
+ yield* handleResponseErrors(nodeUids, volumeId, response.Responses as LinkResponse[]);
229
+ }
230
+
231
+ // Improvement requested: split into multiple calls for many nodes.
232
+ async* restoreNodes(nodeUids: string[], signal?: AbortSignal): AsyncGenerator<NodeResult> {
233
+ const nodeIds = nodeUids.map(splitNodeUid);
234
+ const volumeId = assertAndGetSingleVolumeId(c('Operation').t`Restoring items`, nodeIds);
235
+
236
+ const response = await this.apiService.put<
237
+ PutRestoreNodesRequest,
238
+ PutRestoreNodesResponse
239
+ >(`drive/v2/volumes/${volumeId}/trash/restore_multiple`, {
240
+ LinkIDs: nodeIds.map(({ nodeId }) => nodeId),
241
+ }, signal);
242
+
243
+ // TODO: remove `as` when backend fixes OpenAPI schema.
244
+ yield* handleResponseErrors(nodeUids, volumeId, response.Responses as LinkResponse[]);
245
+ }
246
+
247
+ // Improvement requested: split into multiple calls for many nodes.
248
+ async* deleteNodes(nodeUids: string[], signal?: AbortSignal): AsyncGenerator<NodeResult> {
249
+ const nodeIds = nodeUids.map(splitNodeUid);
250
+ const volumeId = assertAndGetSingleVolumeId(c('Operation').t`Deleting items`, nodeIds);
251
+
252
+ const response = await this.apiService.post<
253
+ PostDeleteNodesRequest,
254
+ PostDeleteNodesResponse
255
+ >(`drive/v2/volumes/${volumeId}/trash/delete_multiple`, {
256
+ LinkIDs: nodeIds.map(({ nodeId }) => nodeId),
257
+ }, signal);
258
+
259
+ // TODO: remove `as` when backend fixes OpenAPI schema.
260
+ yield* handleResponseErrors(nodeUids, volumeId, response.Responses as LinkResponse[]);
261
+ }
262
+
263
+ async createFolder(
264
+ parentUid: string,
265
+ newNode: {
266
+ armoredKey: string,
267
+ armoredHashKey: string,
268
+ armoredNodePassphrase: string,
269
+ armoredNodePassphraseSignature: string,
270
+ signatureEmail: string,
271
+ encryptedName: string,
272
+ hash: string,
273
+ armoredExtendedAttributes?: string,
274
+ },
275
+ ): Promise<string> {
276
+ const { volumeId, nodeId: parentId } = splitNodeUid(parentUid);
277
+
278
+ const response = await this.apiService.post<
279
+ PostCreateFolderRequest,
280
+ PostCreateFolderResponse
281
+ >(`drive/v2/volumes/${volumeId}/folders`, {
282
+ ParentLinkID: parentId,
283
+ NodeKey: newNode.armoredKey,
284
+ NodeHashKey: newNode.armoredHashKey,
285
+ NodePassphrase: newNode.armoredNodePassphrase,
286
+ NodePassphraseSignature: newNode.armoredNodePassphraseSignature,
287
+ SignatureEmail: newNode.signatureEmail,
288
+ Name: newNode.encryptedName,
289
+ Hash: newNode.hash,
290
+ // @ts-expect-error: XAttr is optional as undefined.
291
+ XAttr: newNode.armoredExtendedAttributes,
292
+ });
293
+
294
+ return makeNodeUid(volumeId, response.Folder.ID);
295
+ }
296
+
297
+ async getRevision(nodeRevisionUid: string, signal?: AbortSignal): Promise<EncryptedRevision> {
298
+ const { volumeId, nodeId, revisionId } = splitNodeRevisionUid(nodeRevisionUid);
299
+
300
+ const response = await this.apiService.get<GetRevisionResponse>(`drive/v2/volumes/${volumeId}/files/${nodeId}/revisions/${revisionId}?NoBlockUrls=true`, signal);
301
+ return transformRevisionResponse(volumeId, nodeId, response.Revision);
302
+ }
303
+
304
+ async getRevisions(nodeUid: string, signal?: AbortSignal): Promise<EncryptedRevision[]> {
305
+ const { volumeId, nodeId } = splitNodeUid(nodeUid);
306
+
307
+ const response = await this.apiService.get<GetRevisionsResponse>(`drive/v2/volumes/${volumeId}/files/${nodeId}/revisions`, signal);
308
+ return response.Revisions
309
+ .filter((revision) => revision.State === APIRevisionState.Active || revision.State === APIRevisionState.Obsolete)
310
+ .map((revision) => transformRevisionResponse(volumeId, nodeId, revision));
311
+ }
312
+
313
+ async restoreRevision(nodeRevisionUid: string): Promise<void> {
314
+ const { volumeId, nodeId, revisionId } = splitNodeRevisionUid(nodeRevisionUid);
315
+
316
+ await this.apiService.post<
317
+ undefined,
318
+ PostRestoreRevisionResponse
319
+ >(`drive/v2/volumes/${volumeId}/files/${nodeId}/revisions/${revisionId}/restore`);
320
+ }
321
+
322
+ async deleteRevision(nodeRevisionUid: string): Promise<void> {
323
+ const { volumeId, nodeId, revisionId } = splitNodeRevisionUid(nodeRevisionUid);
324
+
325
+ await this.apiService.delete<DeleteRevisionResponse>(`drive/v2/volumes/${volumeId}/files/${nodeId}/revisions/${revisionId}`);
326
+ }
327
+ }
328
+
329
+ function assertAndGetSingleVolumeId(operationForErrorMessage: string, nodeIds: { volumeId: string }[]): string {
330
+ const uniqueVolumeIds = new Set(nodeIds.map(({ volumeId }) => volumeId));
331
+ if (uniqueVolumeIds.size !== 1) {
332
+ throw new ValidationError(c('Error').t`${operationForErrorMessage} from multiple sections is not allowed`);
333
+ }
334
+ const volumeId = nodeIds[0].volumeId;
335
+ return volumeId;
336
+ }
337
+
338
+ type LinkResponse = {
339
+ LinkID: string,
340
+ Response: {
341
+ Code?: number,
342
+ Error?: string,
343
+ }
344
+ };
345
+
346
+ function* handleResponseErrors(nodeUids: string[], volumeId: string, responses: LinkResponse[] = []): Generator<NodeResult> {
347
+ const errors = new Map();
348
+
349
+ responses.forEach((response) => {
350
+ if (!response.Response.Code || !isCodeOk(response.Response.Code) || response.Response.Error) {
351
+ const nodeUid = makeNodeUid(volumeId, response.LinkID);
352
+ errors.set(nodeUid, response.Response.Error || c('Error').t`Unknown error ${response.Response.Code}`);
353
+ }
354
+ });
355
+
356
+ for (const uid of nodeUids) {
357
+ const error = errors.get(uid);
358
+ if (error) {
359
+ yield { uid, ok: false, error };
360
+ } else {
361
+ yield { uid, ok: true };
362
+ }
363
+ }
364
+ }
365
+
366
+ function linkToEncryptedNode(logger: Logger, volumeId: string, link: PostLoadLinksMetadataResponse['Links'][0]): EncryptedNode {
367
+ const baseNodeMetadata = {
368
+ // Internal metadata
369
+ hash: link.Link.NameHash || undefined,
370
+ encryptedName: link.Link.Name,
371
+
372
+ // Basic node metadata
373
+ uid: makeNodeUid(volumeId, link.Link.LinkID),
374
+ parentUid: link.Link.ParentLinkID ? makeNodeUid(volumeId, link.Link.ParentLinkID) : undefined,
375
+ type: nodeTypeNumberToNodeType(logger, link.Link.Type),
376
+ creationTime: new Date(link.Link.CreateTime*1000),
377
+ trashTime: link.Link.TrashTime ? new Date(link.Link.TrashTime*1000) : undefined,
378
+
379
+ // Sharing node metadata
380
+ shareId: link.Sharing?.ShareID || undefined,
381
+ isShared: !!link.Sharing,
382
+ directMemberRole: permissionsToDirectMemberRole(logger, link.Membership?.Permissions),
383
+ }
384
+ const baseCryptoNodeMetadata = {
385
+ signatureEmail: link.Link.SignatureEmail || undefined,
386
+ nameSignatureEmail: link.Link.NameSignatureEmail || undefined,
387
+ armoredKey: link.Link.NodeKey,
388
+ armoredNodePassphrase: link.Link.NodePassphrase,
389
+ armoredNodePassphraseSignature: link.Link.NodePassphraseSignature,
390
+ }
391
+
392
+ if (link.Link.Type === 1 && link.Folder) {
393
+ return {
394
+ ...baseNodeMetadata,
395
+ encryptedCrypto: {
396
+ ...baseCryptoNodeMetadata,
397
+ folder: {
398
+ armoredExtendedAttributes: link.Folder.XAttr || undefined,
399
+ armoredHashKey: link.Folder.NodeHashKey as string,
400
+ },
401
+ },
402
+ }
403
+ }
404
+
405
+ if (link.Link.Type === 2 && link.File && link.File.ActiveRevision) {
406
+ return {
407
+ ...baseNodeMetadata,
408
+ totalStorageSize: link.File.TotalEncryptedSize,
409
+ mediaType: link.File.MediaType || undefined,
410
+ encryptedCrypto: {
411
+ ...baseCryptoNodeMetadata,
412
+ file: {
413
+ base64ContentKeyPacket: link.File.ContentKeyPacket,
414
+ armoredContentKeyPacketSignature: link.File.ContentKeyPacketSignature || undefined,
415
+ },
416
+ activeRevision: {
417
+ uid: makeNodeRevisionUid(volumeId, link.Link.LinkID, link.File.ActiveRevision.RevisionID),
418
+ state: RevisionState.Active,
419
+ creationTime: new Date(link.File.ActiveRevision.CreateTime*1000),
420
+ storageSize: link.File.ActiveRevision.EncryptedSize,
421
+ signatureEmail: link.File.ActiveRevision.SignatureEmail || undefined,
422
+ armoredExtendedAttributes: link.File.ActiveRevision.XAttr || undefined,
423
+ thumbnails: link.File.ActiveRevision.Thumbnails?.map((thumbnail) => transformThumbnail(volumeId, link.Link.LinkID, thumbnail)) || [],
424
+ },
425
+ },
426
+ }
427
+ }
428
+
429
+ throw new Error(`Unknown node type: ${link.Link.Type}`);
430
+ }
431
+
432
+ function transformRevisionResponse(
433
+ volumeId: string,
434
+ nodeId: string,
435
+ revision: GetRevisionResponse['Revision'] | GetRevisionsResponse['Revisions'][0],
436
+ ): EncryptedRevision {
437
+ return {
438
+ uid: makeNodeRevisionUid(volumeId, nodeId, revision.ID),
439
+ state: revision.State === APIRevisionState.Active ? RevisionState.Active : RevisionState.Superseded,
440
+ creationTime: new Date(revision.CreateTime*1000),
441
+ storageSize: revision.Size,
442
+ signatureEmail: revision.SignatureEmail || undefined,
443
+ armoredExtendedAttributes: revision.XAttr || undefined,
444
+ thumbnails: revision.Thumbnails?.map((thumbnail) => transformThumbnail(volumeId, nodeId, thumbnail)) || [],
445
+ }
446
+ }
447
+
448
+ function transformThumbnail(volumeId: string, nodeId: string, thumbnail: { ThumbnailID: string | null, Type: 1 | 2 | 3}): Thumbnail {
449
+ return {
450
+ // TODO: Legacy thumbnails didn't have ID but we don't have them anymore. Remove typing once API doc is updated.
451
+ uid: makeNodeThumbnailUid(volumeId, nodeId, thumbnail.ThumbnailID as string),
452
+ // TODO: We don't support any other thumbnail type yet.
453
+ type: thumbnail.Type as 1 | 2,
454
+ }
455
+ }
@@ -0,0 +1,197 @@
1
+ import { MemoryCache } from "../../cache";
2
+ import { NodeType, MemberRole } from "../../interface";
3
+ import { getMockLogger } from "../../tests/logger";
4
+ import { CACHE_TAG_KEYS, NodesCache } from "./cache";
5
+ import { DecryptedNode } from "./interface";
6
+
7
+ function generateNode(uid: string, parentUid='root', params: Partial<DecryptedNode> & { volumeId?: string } = {}): DecryptedNode {
8
+ return {
9
+ uid: `${params.volumeId || "volumeId"}~:${uid}`,
10
+ parentUid: `${params.volumeId || "volumeId"}~:${parentUid}`,
11
+ directMemberRole: MemberRole.Admin,
12
+ type: NodeType.File,
13
+ mediaType: "text",
14
+ isShared: false,
15
+ creationTime: new Date(),
16
+ trashTime: undefined,
17
+ volumeId: "volumeId",
18
+ isStale: false,
19
+ ...params,
20
+ } as DecryptedNode;
21
+ }
22
+
23
+ async function generateTreeStructure(cache: NodesCache) {
24
+ for (const node of [
25
+ generateNode('node1', 'root'),
26
+ generateNode('node1a', 'node1'),
27
+ generateNode('node1b', 'node1', { trashTime: new Date() }),
28
+ generateNode('node1c', 'node1'),
29
+ generateNode('node1c-alpha', 'node1c'),
30
+ generateNode('node1c-beta', 'node1c', { trashTime: new Date() }),
31
+
32
+ generateNode('node2', 'root'),
33
+ generateNode('node2a', 'node2'),
34
+ generateNode('node2b', 'node2', { trashTime: new Date() }),
35
+
36
+ generateNode('node3', 'root'),
37
+
38
+ generateNode('root-otherVolume', '', { volumeId: 'volume2' }),
39
+ ]) {
40
+ await cache.setNode(node);
41
+ }
42
+ }
43
+
44
+ async function verifyNodesCache(cache: NodesCache, expectedNodes: string[], expectedMissingNodes: string[]) {
45
+ for (const nodeUid of expectedNodes) {
46
+ try {
47
+ await cache.getNode(`volumeId~:${nodeUid}`);
48
+ } catch (error) {
49
+ throw new Error(`${nodeUid} should be in the cache: ${error}`);
50
+ }
51
+ }
52
+
53
+ for (const nodeUid of expectedMissingNodes) {
54
+ try {
55
+ await cache.getNode(`volumeId~:${nodeUid}`);
56
+ throw new Error(`${nodeUid} should not be in the cache`);
57
+ } catch (error) {
58
+ expect(`${error}`).toBe('Error: Entity not found');
59
+ }
60
+ }
61
+ }
62
+
63
+ describe('nodesCache', () => {
64
+ let memoryCache: MemoryCache<string>;
65
+ let cache: NodesCache;
66
+
67
+ beforeEach(async () => {
68
+ memoryCache = new MemoryCache();
69
+ await memoryCache.setEntity('node-volumeId~:root', JSON.stringify(generateNode('root', '')));
70
+ await memoryCache.setEntity('node-badObject', 'aaa', [`${CACHE_TAG_KEYS.ParentUid}:root`]);
71
+
72
+ cache = new NodesCache(getMockLogger(), memoryCache);
73
+ });
74
+
75
+ it('should store and retrieve node', async () => {
76
+ const node = generateNode('node1', '');
77
+
78
+ await cache.setNode(node);
79
+ const result = await cache.getNode(node.uid);
80
+
81
+ expect(result).toStrictEqual(node);
82
+ });
83
+
84
+ it('should throw an error when retrieving a non-existing entity', async () => {
85
+ try {
86
+ await cache.getNode('nonExistingNodeUid');
87
+ fail('Should have thrown an error');
88
+ } catch (error) {
89
+ expect(`${error}`).toBe('Error: Entity not found');
90
+ }
91
+ });
92
+
93
+ it('should throw an error when retrieving a corrupted node and remove the node from the cache', async () => {
94
+ try {
95
+ await cache.getNode('badObject');
96
+ fail('Should have thrown an error');
97
+ } catch (error) {
98
+ expect(`${error}`).toBe('Error: Failed to deserialise node: Unexpected token \'a\', \"aaa\" is not valid JSON');
99
+ }
100
+
101
+ try {
102
+ await memoryCache.getEntity('nodes-badObject');
103
+ fail('Should have thrown an error');
104
+ } catch (error) {
105
+ expect(`${error}`).toBe('Error: Entity not found');
106
+ }
107
+ });
108
+
109
+ it('should remove node without children', async () => {
110
+ await generateTreeStructure(cache);
111
+ await cache.removeNodes(['volumeId~:node3']);
112
+ await verifyNodesCache(
113
+ cache,
114
+ ['node1', 'node1a', 'node1b', 'node1c', 'node1c-alpha', 'node1c-beta', 'node2', 'node2a', 'node2b'],
115
+ ['node3'],
116
+ )
117
+ });
118
+
119
+ it('should remove node and its children', async () => {
120
+ await generateTreeStructure(cache);
121
+ await cache.removeNodes(['volumeId~:node2']);
122
+ await verifyNodesCache(
123
+ cache,
124
+ ['node1', 'node1a', 'node1b', 'node1c', 'node1c-alpha', 'node1c-beta', 'node3'],
125
+ ['node2', 'node2a', 'node2b',],
126
+ )
127
+ });
128
+
129
+ it('should remove node and its children recursively', async () => {
130
+ await generateTreeStructure(cache);
131
+ await cache.removeNodes(['volumeId~:node1']);
132
+ await verifyNodesCache(
133
+ cache,
134
+ ['node2', 'node2a', 'node2b', 'node3'],
135
+ ['node1', 'node1a', 'node1b', 'node1c', 'node1c-alpha', 'node1c-beta'],
136
+ );
137
+ });
138
+
139
+ it('should iterate requested nodes', async () => {
140
+ await generateTreeStructure(cache);
141
+ const result = await Array.fromAsync(cache.iterateNodes(['volumeId~:node1', 'volumeId~:node2']));
142
+ const nodeUids = result.map(({ uid }) => uid);
143
+ expect(nodeUids).toStrictEqual(['volumeId~:node1', 'volumeId~:node2']);
144
+ });
145
+
146
+ it('should iterate children without trashed items', async () => {
147
+ await generateTreeStructure(cache);
148
+ const result = await Array.fromAsync(cache.iterateChildren('volumeId~:node1'));
149
+ const nodeUids = result.map(({ uid }) => uid);
150
+ expect(nodeUids).toStrictEqual(['volumeId~:node1a', 'volumeId~:node1c']);
151
+ });
152
+
153
+ it('should iterate children and silently remove a corrupted node', async () => {
154
+ await generateTreeStructure(cache);
155
+ // badObject has root as parent.
156
+ const result = await Array.fromAsync(cache.iterateChildren('volumeId~:root'));
157
+ const nodeUids = result.map(({ uid }) => uid);
158
+ expect(nodeUids).toStrictEqual(['volumeId~:node1', 'volumeId~:node2', 'volumeId~:node3']);
159
+ await verifyNodesCache(
160
+ cache,
161
+ ['root', 'node1', 'node1a', 'node1b', 'node1c', 'node1c-alpha', 'node1c-beta', 'node2', 'node2a', 'node2b', 'node3'],
162
+ ['badObject'],
163
+ )
164
+ });
165
+
166
+ it('should iterate trashed nodes', async () => {
167
+ await generateTreeStructure(cache);
168
+ const result = await Array.fromAsync(cache.iterateTrashedNodes());
169
+ const nodeUids = result.map(({ uid }) => uid);
170
+ expect(nodeUids).toStrictEqual(['volumeId~:node1b', 'volumeId~:node1c-beta', 'volumeId~:node2b']);
171
+ });
172
+
173
+ it('should set and unset children loaded state', async () => {
174
+ expect(await cache.isFolderChildrenLoaded('volumeId~:node1')).toBe(false);
175
+
176
+ await cache.setFolderChildrenLoaded('volumeId~:node1');
177
+ expect(await cache.isFolderChildrenLoaded('volumeId~:node1')).toBe(true);
178
+
179
+ await cache.resetFolderChildrenLoaded('volumeId~:node1');
180
+ expect(await cache.isFolderChildrenLoaded('volumeId~:node1')).toBe(false);
181
+ });
182
+
183
+ it('should set nodes from the volume as stale', async () => {
184
+ await generateTreeStructure(cache);
185
+ await cache.setNodesStaleFromVolume('volumeId');
186
+
187
+ const staleNodeUids = ['node1', 'node1a', 'node1b', 'node1c', 'node1c-alpha', 'node1c-beta', 'node2', 'node2a', 'node2b', 'node3']
188
+ .map((uid) => `volumeId~:${uid}`);
189
+ const result = await Array.fromAsync(cache.iterateNodes([...staleNodeUids, 'volume2~:root-otherVolume']));
190
+ const got = result.map((item) => ({ uid: item.uid, isStale: item.ok ? item.node.isStale : item.error }));
191
+ const expected = [
192
+ ...staleNodeUids.map((uid) => ({ uid, isStale: true })),
193
+ { uid: 'volume2~:root-otherVolume', isStale: false },
194
+ ];
195
+ expect(got).toEqual(expected);
196
+ });
197
+ });