@protontech/drive-sdk 0.9.9 → 0.11.0

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 (213) hide show
  1. package/dist/crypto/driveCrypto.d.ts +19 -16
  2. package/dist/crypto/driveCrypto.js +23 -1
  3. package/dist/crypto/driveCrypto.js.map +1 -1
  4. package/dist/crypto/driveCrypto.test.js +2 -1
  5. package/dist/crypto/driveCrypto.test.js.map +1 -1
  6. package/dist/crypto/hmac.d.ts +3 -3
  7. package/dist/crypto/hmac.js.map +1 -1
  8. package/dist/crypto/interface.d.ts +45 -25
  9. package/dist/crypto/interface.js.map +1 -1
  10. package/dist/crypto/openPGPCrypto.d.ts +37 -37
  11. package/dist/crypto/openPGPCrypto.js.map +1 -1
  12. package/dist/crypto/utils.d.ts +1 -1
  13. package/dist/diagnostic/telemetry.js +3 -0
  14. package/dist/diagnostic/telemetry.js.map +1 -1
  15. package/dist/interface/index.d.ts +4 -3
  16. package/dist/interface/index.js +3 -1
  17. package/dist/interface/index.js.map +1 -1
  18. package/dist/interface/nodes.d.ts +8 -0
  19. package/dist/interface/photos.d.ts +31 -2
  20. package/dist/interface/photos.js +14 -0
  21. package/dist/interface/photos.js.map +1 -1
  22. package/dist/interface/sharing.d.ts +2 -0
  23. package/dist/interface/telemetry.d.ts +13 -1
  24. package/dist/interface/telemetry.js.map +1 -1
  25. package/dist/interface/thumbnail.d.ts +2 -2
  26. package/dist/internal/apiService/apiService.d.ts +1 -1
  27. package/dist/internal/apiService/apiService.js +27 -14
  28. package/dist/internal/apiService/apiService.js.map +1 -1
  29. package/dist/internal/apiService/apiService.test.js +33 -5
  30. package/dist/internal/apiService/apiService.test.js.map +1 -1
  31. package/dist/internal/apiService/driveTypes.d.ts +2942 -3187
  32. package/dist/internal/apiService/errors.test.js +17 -7
  33. package/dist/internal/apiService/errors.test.js.map +1 -1
  34. package/dist/internal/devices/manager.d.ts +1 -0
  35. package/dist/internal/devices/manager.js +11 -0
  36. package/dist/internal/devices/manager.js.map +1 -1
  37. package/dist/internal/download/apiService.d.ts +1 -1
  38. package/dist/internal/download/cryptoService.d.ts +4 -4
  39. package/dist/internal/download/cryptoService.js.map +1 -1
  40. package/dist/internal/download/fileDownloader.js.map +1 -1
  41. package/dist/internal/download/fileDownloader.test.js.map +1 -1
  42. package/dist/internal/download/thumbnailDownloader.js.map +1 -1
  43. package/dist/internal/nodes/apiService.js.map +1 -1
  44. package/dist/internal/nodes/cryptoService.d.ts +4 -4
  45. package/dist/internal/nodes/cryptoService.js +5 -3
  46. package/dist/internal/nodes/cryptoService.js.map +1 -1
  47. package/dist/internal/nodes/cryptoService.test.js.map +1 -1
  48. package/dist/internal/nodes/interface.d.ts +1 -1
  49. package/dist/internal/nodes/nodesAccess.js +1 -1
  50. package/dist/internal/nodes/nodesAccess.js.map +1 -1
  51. package/dist/internal/nodes/nodesManagement.js +0 -1
  52. package/dist/internal/nodes/nodesManagement.js.map +1 -1
  53. package/dist/internal/photos/addToAlbum.d.ts +42 -0
  54. package/dist/internal/photos/addToAlbum.js +178 -0
  55. package/dist/internal/photos/addToAlbum.js.map +1 -0
  56. package/dist/internal/photos/addToAlbum.test.js +409 -0
  57. package/dist/internal/photos/addToAlbum.test.js.map +1 -0
  58. package/dist/internal/photos/albumsCrypto.d.ts +20 -3
  59. package/dist/internal/photos/albumsCrypto.js +27 -0
  60. package/dist/internal/photos/albumsCrypto.js.map +1 -1
  61. package/dist/internal/photos/{albums.d.ts → albumsManager.d.ts} +6 -4
  62. package/dist/internal/photos/{albums.js → albumsManager.js} +17 -5
  63. package/dist/internal/photos/albumsManager.js.map +1 -0
  64. package/dist/internal/photos/albumsManager.test.d.ts +1 -0
  65. package/dist/internal/photos/{albums.test.js → albumsManager.test.js} +4 -3
  66. package/dist/internal/photos/albumsManager.test.js.map +1 -0
  67. package/dist/internal/photos/apiService.d.ts +22 -2
  68. package/dist/internal/photos/apiService.js +136 -5
  69. package/dist/internal/photos/apiService.js.map +1 -1
  70. package/dist/internal/photos/apiService.test.d.ts +1 -0
  71. package/dist/internal/photos/apiService.test.js +199 -0
  72. package/dist/internal/photos/apiService.test.js.map +1 -0
  73. package/dist/internal/photos/errors.d.ts +4 -0
  74. package/dist/internal/photos/errors.js +17 -0
  75. package/dist/internal/photos/errors.js.map +1 -0
  76. package/dist/internal/photos/index.d.ts +5 -3
  77. package/dist/internal/photos/index.js +5 -2
  78. package/dist/internal/photos/index.js.map +1 -1
  79. package/dist/internal/photos/interface.d.ts +6 -15
  80. package/dist/internal/photos/interface.js +0 -14
  81. package/dist/internal/photos/interface.js.map +1 -1
  82. package/dist/internal/photos/nodes.js +33 -3
  83. package/dist/internal/photos/nodes.js.map +1 -1
  84. package/dist/internal/photos/nodes.test.js +25 -5
  85. package/dist/internal/photos/nodes.test.js.map +1 -1
  86. package/dist/internal/photos/photosManager.d.ts +22 -0
  87. package/dist/internal/photos/photosManager.js +101 -0
  88. package/dist/internal/photos/photosManager.js.map +1 -0
  89. package/dist/internal/photos/photosManager.test.d.ts +1 -0
  90. package/dist/internal/photos/photosManager.test.js +222 -0
  91. package/dist/internal/photos/photosManager.test.js.map +1 -0
  92. package/dist/internal/photos/photosTransferPayloadBuilder.d.ts +57 -0
  93. package/dist/internal/photos/photosTransferPayloadBuilder.js +113 -0
  94. package/dist/internal/photos/photosTransferPayloadBuilder.js.map +1 -0
  95. package/dist/internal/photos/photosTransferPayloadBuilder.test.d.ts +1 -0
  96. package/dist/internal/photos/photosTransferPayloadBuilder.test.js +289 -0
  97. package/dist/internal/photos/photosTransferPayloadBuilder.test.js.map +1 -0
  98. package/dist/internal/photos/upload.d.ts +2 -2
  99. package/dist/internal/photos/upload.js +1 -1
  100. package/dist/internal/photos/upload.js.map +1 -1
  101. package/dist/internal/shares/apiService.js +1 -0
  102. package/dist/internal/shares/apiService.js.map +1 -1
  103. package/dist/internal/shares/interface.d.ts +1 -0
  104. package/dist/internal/sharing/apiService.d.ts +8 -1
  105. package/dist/internal/sharing/apiService.js +23 -1
  106. package/dist/internal/sharing/apiService.js.map +1 -1
  107. package/dist/internal/sharing/cryptoService.js +8 -4
  108. package/dist/internal/sharing/cryptoService.js.map +1 -1
  109. package/dist/internal/sharing/sharingManagement.d.ts +1 -0
  110. package/dist/internal/sharing/sharingManagement.js +15 -2
  111. package/dist/internal/sharing/sharingManagement.js.map +1 -1
  112. package/dist/internal/sharing/sharingManagement.test.js +30 -5
  113. package/dist/internal/sharing/sharingManagement.test.js.map +1 -1
  114. package/dist/internal/sharingPublic/nodes.d.ts +2 -2
  115. package/dist/internal/sharingPublic/nodes.js.map +1 -1
  116. package/dist/internal/upload/apiService.d.ts +3 -7
  117. package/dist/internal/upload/apiService.js +0 -4
  118. package/dist/internal/upload/apiService.js.map +1 -1
  119. package/dist/internal/upload/blockVerifier.d.ts +2 -2
  120. package/dist/internal/upload/blockVerifier.js.map +1 -1
  121. package/dist/internal/upload/chunkStreamReader.d.ts +2 -2
  122. package/dist/internal/upload/chunkStreamReader.js.map +1 -1
  123. package/dist/internal/upload/chunkStreamReader.test.js.map +1 -1
  124. package/dist/internal/upload/cryptoService.d.ts +7 -7
  125. package/dist/internal/upload/cryptoService.js +4 -4
  126. package/dist/internal/upload/cryptoService.js.map +1 -1
  127. package/dist/internal/upload/interface.d.ts +6 -6
  128. package/dist/internal/upload/manager.d.ts +1 -1
  129. package/dist/internal/upload/manager.js.map +1 -1
  130. package/dist/internal/upload/streamUploader.d.ts +1 -1
  131. package/dist/internal/upload/streamUploader.js +12 -13
  132. package/dist/internal/upload/streamUploader.js.map +1 -1
  133. package/dist/internal/upload/streamUploader.test.js +28 -4
  134. package/dist/internal/upload/streamUploader.test.js.map +1 -1
  135. package/dist/internal/utils.d.ts +1 -1
  136. package/dist/protonDriveClient.d.ts +8 -0
  137. package/dist/protonDriveClient.js +12 -1
  138. package/dist/protonDriveClient.js.map +1 -1
  139. package/dist/protonDrivePhotosClient.d.ts +35 -3
  140. package/dist/protonDrivePhotosClient.js +42 -2
  141. package/dist/protonDrivePhotosClient.js.map +1 -1
  142. package/dist/protonDrivePublicLinkClient.js +1 -1
  143. package/dist/protonDrivePublicLinkClient.js.map +1 -1
  144. package/dist/transformers.js +2 -0
  145. package/dist/transformers.js.map +1 -1
  146. package/package.json +4 -4
  147. package/src/crypto/driveCrypto.test.ts +2 -1
  148. package/src/crypto/driveCrypto.ts +50 -16
  149. package/src/crypto/hmac.ts +4 -4
  150. package/src/crypto/interface.ts +58 -27
  151. package/src/crypto/openPGPCrypto.ts +26 -26
  152. package/src/diagnostic/telemetry.ts +3 -0
  153. package/src/interface/index.ts +11 -2
  154. package/src/interface/nodes.ts +1 -0
  155. package/src/interface/photos.ts +33 -2
  156. package/src/interface/sharing.ts +2 -0
  157. package/src/interface/telemetry.ts +15 -1
  158. package/src/interface/thumbnail.ts +2 -2
  159. package/src/internal/apiService/apiService.test.ts +38 -6
  160. package/src/internal/apiService/apiService.ts +39 -14
  161. package/src/internal/apiService/driveTypes.ts +2942 -3187
  162. package/src/internal/devices/manager.ts +14 -0
  163. package/src/internal/download/apiService.ts +1 -1
  164. package/src/internal/download/cryptoService.ts +4 -4
  165. package/src/internal/download/fileDownloader.test.ts +4 -4
  166. package/src/internal/download/fileDownloader.ts +6 -6
  167. package/src/internal/download/thumbnailDownloader.ts +4 -4
  168. package/src/internal/nodes/apiService.ts +2 -2
  169. package/src/internal/nodes/cryptoService.test.ts +2 -2
  170. package/src/internal/nodes/cryptoService.ts +11 -8
  171. package/src/internal/nodes/interface.ts +1 -1
  172. package/src/internal/nodes/nodesAccess.ts +1 -1
  173. package/src/internal/nodes/nodesManagement.ts +0 -1
  174. package/src/internal/photos/addToAlbum.test.ts +515 -0
  175. package/src/internal/photos/addToAlbum.ts +234 -0
  176. package/src/internal/photos/albumsCrypto.ts +54 -3
  177. package/src/internal/photos/{albums.test.ts → albumsManager.test.ts} +22 -25
  178. package/src/internal/photos/{albums.ts → albumsManager.ts} +32 -3
  179. package/src/internal/photos/apiService.test.ts +233 -0
  180. package/src/internal/photos/apiService.ts +228 -26
  181. package/src/internal/photos/errors.ts +11 -0
  182. package/src/internal/photos/index.ts +6 -3
  183. package/src/internal/photos/interface.ts +8 -18
  184. package/src/internal/photos/nodes.test.ts +27 -6
  185. package/src/internal/photos/nodes.ts +35 -3
  186. package/src/internal/photos/photosManager.test.ts +266 -0
  187. package/src/internal/photos/photosManager.ts +144 -0
  188. package/src/internal/photos/photosTransferPayloadBuilder.test.ts +380 -0
  189. package/src/internal/photos/photosTransferPayloadBuilder.ts +203 -0
  190. package/src/internal/photos/upload.ts +8 -3
  191. package/src/internal/shares/apiService.ts +1 -0
  192. package/src/internal/shares/interface.ts +1 -0
  193. package/src/internal/sharing/apiService.ts +49 -5
  194. package/src/internal/sharing/cryptoService.ts +10 -4
  195. package/src/internal/sharing/sharingManagement.test.ts +33 -5
  196. package/src/internal/sharing/sharingManagement.ts +28 -6
  197. package/src/internal/sharingPublic/nodes.ts +1 -1
  198. package/src/internal/upload/apiService.ts +10 -12
  199. package/src/internal/upload/blockVerifier.ts +3 -3
  200. package/src/internal/upload/chunkStreamReader.test.ts +7 -7
  201. package/src/internal/upload/chunkStreamReader.ts +3 -3
  202. package/src/internal/upload/cryptoService.ts +11 -12
  203. package/src/internal/upload/interface.ts +6 -6
  204. package/src/internal/upload/manager.ts +2 -2
  205. package/src/internal/upload/streamUploader.test.ts +33 -4
  206. package/src/internal/upload/streamUploader.ts +13 -13
  207. package/src/protonDriveClient.ts +16 -4
  208. package/src/protonDrivePhotosClient.ts +73 -17
  209. package/src/protonDrivePublicLinkClient.ts +1 -1
  210. package/src/transformers.ts +2 -0
  211. package/dist/internal/photos/albums.js.map +0 -1
  212. package/dist/internal/photos/albums.test.js.map +0 -1
  213. /package/dist/internal/photos/{albums.test.d.ts → addToAlbum.test.d.ts} +0 -0
@@ -27,7 +27,7 @@ async function mockEncryptBlock(
27
27
  verificationToken: 'verificationToken',
28
28
  originalSize: block.length,
29
29
  encryptedSize: block.length + BLOCK_ENCRYPTION_OVERHEAD,
30
- hash: 'blockHash',
30
+ hashPromise: Promise.resolve('blockHash'),
31
31
  };
32
32
  }
33
33
 
@@ -90,7 +90,7 @@ describe('StreamUploader', () => {
90
90
  encryptedData: thumbnail.thumbnail,
91
91
  originalSize: thumbnail.thumbnail.length,
92
92
  encryptedSize: thumbnail.thumbnail + 1000,
93
- hash: 'thumbnailHash',
93
+ hashPromise: Promise.resolve('thumbnailHash'),
94
94
  })),
95
95
  encryptBlock: jest.fn().mockImplementation(mockEncryptBlock),
96
96
  };
@@ -428,6 +428,37 @@ describe('StreamUploader', () => {
428
428
  expect((uploader as any).maxUploadingBlocks).toEqual(1);
429
429
  });
430
430
 
431
+ it('should not call onProgress after upload has failed', async () => {
432
+ let firstBlockPromise;
433
+
434
+ // Block 1 delays before reporting progress; block 2 fails immediately.
435
+ // This simulates block 1's progress callback firing after we've already
436
+ // entered the catch block.
437
+ apiService.uploadBlock = jest.fn().mockImplementation(async function (bareUrl, token, block, onProgress) {
438
+ if (token === 'token/block:1') {
439
+ firstBlockPromise = new Promise((resolve) => setTimeout(resolve, 100));
440
+ await firstBlockPromise;
441
+ return mockUploadBlock(bareUrl, token, block, onProgress);
442
+ }
443
+ if (token === 'token/block:2') {
444
+ throw new Error('Failed to upload block');
445
+ }
446
+ return mockUploadBlock(bareUrl, token, block, onProgress);
447
+ });
448
+
449
+ const startPromise = uploader.start(stream, thumbnails, onProgress);
450
+ await expect(startPromise).rejects.toThrow('Failed to upload block');
451
+
452
+ expect(firstBlockPromise).toBeDefined();
453
+ await firstBlockPromise!;
454
+
455
+ // Mocked file has 3 blocks - 2x 4 MB blocks and 1x 2 MB block
456
+ // First block is delayed - should not be reported.
457
+ // Second block is failed - should not be reported.
458
+ // Third block is successfull before second block is failed - should be reported.
459
+ await verifyOnProgress([thumbnailSize, 2 * 1024 * 1024]);
460
+ });
461
+
431
462
  it('limitUploadCapacity should wait for the previous blocks to finish', async () => {
432
463
  const error = new Error('TimeoutError');
433
464
  error.name = 'TimeoutError';
@@ -496,8 +527,6 @@ describe('StreamUploader', () => {
496
527
  contentBlocks: [
497
528
  {
498
529
  index: 2,
499
- encryptedSize: 4 * 1024 * 1024 + 10000,
500
- hash: 'blockHash',
501
530
  armoredSignature: 'signature',
502
531
  verificationToken: 'verificationToken',
503
532
  },
@@ -121,7 +121,9 @@ export class StreamUploader {
121
121
  this.logger.info(`Starting upload`);
122
122
  await this.encryptAndUploadBlocks(stream, thumbnails, (uploadedBytes) => {
123
123
  fileProgress += uploadedBytes;
124
- onProgress?.(fileProgress);
124
+ if (!failure) {
125
+ onProgress?.(fileProgress);
126
+ }
125
127
  });
126
128
 
127
129
  this.logger.debug(`All blocks uploaded, committing`);
@@ -230,7 +232,7 @@ export class StreamUploader {
230
232
  };
231
233
  await this.uploadManager.commitDraft(
232
234
  this.revisionDraft,
233
- this.manifest,
235
+ await this.getManifest(),
234
236
  extendedAttributes,
235
237
  this.metadata.additionalMetadata,
236
238
  );
@@ -328,8 +330,6 @@ export class StreamUploader {
328
330
  contentBlocks: Array.from(
329
331
  this.encryptedBlocks.values().map((block) => ({
330
332
  index: block.index,
331
- encryptedSize: block.encryptedSize,
332
- hash: block.hash,
333
333
  armoredSignature: block.armoredSignature,
334
334
  verificationToken: block.verificationToken,
335
335
  })),
@@ -337,8 +337,6 @@ export class StreamUploader {
337
337
  thumbnails: Array.from(
338
338
  this.encryptedThumbnails.values().map((block) => ({
339
339
  type: block.type,
340
- encryptedSize: block.encryptedSize,
341
- hash: block.hash,
342
340
  })),
343
341
  ),
344
342
  },
@@ -422,7 +420,7 @@ export class StreamUploader {
422
420
  );
423
421
  this.uploadedThumbnails.push({
424
422
  type: encryptedThumbnail.type,
425
- hash: encryptedThumbnail.hash,
423
+ hashPromise: encryptedThumbnail.hashPromise,
426
424
  encryptedSize: encryptedThumbnail.encryptedSize,
427
425
  originalSize: encryptedThumbnail.originalSize,
428
426
  });
@@ -474,6 +472,10 @@ export class StreamUploader {
474
472
  let attempt = 0;
475
473
 
476
474
  while (true) {
475
+ if (this.isUploadAborted) {
476
+ throw this.error || new AbortError();
477
+ }
478
+
477
479
  attempt++;
478
480
  try {
479
481
  logger.debug(`Uploading`);
@@ -489,7 +491,7 @@ export class StreamUploader {
489
491
  );
490
492
  this.uploadedBlocks.push({
491
493
  index: encryptedBlock.index,
492
- hash: encryptedBlock.hash,
494
+ hashPromise: encryptedBlock.hashPromise,
493
495
  encryptedSize: encryptedBlock.encryptedSize,
494
496
  originalSize: encryptedBlock.originalSize,
495
497
  });
@@ -524,8 +526,6 @@ export class StreamUploader {
524
526
  contentBlocks: [
525
527
  {
526
528
  index: encryptedBlock.index,
527
- encryptedSize: encryptedBlock.encryptedSize,
528
- hash: encryptedBlock.hash,
529
529
  armoredSignature: encryptedBlock.armoredSignature,
530
530
  verificationToken: encryptedBlock.verificationToken,
531
531
  },
@@ -655,12 +655,12 @@ export class StreamUploader {
655
655
  return uploadedBlocks.map((block) => block.originalSize);
656
656
  }
657
657
 
658
- protected get manifest(): Uint8Array {
658
+ protected async getManifest(): Promise<Uint8Array<ArrayBuffer>> {
659
659
  this.uploadedThumbnails.sort((a, b) => a.type - b.type);
660
660
  this.uploadedBlocks.sort((a, b) => a.index - b.index);
661
661
  const hashes = [
662
- ...this.uploadedThumbnails.map(({ hash }) => hash),
663
- ...this.uploadedBlocks.map(({ hash }) => hash),
662
+ ...(await Promise.all(this.uploadedThumbnails.map(({ hashPromise }) => hashPromise))),
663
+ ...(await Promise.all(this.uploadedBlocks.map(({ hashPromise }) => hashPromise))),
664
664
  ];
665
665
  return mergeUint8Arrays(hashes);
666
666
  }
@@ -135,7 +135,7 @@ export class ProtonDriveClient {
135
135
 
136
136
  const fullConfig = getConfig(config);
137
137
  this.sdkEvents = new SDKEvents(telemetry);
138
- const cryptoModule = new DriveCrypto(openPGPCryptoModule, srpModule);
138
+ const cryptoModule = new DriveCrypto(telemetry, openPGPCryptoModule, srpModule);
139
139
  const apiService = new DriveAPIService(
140
140
  telemetry,
141
141
  this.sdkEvents,
@@ -223,12 +223,12 @@ export class ProtonDriveClient {
223
223
  return keys.contentKeyPacketSessionKey;
224
224
  },
225
225
  getPublicLinkInfo: async (url: string) => {
226
- const { token } = getTokenAndPasswordFromUrl(url)
226
+ const { token } = getTokenAndPasswordFromUrl(url);
227
227
  this.logger.info(`Getting info for public link token ${token}`);
228
228
  return this.publicSessionManager.getInfo(token);
229
229
  },
230
230
  authPublicLink: async (url: string, customPassword?: string, isAnonymousContext: boolean = false) => {
231
- const { token, password: urlPassword } = getTokenAndPasswordFromUrl(url)
231
+ const { token, password: urlPassword } = getTokenAndPasswordFromUrl(url);
232
232
  this.logger.info(`Authenticating public link token ${token}`);
233
233
 
234
234
  const { httpClient, shareKey, rootUid, publicRole } = await this.publicSessionManager.auth(
@@ -681,7 +681,7 @@ export class ProtonDriveClient {
681
681
  * @param customPassword - The optional custom password.
682
682
  */
683
683
  async createBookmark(url: string, customPassword?: string): Promise<void> {
684
- const { token, password: urlPassword } = getTokenAndPasswordFromUrl(url)
684
+ const { token, password: urlPassword } = getTokenAndPasswordFromUrl(url);
685
685
  this.logger.info(`Creating bookmark for token ${token}`);
686
686
  await this.sharing.access.createBookmark(token, urlPassword, customPassword);
687
687
  }
@@ -912,6 +912,18 @@ export class ProtonDriveClient {
912
912
  yield* this.devices.iterateDevices(signal);
913
913
  }
914
914
 
915
+ /**
916
+ * Get the device entity by its UID.
917
+ *
918
+ * @param deviceOrUid - Device entity or its UID string.
919
+ * @returns The device entity.
920
+ * @throws {@link ValidationError} If the device is not found.
921
+ */
922
+ async getDevice(deviceOrUid: DeviceOrUid): Promise<Device> {
923
+ this.logger.info(`Getting device ${getUid(deviceOrUid)}`);
924
+ return this.devices.getDevice(getUid(deviceOrUid));
925
+ }
926
+
915
927
  /**
916
928
  * Creates a new device.
917
929
  *
@@ -17,6 +17,8 @@ import {
17
17
  NonProtonInvitationOrUid,
18
18
  ProtonInvitationWithNode,
19
19
  NodeResult,
20
+ NodeResultWithError,
21
+ PhotoTag,
20
22
  } from './interface';
21
23
  import { getConfig } from './config';
22
24
  import { DriveCrypto } from './crypto';
@@ -40,7 +42,6 @@ import {
40
42
  initPhotosNodesModule,
41
43
  AlbumItem,
42
44
  TimelineItem,
43
- PhotoTag,
44
45
  } from './internal/photos';
45
46
  import { SDKEvents } from './internal/sdkEvents';
46
47
  import { initSharesModule } from './internal/shares';
@@ -92,7 +93,7 @@ export class ProtonDrivePhotosClient {
92
93
 
93
94
  const fullConfig = getConfig(config);
94
95
  this.sdkEvents = new SDKEvents(telemetry);
95
- const cryptoModule = new DriveCrypto(openPGPCryptoModule, srpModule);
96
+ const cryptoModule = new DriveCrypto(telemetry, openPGPCryptoModule, srpModule);
96
97
  const apiService = new DriveAPIService(
97
98
  telemetry,
98
99
  this.sdkEvents,
@@ -120,13 +121,7 @@ export class ProtonDrivePhotosClient {
120
121
  this.photoShares,
121
122
  fullConfig.clientUid,
122
123
  );
123
- this.photos = initPhotosModule(
124
- telemetry,
125
- apiService,
126
- cryptoModule,
127
- this.photoShares,
128
- this.nodes.access,
129
- );
124
+ this.photos = initPhotosModule(telemetry, apiService, cryptoModule, this.photoShares, this.nodes.access);
130
125
  this.sharing = initSharingModule(
131
126
  telemetry,
132
127
  apiService,
@@ -238,7 +233,7 @@ export class ProtonDrivePhotosClient {
238
233
  */
239
234
  async *iterateTrashedNodes(signal?: AbortSignal): AsyncGenerator<MaybePhotoNode> {
240
235
  this.logger.info('Iterating trashed nodes');
241
- yield * convertInternalPhotoNodeIterator(this.nodes.access.iterateTrashedNodes(signal));
236
+ yield* convertInternalPhotoNodeIterator(this.nodes.access.iterateTrashedNodes(signal));
242
237
  }
243
238
 
244
239
  /**
@@ -249,7 +244,7 @@ export class ProtonDrivePhotosClient {
249
244
  async *iterateNodes(nodeUids: NodeOrUid[], signal?: AbortSignal): AsyncGenerator<MaybeMissingPhotoNode> {
250
245
  this.logger.info(`Iterating ${nodeUids.length} nodes`);
251
246
  // TODO: expose photo type
252
- yield * convertInternalMissingPhotoNodeIterator(this.nodes.access.iterateNodes(getUids(nodeUids), signal));
247
+ yield* convertInternalMissingPhotoNodeIterator(this.nodes.access.iterateNodes(getUids(nodeUids), signal));
253
248
  }
254
249
 
255
250
  /**
@@ -299,7 +294,7 @@ export class ProtonDrivePhotosClient {
299
294
  */
300
295
  async *deleteNodes(nodeUids: NodeOrUid[], signal?: AbortSignal): AsyncGenerator<NodeResult> {
301
296
  this.logger.info(`Deleting ${nodeUids.length} nodes`);
302
- yield * this.nodes.management.deleteTrashedNodes(getUids(nodeUids), signal);
297
+ yield* this.nodes.management.deleteTrashedNodes(getUids(nodeUids), signal);
303
298
  }
304
299
 
305
300
  /**
@@ -317,7 +312,7 @@ export class ProtonDrivePhotosClient {
317
312
  */
318
313
  async *iterateSharedNodes(signal?: AbortSignal): AsyncGenerator<MaybePhotoNode> {
319
314
  this.logger.info('Iterating shared nodes by me');
320
- yield * convertInternalPhotoNodeIterator(this.sharing.access.iterateSharedNodes(signal));
315
+ yield* convertInternalPhotoNodeIterator(this.sharing.access.iterateSharedNodes(signal));
321
316
  }
322
317
 
323
318
  /**
@@ -484,7 +479,9 @@ export class ProtonDrivePhotosClient {
484
479
  */
485
480
  async isDuplicatePhoto(name: string, generateSha1: () => Promise<string>, signal?: AbortSignal): Promise<boolean> {
486
481
  this.logger.info(`Checking if photo is a duplicate`);
487
- return this.photos.timeline.findPhotoDuplicates(name, generateSha1, signal).then(nodeUids => nodeUids.length !== 0);
482
+ return this.photos.timeline
483
+ .findPhotoDuplicates(name, generateSha1, signal)
484
+ .then((nodeUids) => nodeUids.length !== 0);
488
485
  }
489
486
 
490
487
  /**
@@ -505,7 +502,11 @@ export class ProtonDrivePhotosClient {
505
502
  * @param signal - An optional abort signal to cancel the operation.
506
503
  * @returns An array of node UIDs of duplicate photos. Empty array if no duplicates found.
507
504
  */
508
- async findPhotoDuplicates(name: string, generateSha1: () => Promise<string>, signal?: AbortSignal): Promise<string[]> {
505
+ async findPhotoDuplicates(
506
+ name: string,
507
+ generateSha1: () => Promise<string>,
508
+ signal?: AbortSignal,
509
+ ): Promise<string[]> {
509
510
  this.logger.info(`Checking if photo have duplicates`);
510
511
  return this.photos.timeline.findPhotoDuplicates(name, generateSha1, signal);
511
512
  }
@@ -575,7 +576,7 @@ export class ProtonDrivePhotosClient {
575
576
  async *iterateAlbums(signal?: AbortSignal): AsyncGenerator<MaybePhotoNode> {
576
577
  this.logger.info('Iterating albums');
577
578
  // TODO: expose album type
578
- yield * convertInternalPhotoNodeIterator(this.photos.albums.iterateAlbums(signal));
579
+ yield* convertInternalPhotoNodeIterator(this.photos.albums.iterateAlbums(signal));
579
580
  }
580
581
 
581
582
  /**
@@ -592,6 +593,29 @@ export class ProtonDrivePhotosClient {
592
593
  yield* this.photos.albums.iterateAlbum(getUid(albumNodeUid), signal);
593
594
  }
594
595
 
596
+ /**
597
+ * Adds photos to an album.
598
+ *
599
+ * Photos are added in batches. Each photo's related photos (e.g., live
600
+ * photo components) are always included with the main photo.
601
+ *
602
+ * The album has a limit of 10,000 photos. If the limit is reached,
603
+ * a `ValidationError` is thrown.
604
+ *
605
+ * @param albumNodeUid - The UID of the album to add photos to.
606
+ * @param photoNodeUids - The UIDs of the photos to add to the album.
607
+ * @param signal - An optional abort signal to cancel the operation.
608
+ * @returns An async generator of the added photo results.
609
+ */
610
+ async *addPhotosToAlbum(
611
+ albumNodeUid: NodeOrUid,
612
+ photoNodeUids: NodeOrUid[],
613
+ signal?: AbortSignal,
614
+ ): AsyncGenerator<NodeResultWithError> {
615
+ this.logger.info(`Adding ${photoNodeUids.length} photos to album ${getUid(albumNodeUid)}`);
616
+ yield* this.photos.albums.addPhotos(getUid(albumNodeUid), getUids(photoNodeUids), signal);
617
+ }
618
+
595
619
  /**
596
620
  * Removes photos from an album.
597
621
  *
@@ -608,8 +632,40 @@ export class ProtonDrivePhotosClient {
608
632
  albumNodeUid: NodeOrUid,
609
633
  photoNodeUids: NodeOrUid[],
610
634
  signal?: AbortSignal,
611
- ): AsyncGenerator<NodeResult> {
635
+ ): AsyncGenerator<NodeResultWithError> {
612
636
  this.logger.info(`Removing ${photoNodeUids.length} photos from album ${getUid(albumNodeUid)}`);
613
637
  yield* this.photos.albums.removePhotos(getUid(albumNodeUid), getUids(photoNodeUids), signal);
614
638
  }
639
+
640
+ /**
641
+ * Updates photos with the given settings: add or remove tags.
642
+ *
643
+ * Assigning a favorite tag to a photo that is not in the timeline will
644
+ * result in a move operation to the timeline. The photo will stay in
645
+ * the album.
646
+ *
647
+ * @param nodeUids - The UIDs of the photos to update.
648
+ * @param settings - addTags: tags to add, removeTags: tags to remove.
649
+ * @param signal - An optional abort signal to cancel the operation.
650
+ * @returns An async generator of per-photo results.
651
+ */
652
+ async *updatePhotos(
653
+ photos: {
654
+ nodeUid: NodeOrUid;
655
+ tagsToAdd?: PhotoTag[];
656
+ tagsToRemove?: PhotoTag[];
657
+ }[],
658
+ signal?: AbortSignal,
659
+ ): AsyncGenerator<NodeResultWithError> {
660
+ this.logger.info(`Updating ${photos.length} photos`);
661
+ yield *
662
+ this.photos.photos.updatePhotos(
663
+ photos.map((p) => ({
664
+ nodeUid: getUid(p.nodeUid),
665
+ tagsToAdd: p.tagsToAdd || [],
666
+ tagsToRemove: p.tagsToRemove || [],
667
+ })),
668
+ signal,
669
+ );
670
+ }
615
671
  }
@@ -132,7 +132,7 @@ export class ProtonDrivePublicLinkClient {
132
132
  fullConfig.baseUrl,
133
133
  fullConfig.language,
134
134
  );
135
- const cryptoModule = new DriveCrypto(openPGPCryptoModule, srpModule);
135
+ const cryptoModule = new DriveCrypto(telemetry, openPGPCryptoModule, srpModule);
136
136
  this.sharingPublic = initSharingPublicModule(
137
137
  telemetry,
138
138
  apiService,
@@ -160,11 +160,13 @@ export function convertInternalPhotoNode(photoNode: InternalPartialPhotoNode): P
160
160
  return resultOk({
161
161
  ...node.value,
162
162
  photo: photoNode.photo,
163
+ album: photoNode.album,
163
164
  } as PublicPhotoNode);
164
165
  }
165
166
  return resultError({
166
167
  ...node.error,
167
168
  photo: photoNode.photo,
169
+ album: photoNode.album,
168
170
  } as PublicDegradedPhotoNode);
169
171
  }
170
172
 
@@ -1 +0,0 @@
1
- {"version":3,"file":"albums.js","sourceRoot":"","sources":["../../../src/internal/photos/albums.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"albums.test.js","sourceRoot":"","sources":["../../../src/internal/photos/albums.test.ts"],"names":[],"mappings":"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"}