@protontech/drive-sdk 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cache/memoryCache.js +0 -1
- package/dist/cache/memoryCache.js.map +1 -1
- package/dist/cache/memoryCache.test.js +2 -4
- package/dist/cache/memoryCache.test.js.map +1 -1
- package/dist/cache/nullCache.js +0 -1
- package/dist/cache/nullCache.js.map +1 -1
- package/dist/crypto/driveCrypto.d.ts +2 -5
- package/dist/crypto/driveCrypto.js +7 -12
- package/dist/crypto/driveCrypto.js.map +1 -1
- package/dist/crypto/driveCrypto.test.js +14 -14
- package/dist/crypto/openPGPCrypto.js +3 -3
- package/dist/crypto/openPGPCrypto.js.map +1 -1
- package/dist/diagnostic/eventsGenerator.js +1 -1
- package/dist/diagnostic/eventsGenerator.js.map +1 -1
- package/dist/diagnostic/httpClient.d.ts +1 -1
- package/dist/diagnostic/httpClient.js.map +1 -1
- package/dist/diagnostic/index.d.ts +3 -3
- package/dist/diagnostic/index.js.map +1 -1
- package/dist/diagnostic/integrityVerificationStream.js +1 -1
- package/dist/diagnostic/integrityVerificationStream.js.map +1 -1
- package/dist/diagnostic/interface.d.ts +2 -2
- package/dist/diagnostic/sdkDiagnostic.d.ts +3 -3
- package/dist/diagnostic/sdkDiagnostic.js +8 -2
- package/dist/diagnostic/sdkDiagnostic.js.map +1 -1
- package/dist/diagnostic/sdkDiagnosticFull.d.ts +4 -4
- package/dist/diagnostic/sdkDiagnosticFull.js.map +1 -1
- package/dist/diagnostic/telemetry.js.map +1 -1
- package/dist/diagnostic/zipGenerators.js +2 -2
- package/dist/diagnostic/zipGenerators.js.map +1 -1
- package/dist/diagnostic/zipGenerators.test.js +1 -1
- package/dist/diagnostic/zipGenerators.test.js.map +1 -1
- package/dist/interface/events.d.ts +2 -4
- package/dist/interface/events.js.map +1 -1
- package/dist/interface/index.d.ts +5 -5
- package/dist/interface/index.js +0 -1
- package/dist/interface/index.js.map +1 -1
- package/dist/interface/result.js.map +1 -1
- package/dist/interface/sharing.d.ts +1 -0
- package/dist/interface/sharing.js.map +1 -1
- package/dist/interface/telemetry.js +0 -8
- package/dist/interface/telemetry.js.map +1 -1
- package/dist/interface/thumbnail.js.map +1 -1
- package/dist/interface/upload.d.ts +1 -1
- package/dist/internal/apiService/apiService.d.ts +1 -1
- package/dist/internal/apiService/apiService.js +7 -11
- package/dist/internal/apiService/apiService.js.map +1 -1
- package/dist/internal/apiService/apiService.test.js +55 -48
- package/dist/internal/apiService/apiService.test.js.map +1 -1
- package/dist/internal/apiService/coreTypes.d.ts +2356 -2356
- package/dist/internal/apiService/driveTypes.d.ts +1680 -1680
- package/dist/internal/apiService/errors.js +14 -8
- package/dist/internal/apiService/errors.js.map +1 -1
- package/dist/internal/apiService/errors.test.js +17 -12
- package/dist/internal/apiService/errors.test.js.map +1 -1
- package/dist/internal/apiService/transformers.d.ts +1 -1
- package/dist/internal/apiService/transformers.js +1 -1
- package/dist/internal/asyncIteratorMap.test.js +2 -2
- package/dist/internal/asyncIteratorMap.test.js.map +1 -1
- package/dist/internal/asyncIteratorRace.d.ts +13 -0
- package/dist/internal/asyncIteratorRace.js +59 -0
- package/dist/internal/asyncIteratorRace.js.map +1 -0
- package/dist/internal/asyncIteratorRace.test.d.ts +1 -0
- package/dist/internal/asyncIteratorRace.test.js +119 -0
- package/dist/internal/asyncIteratorRace.test.js.map +1 -0
- package/dist/internal/batch.d.ts +1 -0
- package/dist/internal/batch.js +12 -0
- package/dist/internal/batch.js.map +1 -0
- package/dist/internal/batch.test.d.ts +1 -0
- package/dist/internal/batch.test.js +41 -0
- package/dist/internal/batch.test.js.map +1 -0
- package/dist/internal/batchLoading.js.map +1 -1
- package/dist/internal/batchLoading.test.js +13 -13
- package/dist/internal/batchLoading.test.js.map +1 -1
- package/dist/internal/devices/apiService.d.ts +3 -3
- package/dist/internal/devices/apiService.js +2 -2
- package/dist/internal/devices/apiService.js.map +1 -1
- package/dist/internal/devices/cryptoService.js +1 -2
- package/dist/internal/devices/cryptoService.js.map +1 -1
- package/dist/internal/devices/index.d.ts +5 -5
- package/dist/internal/devices/index.js.map +1 -1
- package/dist/internal/devices/interface.d.ts +3 -3
- package/dist/internal/devices/manager.js +2 -2
- package/dist/internal/devices/manager.js.map +1 -1
- package/dist/internal/devices/manager.test.js +38 -7
- package/dist/internal/devices/manager.test.js.map +1 -1
- package/dist/internal/download/apiService.d.ts +4 -4
- package/dist/internal/download/apiService.js +0 -1
- package/dist/internal/download/apiService.js.map +1 -1
- package/dist/internal/download/cryptoService.d.ts +4 -4
- package/dist/internal/download/cryptoService.js +6 -5
- package/dist/internal/download/cryptoService.js.map +1 -1
- package/dist/internal/download/fileDownloader.d.ts +4 -4
- package/dist/internal/download/fileDownloader.js +3 -2
- package/dist/internal/download/fileDownloader.js.map +1 -1
- package/dist/internal/download/fileDownloader.test.js +1 -1
- package/dist/internal/download/fileDownloader.test.js.map +1 -1
- package/dist/internal/download/index.d.ts +5 -5
- package/dist/internal/download/index.js +5 -5
- package/dist/internal/download/index.js.map +1 -1
- package/dist/internal/download/interface.d.ts +3 -4
- package/dist/internal/download/telemetry.d.ts +3 -3
- package/dist/internal/download/telemetry.js +4 -2
- package/dist/internal/download/telemetry.js.map +1 -1
- package/dist/internal/download/telemetry.test.js +8 -8
- package/dist/internal/download/telemetry.test.js.map +1 -1
- package/dist/internal/download/thumbnailDownloader.d.ts +4 -4
- package/dist/internal/download/thumbnailDownloader.js +6 -6
- package/dist/internal/download/thumbnailDownloader.js.map +1 -1
- package/dist/internal/download/thumbnailDownloader.test.js.map +1 -1
- package/dist/internal/errors.d.ts +1 -1
- package/dist/internal/errors.js +1 -3
- package/dist/internal/errors.js.map +1 -1
- package/dist/internal/events/apiService.d.ts +2 -2
- package/dist/internal/events/apiService.js +9 -5
- package/dist/internal/events/apiService.js.map +1 -1
- package/dist/internal/events/coreEventManager.d.ts +3 -3
- package/dist/internal/events/coreEventManager.js.map +1 -1
- package/dist/internal/events/coreEventManager.test.js +14 -14
- package/dist/internal/events/eventManager.d.ts +1 -1
- package/dist/internal/events/eventManager.js +0 -1
- package/dist/internal/events/eventManager.js.map +1 -1
- package/dist/internal/events/eventManager.test.js +34 -25
- package/dist/internal/events/eventManager.test.js.map +1 -1
- package/dist/internal/events/index.d.ts +6 -6
- package/dist/internal/events/index.js.map +1 -1
- package/dist/internal/events/interface.d.ts +1 -1
- package/dist/internal/events/interface.js +0 -1
- package/dist/internal/events/interface.js.map +1 -1
- package/dist/internal/events/volumeEventManager.d.ts +3 -3
- package/dist/internal/events/volumeEventManager.js.map +1 -1
- package/dist/internal/events/volumeEventManager.test.js +55 -55
- package/dist/internal/events/volumeEventManager.test.js.map +1 -1
- package/dist/internal/nodes/apiService.d.ts +4 -3
- package/dist/internal/nodes/apiService.js +36 -15
- package/dist/internal/nodes/apiService.js.map +1 -1
- package/dist/internal/nodes/apiService.test.js +60 -41
- package/dist/internal/nodes/apiService.test.js.map +1 -1
- package/dist/internal/nodes/cache.d.ts +5 -5
- package/dist/internal/nodes/cache.js +14 -7
- package/dist/internal/nodes/cache.js.map +1 -1
- package/dist/internal/nodes/cache.test.js +31 -9
- package/dist/internal/nodes/cache.test.js.map +1 -1
- package/dist/internal/nodes/cryptoCache.d.ts +2 -2
- package/dist/internal/nodes/cryptoCache.js.map +1 -1
- package/dist/internal/nodes/cryptoCache.test.js +24 -4
- package/dist/internal/nodes/cryptoCache.test.js.map +1 -1
- package/dist/internal/nodes/cryptoService.d.ts +3 -3
- package/dist/internal/nodes/cryptoService.js +11 -17
- package/dist/internal/nodes/cryptoService.js.map +1 -1
- package/dist/internal/nodes/cryptoService.test.js +320 -241
- package/dist/internal/nodes/cryptoService.test.js.map +1 -1
- package/dist/internal/nodes/events.d.ts +3 -3
- package/dist/internal/nodes/events.js.map +1 -1
- package/dist/internal/nodes/events.test.js +27 -21
- package/dist/internal/nodes/events.test.js.map +1 -1
- package/dist/internal/nodes/extendedAttributes.d.ts +1 -1
- package/dist/internal/nodes/extendedAttributes.js +3 -1
- package/dist/internal/nodes/extendedAttributes.js.map +1 -1
- package/dist/internal/nodes/extendedAttributes.test.js +7 -10
- package/dist/internal/nodes/extendedAttributes.test.js.map +1 -1
- package/dist/internal/nodes/index.d.ts +10 -10
- package/dist/internal/nodes/index.js.map +1 -1
- package/dist/internal/nodes/index.test.d.ts +1 -0
- package/dist/internal/nodes/index.test.js +106 -0
- package/dist/internal/nodes/index.test.js.map +1 -0
- package/dist/internal/nodes/interface.d.ts +2 -2
- package/dist/internal/nodes/nodesAccess.d.ts +7 -7
- package/dist/internal/nodes/nodesAccess.js +28 -16
- package/dist/internal/nodes/nodesAccess.js.map +1 -1
- package/dist/internal/nodes/nodesAccess.test.js +39 -13
- package/dist/internal/nodes/nodesAccess.test.js.map +1 -1
- package/dist/internal/nodes/nodesManagement.d.ts +6 -6
- package/dist/internal/nodes/nodesManagement.js +9 -7
- package/dist/internal/nodes/nodesManagement.js.map +1 -1
- package/dist/internal/nodes/nodesManagement.test.js +9 -9
- package/dist/internal/nodes/nodesManagement.test.js.map +1 -1
- package/dist/internal/nodes/nodesRevisions.d.ts +4 -4
- package/dist/internal/nodes/nodesRevisions.js.map +1 -1
- package/dist/internal/photos/albums.d.ts +3 -3
- package/dist/internal/photos/albums.js.map +1 -1
- package/dist/internal/photos/apiService.d.ts +1 -1
- package/dist/internal/photos/apiService.js +3 -6
- package/dist/internal/photos/apiService.js.map +1 -1
- package/dist/internal/photos/cache.d.ts +1 -1
- package/dist/internal/photos/index.d.ts +5 -5
- package/dist/internal/photos/index.js.map +1 -1
- package/dist/internal/photos/interface.d.ts +2 -2
- package/dist/internal/photos/photosTimeline.d.ts +3 -3
- package/dist/internal/photos/photosTimeline.js +1 -2
- package/dist/internal/photos/photosTimeline.js.map +1 -1
- package/dist/internal/sdkEvents.d.ts +1 -1
- package/dist/internal/sdkEvents.js +2 -7
- package/dist/internal/sdkEvents.js.map +1 -1
- package/dist/internal/sdkEvents.test.js +8 -8
- package/dist/internal/shares/apiService.d.ts +2 -2
- package/dist/internal/shares/apiService.js +5 -3
- package/dist/internal/shares/apiService.js.map +1 -1
- package/dist/internal/shares/cache.d.ts +2 -2
- package/dist/internal/shares/cache.js +12 -6
- package/dist/internal/shares/cache.js.map +1 -1
- package/dist/internal/shares/cache.test.js.map +1 -1
- package/dist/internal/shares/cryptoCache.d.ts +2 -2
- package/dist/internal/shares/cryptoCache.test.js +8 -2
- package/dist/internal/shares/cryptoCache.test.js.map +1 -1
- package/dist/internal/shares/cryptoService.d.ts +3 -3
- package/dist/internal/shares/cryptoService.js.map +1 -1
- package/dist/internal/shares/cryptoService.test.js +42 -42
- package/dist/internal/shares/cryptoService.test.js.map +1 -1
- package/dist/internal/shares/index.d.ts +4 -4
- package/dist/internal/shares/index.js.map +1 -1
- package/dist/internal/shares/interface.d.ts +2 -2
- package/dist/internal/shares/manager.d.ts +7 -7
- package/dist/internal/shares/manager.js.map +1 -1
- package/dist/internal/shares/manager.test.js +71 -63
- package/dist/internal/shares/manager.test.js.map +1 -1
- package/dist/internal/sharing/apiService.d.ts +4 -4
- package/dist/internal/sharing/apiService.js +4 -3
- package/dist/internal/sharing/apiService.js.map +1 -1
- package/dist/internal/sharing/cache.d.ts +1 -1
- package/dist/internal/sharing/cache.test.js +33 -33
- package/dist/internal/sharing/cryptoService.d.ts +3 -3
- package/dist/internal/sharing/cryptoService.js +3 -5
- package/dist/internal/sharing/cryptoService.js.map +1 -1
- package/dist/internal/sharing/cryptoService.test.js +39 -39
- package/dist/internal/sharing/cryptoService.test.js.map +1 -1
- package/dist/internal/sharing/events.d.ts +4 -4
- package/dist/internal/sharing/events.js +0 -1
- package/dist/internal/sharing/events.js.map +1 -1
- package/dist/internal/sharing/events.test.js +39 -40
- package/dist/internal/sharing/events.test.js.map +1 -1
- package/dist/internal/sharing/index.d.ts +6 -6
- package/dist/internal/sharing/index.js.map +1 -1
- package/dist/internal/sharing/interface.d.ts +5 -4
- package/dist/internal/sharing/sharingAccess.d.ts +6 -6
- package/dist/internal/sharing/sharingAccess.js +8 -4
- package/dist/internal/sharing/sharingAccess.js.map +1 -1
- package/dist/internal/sharing/sharingAccess.test.js +45 -39
- package/dist/internal/sharing/sharingAccess.test.js.map +1 -1
- package/dist/internal/sharing/sharingManagement.d.ts +4 -4
- package/dist/internal/sharing/sharingManagement.js +5 -7
- package/dist/internal/sharing/sharingManagement.js.map +1 -1
- package/dist/internal/sharing/sharingManagement.test.js +297 -248
- package/dist/internal/sharing/sharingManagement.test.js.map +1 -1
- package/dist/internal/uids.js.map +1 -1
- package/dist/internal/upload/apiService.d.ts +3 -3
- package/dist/internal/upload/apiService.js +1 -1
- package/dist/internal/upload/apiService.js.map +1 -1
- package/dist/internal/upload/blockVerifier.d.ts +3 -3
- package/dist/internal/upload/blockVerifier.js +1 -1
- package/dist/internal/upload/blockVerifier.js.map +1 -1
- package/dist/internal/upload/chunkStreamReader.test.js +6 -6
- package/dist/internal/upload/cryptoService.d.ts +4 -4
- package/dist/internal/upload/cryptoService.js +4 -4
- package/dist/internal/upload/cryptoService.js.map +1 -1
- package/dist/internal/upload/digests.js.map +1 -1
- package/dist/internal/upload/fileUploader.d.ts +6 -6
- package/dist/internal/upload/fileUploader.js.map +1 -1
- package/dist/internal/upload/fileUploader.test.js.map +1 -1
- package/dist/internal/upload/index.d.ts +5 -5
- package/dist/internal/upload/index.js.map +1 -1
- package/dist/internal/upload/interface.d.ts +3 -3
- package/dist/internal/upload/manager.d.ts +4 -4
- package/dist/internal/upload/manager.js +7 -5
- package/dist/internal/upload/manager.js.map +1 -1
- package/dist/internal/upload/manager.test.js +137 -123
- package/dist/internal/upload/manager.test.js.map +1 -1
- package/dist/internal/upload/streamUploader.d.ts +6 -6
- package/dist/internal/upload/streamUploader.js +8 -6
- package/dist/internal/upload/streamUploader.js.map +1 -1
- package/dist/internal/upload/streamUploader.test.js +16 -11
- package/dist/internal/upload/streamUploader.test.js.map +1 -1
- package/dist/internal/upload/telemetry.d.ts +3 -3
- package/dist/internal/upload/telemetry.js +5 -3
- package/dist/internal/upload/telemetry.js.map +1 -1
- package/dist/internal/upload/telemetry.test.js +8 -8
- package/dist/internal/upload/telemetry.test.js.map +1 -1
- package/dist/protonDriveClient.d.ts +8 -8
- package/dist/protonDriveClient.js +12 -9
- package/dist/protonDriveClient.js.map +1 -1
- package/dist/protonDrivePhotosClient.js.map +1 -1
- package/dist/telemetry.js +18 -15
- package/dist/telemetry.js.map +1 -1
- package/dist/tests/logger.js.map +1 -1
- package/dist/tests/telemetry.d.ts +1 -1
- package/dist/transformers.js +4 -2
- package/dist/transformers.js.map +1 -1
- package/package.json +1 -1
- package/src/cache/interface.ts +22 -22
- package/src/cache/memoryCache.test.ts +7 -7
- package/src/cache/memoryCache.ts +4 -4
- package/src/cache/nullCache.ts +1 -1
- package/src/config.ts +5 -5
- package/src/crypto/driveCrypto.test.ts +15 -15
- package/src/crypto/driveCrypto.ts +120 -156
- package/src/crypto/hmac.ts +1 -1
- package/src/crypto/interface.ts +63 -72
- package/src/crypto/openPGPCrypto.ts +74 -94
- package/src/crypto/utils.ts +1 -1
- package/src/diagnostic/eventsGenerator.ts +2 -2
- package/src/diagnostic/httpClient.ts +6 -2
- package/src/diagnostic/index.ts +12 -10
- package/src/diagnostic/integrityVerificationStream.ts +3 -4
- package/src/diagnostic/interface.ts +81 -81
- package/src/diagnostic/sdkDiagnostic.ts +35 -24
- package/src/diagnostic/sdkDiagnosticFull.ts +16 -19
- package/src/diagnostic/telemetry.ts +4 -1
- package/src/diagnostic/zipGenerators.test.ts +1 -1
- package/src/diagnostic/zipGenerators.ts +3 -3
- package/src/errors.ts +21 -21
- package/src/index.ts +3 -3
- package/src/interface/account.ts +10 -10
- package/src/interface/author.ts +6 -6
- package/src/interface/config.ts +4 -4
- package/src/interface/devices.ts +6 -6
- package/src/interface/download.ts +12 -9
- package/src/interface/events.ts +45 -39
- package/src/interface/httpClient.ts +11 -11
- package/src/interface/index.ts +76 -19
- package/src/interface/nodes.ts +47 -49
- package/src/interface/result.ts +1 -3
- package/src/interface/sharing.ts +60 -57
- package/src/interface/telemetry.ts +74 -74
- package/src/interface/thumbnail.ts +5 -6
- package/src/interface/upload.ts +20 -12
- package/src/internal/apiService/apiService.test.ts +109 -76
- package/src/internal/apiService/apiService.ts +40 -26
- package/src/internal/apiService/coreTypes.ts +2474 -2463
- package/src/internal/apiService/driveTypes.ts +1868 -1822
- package/src/internal/apiService/errorCodes.ts +4 -4
- package/src/internal/apiService/errors.test.ts +25 -23
- package/src/internal/apiService/errors.ts +15 -9
- package/src/internal/apiService/index.ts +1 -1
- package/src/internal/apiService/transformers.ts +2 -2
- package/src/internal/asyncIteratorMap.test.ts +4 -4
- package/src/internal/asyncIteratorMap.ts +1 -1
- package/src/internal/asyncIteratorRace.test.ts +149 -0
- package/src/internal/asyncIteratorRace.ts +79 -0
- package/src/internal/batch.test.ts +50 -0
- package/src/internal/batch.ts +9 -0
- package/src/internal/batchLoading.test.ts +13 -14
- package/src/internal/batchLoading.ts +8 -8
- package/src/internal/devices/apiService.ts +58 -51
- package/src/internal/devices/cryptoService.ts +22 -17
- package/src/internal/devices/index.ts +17 -10
- package/src/internal/devices/interface.ts +21 -12
- package/src/internal/devices/manager.test.ts +40 -9
- package/src/internal/devices/manager.ts +3 -3
- package/src/internal/download/apiService.ts +66 -49
- package/src/internal/download/cryptoService.ts +34 -18
- package/src/internal/download/fileDownloader.test.ts +25 -9
- package/src/internal/download/fileDownloader.ts +36 -18
- package/src/internal/download/index.ts +19 -19
- package/src/internal/download/interface.ts +19 -20
- package/src/internal/download/queue.ts +3 -3
- package/src/internal/download/telemetry.test.ts +11 -11
- package/src/internal/download/telemetry.ts +24 -14
- package/src/internal/download/thumbnailDownloader.test.ts +11 -6
- package/src/internal/download/thumbnailDownloader.ts +43 -32
- package/src/internal/errors.ts +7 -5
- package/src/internal/events/apiService.ts +30 -17
- package/src/internal/events/coreEventManager.test.ts +18 -18
- package/src/internal/events/coreEventManager.ts +9 -6
- package/src/internal/events/eventManager.test.ts +51 -46
- package/src/internal/events/eventManager.ts +6 -5
- package/src/internal/events/index.ts +24 -14
- package/src/internal/events/interface.ts +47 -39
- package/src/internal/events/volumeEventManager.test.ts +61 -65
- package/src/internal/events/volumeEventManager.ts +18 -9
- package/src/internal/nodes/apiService.test.ts +197 -147
- package/src/internal/nodes/apiService.ts +288 -174
- package/src/internal/nodes/cache.test.ts +48 -20
- package/src/internal/nodes/cache.ts +60 -44
- package/src/internal/nodes/cryptoCache.test.ts +34 -14
- package/src/internal/nodes/cryptoCache.ts +10 -5
- package/src/internal/nodes/cryptoService.test.ts +492 -351
- package/src/internal/nodes/cryptoService.ts +170 -88
- package/src/internal/nodes/events.test.ts +38 -28
- package/src/internal/nodes/events.ts +7 -5
- package/src/internal/nodes/extendedAttributes.test.ts +28 -24
- package/src/internal/nodes/extendedAttributes.ts +20 -15
- package/src/internal/nodes/index.test.ts +133 -0
- package/src/internal/nodes/index.ts +27 -15
- package/src/internal/nodes/interface.ts +42 -29
- package/src/internal/nodes/nodesAccess.test.ts +124 -58
- package/src/internal/nodes/nodesAccess.ts +73 -49
- package/src/internal/nodes/nodesManagement.test.ts +32 -31
- package/src/internal/nodes/nodesManagement.ts +39 -32
- package/src/internal/nodes/nodesRevisions.ts +7 -7
- package/src/internal/nodes/validations.ts +2 -2
- package/src/internal/photos/albums.ts +5 -5
- package/src/internal/photos/apiService.ts +4 -7
- package/src/internal/photos/cache.ts +1 -1
- package/src/internal/photos/index.ts +8 -8
- package/src/internal/photos/interface.ts +2 -2
- package/src/internal/photos/photosTimeline.ts +4 -5
- package/src/internal/sdkEvents.test.ts +10 -10
- package/src/internal/sdkEvents.ts +5 -13
- package/src/internal/shares/apiService.ts +44 -33
- package/src/internal/shares/cache.test.ts +6 -4
- package/src/internal/shares/cache.ts +21 -12
- package/src/internal/shares/cryptoCache.test.ts +17 -11
- package/src/internal/shares/cryptoCache.ts +4 -4
- package/src/internal/shares/cryptoService.test.ts +72 -74
- package/src/internal/shares/cryptoService.ts +48 -23
- package/src/internal/shares/index.ts +23 -11
- package/src/internal/shares/interface.ts +8 -8
- package/src/internal/shares/manager.test.ts +88 -80
- package/src/internal/shares/manager.ts +19 -19
- package/src/internal/sharing/apiService.ts +282 -175
- package/src/internal/sharing/cache.test.ts +35 -35
- package/src/internal/sharing/cache.ts +2 -2
- package/src/internal/sharing/cryptoService.test.ts +58 -46
- package/src/internal/sharing/cryptoService.ts +121 -84
- package/src/internal/sharing/events.test.ts +45 -49
- package/src/internal/sharing/events.ts +9 -6
- package/src/internal/sharing/index.ts +22 -11
- package/src/internal/sharing/interface.ts +40 -40
- package/src/internal/sharing/sharingAccess.test.ts +71 -65
- package/src/internal/sharing/sharingAccess.ts +39 -21
- package/src/internal/sharing/sharingManagement.test.ts +398 -298
- package/src/internal/sharing/sharingManagement.ts +138 -65
- package/src/internal/uids.ts +1 -1
- package/src/internal/upload/apiService.ts +167 -117
- package/src/internal/upload/blockVerifier.ts +8 -6
- package/src/internal/upload/chunkStreamReader.test.ts +7 -7
- package/src/internal/upload/cryptoService.ts +42 -36
- package/src/internal/upload/digests.ts +2 -2
- package/src/internal/upload/fileUploader.test.ts +15 -3
- package/src/internal/upload/fileUploader.ts +39 -17
- package/src/internal/upload/index.ts +13 -14
- package/src/internal/upload/interface.ts +78 -78
- package/src/internal/upload/manager.test.ts +170 -153
- package/src/internal/upload/manager.ts +59 -35
- package/src/internal/upload/queue.ts +3 -3
- package/src/internal/upload/streamUploader.test.ts +40 -26
- package/src/internal/upload/streamUploader.ts +87 -69
- package/src/internal/upload/telemetry.test.ts +11 -11
- package/src/internal/upload/telemetry.ts +25 -15
- package/src/internal/wait.test.ts +1 -1
- package/src/internal/wait.ts +3 -3
- package/src/protonDriveClient.ts +121 -39
- package/src/protonDrivePhotosClient.ts +16 -10
- package/src/telemetry.ts +60 -52
- package/src/tests/logger.ts +1 -1
- package/src/tests/telemetry.ts +2 -2
- package/src/transformers.ts +27 -21
- package/src/version.ts +0 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { c } from 'ttag';
|
|
2
2
|
|
|
3
|
-
import { NodeType, ThumbnailType, ProtonDriveTelemetry, Logger, ThumbnailResult } from
|
|
3
|
+
import { NodeType, ThumbnailType, ProtonDriveTelemetry, Logger, ThumbnailResult } from '../../interface';
|
|
4
4
|
import { ValidationError } from '../../errors';
|
|
5
5
|
import { LoggerWithPrefix } from '../../telemetry';
|
|
6
|
-
import { DownloadAPIService } from
|
|
7
|
-
import { DownloadCryptoService } from
|
|
8
|
-
import { NodesService } from
|
|
6
|
+
import { DownloadAPIService } from './apiService';
|
|
7
|
+
import { DownloadCryptoService } from './cryptoService';
|
|
8
|
+
import { NodesService } from './interface';
|
|
9
9
|
import { getErrorMessage } from '../errors';
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -24,8 +24,8 @@ export class ThumbnailDownloader {
|
|
|
24
24
|
private batchThumbnailToNodeUids = new Map<string, string>();
|
|
25
25
|
private ongoingDownloads = new Map<string, Promise<void>>();
|
|
26
26
|
private bufferedThumbnails: (
|
|
27
|
-
{ nodeUid: string
|
|
28
|
-
{ nodeUid: string
|
|
27
|
+
| { nodeUid: string; ok: true; thumbnail: Uint8Array }
|
|
28
|
+
| { nodeUid: string; ok: false; error: string }
|
|
29
29
|
)[] = [];
|
|
30
30
|
|
|
31
31
|
constructor(
|
|
@@ -34,7 +34,7 @@ export class ThumbnailDownloader {
|
|
|
34
34
|
private apiService: DownloadAPIService,
|
|
35
35
|
private cryptoService: DownloadCryptoService,
|
|
36
36
|
) {
|
|
37
|
-
this.logger = telemetry.getLogger(
|
|
37
|
+
this.logger = telemetry.getLogger('download');
|
|
38
38
|
this.nodesService = nodesService;
|
|
39
39
|
this.apiService = apiService;
|
|
40
40
|
this.cryptoService = cryptoService;
|
|
@@ -79,40 +79,41 @@ export class ThumbnailDownloader {
|
|
|
79
79
|
this.bufferedThumbnails = [];
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
private async *iterateThumbnailUids(
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
private async *iterateThumbnailUids(
|
|
83
|
+
nodeUids: string[],
|
|
84
|
+
thumbnailType: ThumbnailType,
|
|
85
|
+
signal?: AbortSignal,
|
|
86
|
+
): AsyncGenerator<
|
|
87
|
+
{ nodeUid: string; ok: true; thumbnailUid: string } | { nodeUid: string; ok: false; error: string }
|
|
85
88
|
> {
|
|
86
89
|
for await (const node of this.nodesService.iterateNodes(nodeUids, signal)) {
|
|
87
90
|
if ('missingUid' in node) {
|
|
88
91
|
yield {
|
|
89
92
|
nodeUid: node.missingUid,
|
|
90
93
|
ok: false,
|
|
91
|
-
error: c(
|
|
92
|
-
}
|
|
94
|
+
error: c('Error').t`Node not found`,
|
|
95
|
+
};
|
|
93
96
|
continue;
|
|
94
97
|
}
|
|
95
98
|
if (node.type !== NodeType.File) {
|
|
96
99
|
yield {
|
|
97
100
|
nodeUid: node.uid,
|
|
98
101
|
ok: false,
|
|
99
|
-
error: c(
|
|
100
|
-
}
|
|
102
|
+
error: c('Error').t`Node is not a file`,
|
|
103
|
+
};
|
|
101
104
|
continue;
|
|
102
105
|
}
|
|
103
106
|
|
|
104
107
|
let thumbnail;
|
|
105
108
|
if (node.activeRevision?.ok) {
|
|
106
|
-
thumbnail = node.activeRevision.value.thumbnails?.find(
|
|
107
|
-
(t) => t.type === thumbnailType,
|
|
108
|
-
);
|
|
109
|
+
thumbnail = node.activeRevision.value.thumbnails?.find((t) => t.type === thumbnailType);
|
|
109
110
|
}
|
|
110
111
|
if (!thumbnail) {
|
|
111
112
|
yield {
|
|
112
113
|
nodeUid: node.uid,
|
|
113
114
|
ok: false,
|
|
114
|
-
error: c(
|
|
115
|
-
}
|
|
115
|
+
error: c('Error').t`Node has no thumbnail`,
|
|
116
|
+
};
|
|
116
117
|
continue;
|
|
117
118
|
}
|
|
118
119
|
|
|
@@ -120,7 +121,7 @@ export class ThumbnailDownloader {
|
|
|
120
121
|
nodeUid: node.uid,
|
|
121
122
|
ok: true,
|
|
122
123
|
thumbnailUid: thumbnail.uid,
|
|
123
|
-
}
|
|
124
|
+
};
|
|
124
125
|
}
|
|
125
126
|
}
|
|
126
127
|
|
|
@@ -163,13 +164,15 @@ export class ThumbnailDownloader {
|
|
|
163
164
|
}),
|
|
164
165
|
);
|
|
165
166
|
}
|
|
166
|
-
|
|
167
|
+
|
|
167
168
|
this.batchThumbnailToNodeUids.clear();
|
|
168
169
|
}
|
|
169
170
|
|
|
170
|
-
private async *iterateThumbnailDownloads(
|
|
171
|
-
|
|
172
|
-
|
|
171
|
+
private async *iterateThumbnailDownloads(
|
|
172
|
+
signal?: AbortSignal,
|
|
173
|
+
): AsyncGenerator<
|
|
174
|
+
| { nodeUid: string; ok: true; downloadPromise: Promise<Uint8Array> }
|
|
175
|
+
| { nodeUid: string; ok: false; error: string }
|
|
173
176
|
> {
|
|
174
177
|
const missingThumbnailUids = new Set(this.batchThumbnailToNodeUids.keys());
|
|
175
178
|
|
|
@@ -190,7 +193,7 @@ export class ThumbnailDownloader {
|
|
|
190
193
|
nodeUid,
|
|
191
194
|
ok: false,
|
|
192
195
|
error: result.error,
|
|
193
|
-
}
|
|
196
|
+
};
|
|
194
197
|
continue;
|
|
195
198
|
}
|
|
196
199
|
|
|
@@ -198,7 +201,7 @@ export class ThumbnailDownloader {
|
|
|
198
201
|
nodeUid,
|
|
199
202
|
ok: true,
|
|
200
203
|
downloadPromise: this.downloadThumbnail(nodeUid, result.bareUrl, result.token, signal),
|
|
201
|
-
}
|
|
204
|
+
};
|
|
202
205
|
}
|
|
203
206
|
|
|
204
207
|
for (const uid of missingThumbnailUids) {
|
|
@@ -207,14 +210,19 @@ export class ThumbnailDownloader {
|
|
|
207
210
|
yield {
|
|
208
211
|
nodeUid,
|
|
209
212
|
ok: false,
|
|
210
|
-
error: c(
|
|
211
|
-
}
|
|
213
|
+
error: c('Error').t`Thumbnail not found`,
|
|
214
|
+
};
|
|
212
215
|
}
|
|
213
216
|
}
|
|
214
217
|
|
|
215
|
-
private async downloadThumbnail(
|
|
218
|
+
private async downloadThumbnail(
|
|
219
|
+
nodeUid: string,
|
|
220
|
+
bareUrl: string,
|
|
221
|
+
token: string,
|
|
222
|
+
signal?: AbortSignal,
|
|
223
|
+
): Promise<Uint8Array> {
|
|
216
224
|
const logger = new LoggerWithPrefix(this.logger, `thumbnail ${token}`);
|
|
217
|
-
|
|
225
|
+
|
|
218
226
|
let decryptedBlock: Uint8Array | null = null;
|
|
219
227
|
let attempt = 0;
|
|
220
228
|
|
|
@@ -229,11 +237,14 @@ export class ThumbnailDownloader {
|
|
|
229
237
|
]);
|
|
230
238
|
|
|
231
239
|
if (!nodeKeys.contentKeyPacketSessionKey) {
|
|
232
|
-
throw new ValidationError(c(
|
|
240
|
+
throw new ValidationError(c('Error').t`File has no content key`);
|
|
233
241
|
}
|
|
234
242
|
|
|
235
243
|
logger.debug(`Decrypting`);
|
|
236
|
-
decryptedBlock = await this.cryptoService.decryptThumbnail(
|
|
244
|
+
decryptedBlock = await this.cryptoService.decryptThumbnail(
|
|
245
|
+
encryptedBlock,
|
|
246
|
+
nodeKeys.contentKeyPacketSessionKey,
|
|
247
|
+
);
|
|
237
248
|
} catch (error: unknown) {
|
|
238
249
|
if (attempt <= MAX_THUMBNAIL_DOWNLOAD_ATTEMPTS) {
|
|
239
250
|
logger.warn(`Thumbnail download failed #${attempt}, retrying: ${getErrorMessage(error)}`);
|
package/src/internal/errors.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { c } from 'ttag';
|
|
2
2
|
|
|
3
|
-
import { VERIFICATION_STATUS } from
|
|
3
|
+
import { VERIFICATION_STATUS } from '../crypto';
|
|
4
4
|
|
|
5
5
|
export function getErrorMessage(error: unknown): string {
|
|
6
6
|
return error instanceof Error ? error.message : c('Error').t`Unknown error`;
|
|
@@ -9,11 +9,13 @@ export function getErrorMessage(error: unknown): string {
|
|
|
9
9
|
/**
|
|
10
10
|
* @param signatureType - Must be translated before calling this function.
|
|
11
11
|
*/
|
|
12
|
-
export function getVerificationMessage(
|
|
12
|
+
export function getVerificationMessage(
|
|
13
|
+
verified: VERIFICATION_STATUS,
|
|
14
|
+
signatureType?: string,
|
|
15
|
+
notAvailableVerificationKeys = false,
|
|
16
|
+
): string {
|
|
13
17
|
if (verified === VERIFICATION_STATUS.NOT_SIGNED) {
|
|
14
|
-
return signatureType
|
|
15
|
-
? c('Error').t`Missing signature for ${signatureType}`
|
|
16
|
-
: c('Error').t`Missing signature`;
|
|
18
|
+
return signatureType ? c('Error').t`Missing signature for ${signatureType}` : c('Error').t`Missing signature`;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
if (notAvailableVerificationKeys) {
|
|
@@ -1,22 +1,26 @@
|
|
|
1
|
-
import { DriveAPIService, drivePaths, corePaths } from
|
|
2
|
-
import { makeNodeUid } from
|
|
3
|
-
import { DriveEventsListWithStatus, DriveEvent, DriveEventType, NodeEvent, NodeEventType } from
|
|
1
|
+
import { DriveAPIService, drivePaths, corePaths } from '../apiService';
|
|
2
|
+
import { makeNodeUid } from '../uids';
|
|
3
|
+
import { DriveEventsListWithStatus, DriveEvent, DriveEventType, NodeEvent, NodeEventType } from './interface';
|
|
4
4
|
|
|
5
|
-
type GetCoreLatestEventResponse =
|
|
6
|
-
|
|
5
|
+
type GetCoreLatestEventResponse =
|
|
6
|
+
corePaths['/core/{_version}/events/latest']['get']['responses']['200']['content']['application/json'];
|
|
7
|
+
type GetCoreEventResponse =
|
|
8
|
+
corePaths['/core/{_version}/events/{id}']['get']['responses']['200']['content']['application/json'];
|
|
7
9
|
|
|
8
|
-
type GetVolumeLatestEventResponse =
|
|
9
|
-
|
|
10
|
+
type GetVolumeLatestEventResponse =
|
|
11
|
+
drivePaths['/drive/volumes/{volumeID}/events/latest']['get']['responses']['200']['content']['application/json'];
|
|
12
|
+
type GetVolumeEventResponse =
|
|
13
|
+
drivePaths['/drive/v2/volumes/{volumeID}/events/{eventID}']['get']['responses']['200']['content']['application/json'];
|
|
10
14
|
|
|
11
15
|
interface VolumeEventTypeMap {
|
|
12
|
-
[key: number]: NodeEventType
|
|
16
|
+
[key: number]: NodeEventType;
|
|
13
17
|
}
|
|
14
18
|
const VOLUME_EVENT_TYPE_MAP: VolumeEventTypeMap = {
|
|
15
19
|
0: DriveEventType.NodeDeleted,
|
|
16
20
|
1: DriveEventType.NodeCreated,
|
|
17
21
|
2: DriveEventType.NodeUpdated,
|
|
18
22
|
3: DriveEventType.NodeUpdated,
|
|
19
|
-
}
|
|
23
|
+
};
|
|
20
24
|
|
|
21
25
|
/**
|
|
22
26
|
* Provides API communication for fetching events.
|
|
@@ -39,11 +43,16 @@ export class EventsAPIService {
|
|
|
39
43
|
const result = await this.apiService.get<GetCoreEventResponse>(`core/v5/events/${eventId}`);
|
|
40
44
|
// in core/v5/events, refresh is always all apps, value 255
|
|
41
45
|
const refresh = result.Refresh > 0;
|
|
42
|
-
const events: DriveEvent[] =
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
const events: DriveEvent[] =
|
|
47
|
+
refresh || result.DriveShareRefresh?.Action === 2
|
|
48
|
+
? [
|
|
49
|
+
{
|
|
50
|
+
type: DriveEventType.SharedWithMeUpdated,
|
|
51
|
+
eventId: result.EventID,
|
|
52
|
+
treeEventScopeId: 'core',
|
|
53
|
+
},
|
|
54
|
+
]
|
|
55
|
+
: [];
|
|
47
56
|
|
|
48
57
|
return {
|
|
49
58
|
latestEventId: result.EventID,
|
|
@@ -54,12 +63,16 @@ export class EventsAPIService {
|
|
|
54
63
|
}
|
|
55
64
|
|
|
56
65
|
async getVolumeLatestEventId(volumeId: string): Promise<string> {
|
|
57
|
-
const result = await this.apiService.get<GetVolumeLatestEventResponse>(
|
|
66
|
+
const result = await this.apiService.get<GetVolumeLatestEventResponse>(
|
|
67
|
+
`drive/volumes/${volumeId}/events/latest`,
|
|
68
|
+
);
|
|
58
69
|
return result.EventID;
|
|
59
70
|
}
|
|
60
71
|
|
|
61
72
|
async getVolumeEvents(volumeId: string, eventId: string): Promise<DriveEventsListWithStatus> {
|
|
62
|
-
const result = await this.apiService.get<GetVolumeEventResponse>(
|
|
73
|
+
const result = await this.apiService.get<GetVolumeEventResponse>(
|
|
74
|
+
`drive/v2/volumes/${volumeId}/events/${eventId}`,
|
|
75
|
+
);
|
|
63
76
|
return {
|
|
64
77
|
latestEventId: result.EventID,
|
|
65
78
|
more: result.More,
|
|
@@ -69,7 +82,7 @@ export class EventsAPIService {
|
|
|
69
82
|
const uids = {
|
|
70
83
|
nodeUid: makeNodeUid(volumeId, event.Link.LinkID),
|
|
71
84
|
parentNodeUid: makeNodeUid(volumeId, event.Link.ParentLinkID as string),
|
|
72
|
-
}
|
|
85
|
+
};
|
|
73
86
|
return {
|
|
74
87
|
type,
|
|
75
88
|
...uids,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { getMockLogger } from
|
|
2
|
-
import { EventsAPIService } from
|
|
3
|
-
import { DriveEvent, DriveEventsListWithStatus, DriveEventType } from
|
|
4
|
-
import { CoreEventManager } from
|
|
1
|
+
import { getMockLogger } from '../../tests/logger';
|
|
2
|
+
import { EventsAPIService } from './apiService';
|
|
3
|
+
import { DriveEvent, DriveEventsListWithStatus, DriveEventType } from './interface';
|
|
4
|
+
import { CoreEventManager } from './coreEventManager';
|
|
5
5
|
|
|
6
|
-
describe(
|
|
6
|
+
describe('CoreEventManager', () => {
|
|
7
7
|
let mockApiService: jest.Mocked<EventsAPIService>;
|
|
8
8
|
let coreEventManager: CoreEventManager;
|
|
9
9
|
const mockLogger = getMockLogger();
|
|
@@ -22,9 +22,9 @@ describe("CoreEventManager", () => {
|
|
|
22
22
|
coreEventManager = new CoreEventManager(mockLogger, mockApiService);
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
-
describe(
|
|
26
|
-
it(
|
|
27
|
-
const expectedEventId =
|
|
25
|
+
describe('getLatestEventId', () => {
|
|
26
|
+
it('should return the latest event ID from API service', async () => {
|
|
27
|
+
const expectedEventId = 'event-123';
|
|
28
28
|
mockApiService.getCoreLatestEventId.mockResolvedValue(expectedEventId);
|
|
29
29
|
|
|
30
30
|
const result = await coreEventManager.getLatestEventId();
|
|
@@ -33,20 +33,20 @@ describe("CoreEventManager", () => {
|
|
|
33
33
|
expect(mockApiService.getCoreLatestEventId).toHaveBeenCalledTimes(1);
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
-
it(
|
|
37
|
-
const error = new Error(
|
|
36
|
+
it('should handle API service errors', async () => {
|
|
37
|
+
const error = new Error('API error');
|
|
38
38
|
mockApiService.getCoreLatestEventId.mockRejectedValue(error);
|
|
39
39
|
|
|
40
|
-
await expect(coreEventManager.getLatestEventId()).rejects.toThrow(
|
|
40
|
+
await expect(coreEventManager.getLatestEventId()).rejects.toThrow('API error');
|
|
41
41
|
expect(mockApiService.getCoreLatestEventId).toHaveBeenCalledTimes(1);
|
|
42
42
|
});
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
-
describe(
|
|
46
|
-
const eventId =
|
|
47
|
-
const latestEventId =
|
|
45
|
+
describe('getEvents', () => {
|
|
46
|
+
const eventId = 'event1';
|
|
47
|
+
const latestEventId = 'event2';
|
|
48
48
|
|
|
49
|
-
it(
|
|
49
|
+
it('should yield ShareWithMeUpdated event when refresh is true', async () => {
|
|
50
50
|
const mockEvents: DriveEventsListWithStatus = {
|
|
51
51
|
latestEventId,
|
|
52
52
|
more: false,
|
|
@@ -69,15 +69,15 @@ describe("CoreEventManager", () => {
|
|
|
69
69
|
expect(mockApiService.getCoreEvents).toHaveBeenCalledWith(eventId);
|
|
70
70
|
});
|
|
71
71
|
|
|
72
|
-
it(
|
|
72
|
+
it('should yield all events when there are actual events', async () => {
|
|
73
73
|
const mockEvent1: DriveEvent = {
|
|
74
74
|
type: DriveEventType.SharedWithMeUpdated,
|
|
75
|
-
eventId:
|
|
75
|
+
eventId: 'event-1',
|
|
76
76
|
treeEventScopeId: 'core',
|
|
77
77
|
};
|
|
78
78
|
const mockEvent2: DriveEvent = {
|
|
79
79
|
type: DriveEventType.SharedWithMeUpdated,
|
|
80
|
-
eventId:
|
|
80
|
+
eventId: 'event-2',
|
|
81
81
|
treeEventScopeId: 'core',
|
|
82
82
|
};
|
|
83
83
|
const mockEvents: DriveEventsListWithStatus = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Logger } from
|
|
2
|
-
import { LoggerWithPrefix } from
|
|
3
|
-
import { EventsAPIService } from
|
|
4
|
-
import { DriveEvent, DriveEventType, EventManagerInterface } from
|
|
1
|
+
import { Logger } from '../../interface';
|
|
2
|
+
import { LoggerWithPrefix } from '../../telemetry';
|
|
3
|
+
import { EventsAPIService } from './apiService';
|
|
4
|
+
import { DriveEvent, DriveEventType, EventManagerInterface } from './interface';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Combines API and event manager to provide a service for listening to
|
|
@@ -15,7 +15,10 @@ import { DriveEvent, DriveEventType, EventManagerInterface } from "./interface";
|
|
|
15
15
|
* with own implementation.
|
|
16
16
|
*/
|
|
17
17
|
export class CoreEventManager implements EventManagerInterface<DriveEvent> {
|
|
18
|
-
constructor(
|
|
18
|
+
constructor(
|
|
19
|
+
private logger: Logger,
|
|
20
|
+
private apiService: EventsAPIService,
|
|
21
|
+
) {
|
|
19
22
|
this.apiService = apiService;
|
|
20
23
|
|
|
21
24
|
this.logger = new LoggerWithPrefix(logger, `core`);
|
|
@@ -25,7 +28,7 @@ export class CoreEventManager implements EventManagerInterface<DriveEvent> {
|
|
|
25
28
|
return await this.apiService.getCoreLatestEventId();
|
|
26
29
|
}
|
|
27
30
|
|
|
28
|
-
async *
|
|
31
|
+
async *getEvents(eventId: string): AsyncIterable<DriveEvent> {
|
|
29
32
|
const events = await this.apiService.getCoreEvents(eventId);
|
|
30
33
|
if (events.events.length === 0 && events.latestEventId !== eventId) {
|
|
31
34
|
yield {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { getMockLogger } from
|
|
2
|
-
import { EventManager } from
|
|
3
|
-
import { DriveEvent, DriveEventType, EventSubscription, UnsubscribeFromEventsSourceError } from
|
|
1
|
+
import { getMockLogger } from '../../tests/logger';
|
|
2
|
+
import { EventManager } from './eventManager';
|
|
3
|
+
import { DriveEvent, DriveEventType, EventSubscription, UnsubscribeFromEventsSourceError } from './interface';
|
|
4
4
|
|
|
5
5
|
jest.useFakeTimers();
|
|
6
6
|
|
|
7
7
|
const POLLING_INTERVAL = 1;
|
|
8
8
|
|
|
9
|
-
describe(
|
|
9
|
+
describe('EventManager', () => {
|
|
10
10
|
let manager: EventManager<DriveEvent>;
|
|
11
11
|
|
|
12
12
|
const getLatestEventIdMock = jest.fn();
|
|
@@ -22,11 +22,7 @@ describe("EventManager", () => {
|
|
|
22
22
|
getEvents: getEventsMock,
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
manager = new EventManager(
|
|
26
|
-
mockEventManager as any,
|
|
27
|
-
POLLING_INTERVAL,
|
|
28
|
-
null,
|
|
29
|
-
);
|
|
25
|
+
manager = new EventManager(mockEventManager as any, POLLING_INTERVAL, null);
|
|
30
26
|
const subscription = manager.addListener(listenerMock);
|
|
31
27
|
subscriptions.push(subscription);
|
|
32
28
|
});
|
|
@@ -40,28 +36,34 @@ describe("EventManager", () => {
|
|
|
40
36
|
jest.clearAllMocks();
|
|
41
37
|
});
|
|
42
38
|
|
|
43
|
-
it(
|
|
39
|
+
it('should start polling when started', async () => {
|
|
44
40
|
getLatestEventIdMock.mockResolvedValue('EventId1');
|
|
45
41
|
|
|
46
42
|
const mockEvents: DriveEvent[][] = [
|
|
47
|
-
[
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
43
|
+
[
|
|
44
|
+
{
|
|
45
|
+
type: DriveEventType.FastForward,
|
|
46
|
+
treeEventScopeId: 'volume1',
|
|
47
|
+
eventId: 'EventId2',
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
[
|
|
51
|
+
{
|
|
52
|
+
type: DriveEventType.FastForward,
|
|
53
|
+
treeEventScopeId: 'volume1',
|
|
54
|
+
eventId: 'EventId3',
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
57
|
];
|
|
58
58
|
|
|
59
|
-
getEventsMock
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
59
|
+
getEventsMock
|
|
60
|
+
.mockImplementationOnce(async function* () {
|
|
61
|
+
yield* mockEvents[0];
|
|
62
|
+
})
|
|
63
|
+
.mockImplementationOnce(async function* () {
|
|
64
|
+
yield* mockEvents[1];
|
|
65
|
+
})
|
|
66
|
+
.mockImplementationOnce(async function* () {});
|
|
65
67
|
|
|
66
68
|
expect(getLatestEventIdMock).toHaveBeenCalledTimes(0);
|
|
67
69
|
expect(getEventsMock).toHaveBeenCalledTimes(0);
|
|
@@ -76,7 +78,7 @@ describe("EventManager", () => {
|
|
|
76
78
|
expect(getEventsMock).toHaveBeenCalledWith('EventId2');
|
|
77
79
|
});
|
|
78
80
|
|
|
79
|
-
it(
|
|
81
|
+
it('should stop polling when stopped', async () => {
|
|
80
82
|
getLatestEventIdMock.mockResolvedValue('eventId1');
|
|
81
83
|
getEventsMock.mockImplementation(async function* () {
|
|
82
84
|
yield {
|
|
@@ -97,7 +99,7 @@ describe("EventManager", () => {
|
|
|
97
99
|
expect(getEventsMock).toHaveBeenCalledTimes(callsBeforeStop);
|
|
98
100
|
});
|
|
99
101
|
|
|
100
|
-
it(
|
|
102
|
+
it('should notify all listeners when getting events', async () => {
|
|
101
103
|
getLatestEventIdMock.mockResolvedValue('eventId1');
|
|
102
104
|
|
|
103
105
|
const mockEvents: DriveEvent[] = [
|
|
@@ -112,10 +114,11 @@ describe("EventManager", () => {
|
|
|
112
114
|
},
|
|
113
115
|
];
|
|
114
116
|
|
|
115
|
-
getEventsMock
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
117
|
+
getEventsMock
|
|
118
|
+
.mockImplementationOnce(async function* () {
|
|
119
|
+
yield* mockEvents;
|
|
120
|
+
})
|
|
121
|
+
.mockImplementation(async function* () {});
|
|
119
122
|
|
|
120
123
|
expect(await manager.start()).toBeUndefined();
|
|
121
124
|
await jest.runOnlyPendingTimersAsync();
|
|
@@ -123,9 +126,9 @@ describe("EventManager", () => {
|
|
|
123
126
|
expect(listenerMock).toHaveBeenNthCalledWith(1, mockEvents[0]);
|
|
124
127
|
});
|
|
125
128
|
|
|
126
|
-
it(
|
|
129
|
+
it('should propagate unsubscription errors', async () => {
|
|
127
130
|
getLatestEventIdMock.mockImplementation(() => {
|
|
128
|
-
throw new UnsubscribeFromEventsSourceError(
|
|
131
|
+
throw new UnsubscribeFromEventsSourceError('Not found');
|
|
129
132
|
});
|
|
130
133
|
|
|
131
134
|
await expect(manager.start()).rejects.toThrow(UnsubscribeFromEventsSourceError);
|
|
@@ -135,7 +138,7 @@ describe("EventManager", () => {
|
|
|
135
138
|
expect(getEventsMock).toHaveBeenCalledTimes(0);
|
|
136
139
|
});
|
|
137
140
|
|
|
138
|
-
it(
|
|
141
|
+
it('should continue processing multiple events', async () => {
|
|
139
142
|
getLatestEventIdMock.mockResolvedValue('eventId1');
|
|
140
143
|
|
|
141
144
|
const mockEvents: DriveEvent[] = [
|
|
@@ -156,14 +159,16 @@ describe("EventManager", () => {
|
|
|
156
159
|
isShared: false,
|
|
157
160
|
treeEventScopeId: 'volume1',
|
|
158
161
|
eventId: 'eventId3',
|
|
159
|
-
}
|
|
162
|
+
},
|
|
160
163
|
];
|
|
161
164
|
|
|
162
|
-
getEventsMock
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
getEventsMock
|
|
166
|
+
.mockImplementationOnce(async function* () {
|
|
167
|
+
yield* mockEvents;
|
|
168
|
+
})
|
|
169
|
+
.mockImplementation(async function* () {
|
|
170
|
+
// Empty generator for subsequent calls
|
|
171
|
+
});
|
|
167
172
|
|
|
168
173
|
await manager.start();
|
|
169
174
|
await jest.runOnlyPendingTimersAsync();
|
|
@@ -174,21 +179,21 @@ describe("EventManager", () => {
|
|
|
174
179
|
|
|
175
180
|
getEventsMock.mockImplementationOnce(async function* () {
|
|
176
181
|
yield* mockEvents;
|
|
177
|
-
})
|
|
182
|
+
});
|
|
178
183
|
await jest.runOnlyPendingTimersAsync();
|
|
179
184
|
expect(listenerMock).toHaveBeenCalledTimes(4);
|
|
180
185
|
expect(listenerMock).toHaveBeenNthCalledWith(1, mockEvents[0]);
|
|
181
186
|
expect(listenerMock).toHaveBeenNthCalledWith(2, mockEvents[1]);
|
|
182
187
|
});
|
|
183
188
|
|
|
184
|
-
it(
|
|
189
|
+
it('should retry on error with exponential backoff', async () => {
|
|
185
190
|
getLatestEventIdMock.mockResolvedValue('eventId1');
|
|
186
191
|
|
|
187
192
|
let callCount = 0;
|
|
188
193
|
getEventsMock.mockImplementation(async function* () {
|
|
189
194
|
callCount++;
|
|
190
195
|
if (callCount <= 3) {
|
|
191
|
-
throw new Error(
|
|
196
|
+
throw new Error('Network error');
|
|
192
197
|
}
|
|
193
198
|
yield {
|
|
194
199
|
type: DriveEventType.FastForward,
|
|
@@ -218,7 +223,7 @@ describe("EventManager", () => {
|
|
|
218
223
|
expect(manager['retryIndex']).toEqual(0);
|
|
219
224
|
});
|
|
220
225
|
|
|
221
|
-
it(
|
|
226
|
+
it('should stop polling when stopped immediately', async () => {
|
|
222
227
|
getLatestEventIdMock.mockResolvedValue('eventId1');
|
|
223
228
|
getEventsMock.mockImplementation(async function* () {
|
|
224
229
|
yield {
|
|
@@ -237,7 +242,7 @@ describe("EventManager", () => {
|
|
|
237
242
|
expect(getEventsMock).toHaveBeenCalledTimes(1);
|
|
238
243
|
});
|
|
239
244
|
|
|
240
|
-
it(
|
|
245
|
+
it('should handle empty event streams', async () => {
|
|
241
246
|
getLatestEventIdMock.mockResolvedValue('eventId1');
|
|
242
247
|
|
|
243
248
|
getEventsMock.mockImplementation(async function* () {
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { Logger } from
|
|
2
|
-
import { EventManagerInterface, Event, EventSubscription } from
|
|
1
|
+
import { Logger } from '../../interface';
|
|
2
|
+
import { EventManagerInterface, Event, EventSubscription } from './interface';
|
|
3
3
|
|
|
4
4
|
const FIBONACCI_LIST = [1, 1, 2, 3, 5, 8, 13];
|
|
5
5
|
|
|
6
6
|
type Listener<T> = (event: T) => Promise<void>;
|
|
7
7
|
|
|
8
|
-
|
|
9
8
|
/**
|
|
10
9
|
* Event manager general helper that is responsible for fetching events
|
|
11
10
|
* from the server and notifying listeners about the events.
|
|
@@ -99,7 +98,9 @@ export class EventManager<T extends Event> {
|
|
|
99
98
|
this.retryIndex = 0;
|
|
100
99
|
} catch (error: unknown) {
|
|
101
100
|
// This could be improved to catch api specific errors and let the listener errors bubble up directly
|
|
102
|
-
this.logger.error(
|
|
101
|
+
this.logger.error(
|
|
102
|
+
`Failed to process events: ${error instanceof Error ? error.message : error} (retry ${this.retryIndex}, last event ID: ${this.latestEventId})`,
|
|
103
|
+
);
|
|
103
104
|
this.retryIndex++;
|
|
104
105
|
}
|
|
105
106
|
if (listenerError) {
|
|
@@ -109,7 +110,7 @@ export class EventManager<T extends Event> {
|
|
|
109
110
|
this.timeoutHandle = setTimeout(() => {
|
|
110
111
|
this.processPromise = this.processEvents();
|
|
111
112
|
}, this.nextPollTimeout);
|
|
112
|
-
}
|
|
113
|
+
}
|
|
113
114
|
|
|
114
115
|
/**
|
|
115
116
|
* Polling timeout is using exponential backoff with Fibonacci sequence.
|