@protontech/drive-sdk 0.0.13 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cache/index.d.ts +1 -0
- package/dist/cache/index.js +3 -1
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/memoryCache.d.ts +1 -1
- 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.d.ts +14 -0
- package/dist/cache/nullCache.js +36 -0
- package/dist/cache/nullCache.js.map +1 -0
- package/dist/config.d.ts +16 -1
- package/dist/config.js +1 -1
- package/dist/config.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 +5 -3
- package/dist/crypto/openPGPCrypto.js.map +1 -1
- package/dist/diagnostic/eventsGenerator.d.ts +14 -0
- package/dist/diagnostic/eventsGenerator.js +49 -0
- package/dist/diagnostic/eventsGenerator.js.map +1 -0
- package/dist/diagnostic/httpClient.d.ts +16 -0
- package/dist/diagnostic/httpClient.js +81 -0
- package/dist/diagnostic/httpClient.js.map +1 -0
- package/dist/diagnostic/index.d.ts +10 -0
- package/dist/diagnostic/index.js +35 -0
- package/dist/diagnostic/index.js.map +1 -0
- package/dist/diagnostic/integrityVerificationStream.d.ts +21 -0
- package/dist/diagnostic/integrityVerificationStream.js +56 -0
- package/dist/diagnostic/integrityVerificationStream.js.map +1 -0
- package/dist/diagnostic/interface.d.ts +102 -0
- package/dist/diagnostic/interface.js +3 -0
- package/dist/diagnostic/interface.js.map +1 -0
- package/dist/diagnostic/sdkDiagnostic.d.ts +22 -0
- package/dist/diagnostic/sdkDiagnostic.js +222 -0
- package/dist/diagnostic/sdkDiagnostic.js.map +1 -0
- package/dist/diagnostic/sdkDiagnosticFull.d.ts +18 -0
- package/dist/diagnostic/sdkDiagnosticFull.js +35 -0
- package/dist/diagnostic/sdkDiagnosticFull.js.map +1 -0
- package/dist/diagnostic/telemetry.d.ts +25 -0
- package/dist/diagnostic/telemetry.js +70 -0
- package/dist/diagnostic/telemetry.js.map +1 -0
- package/dist/diagnostic/zipGenerators.d.ts +9 -0
- package/dist/diagnostic/zipGenerators.js +64 -0
- package/dist/diagnostic/zipGenerators.js.map +1 -0
- package/dist/diagnostic/zipGenerators.test.js +144 -0
- package/dist/diagnostic/zipGenerators.test.js.map +1 -0
- package/dist/errors.d.ts +2 -1
- package/dist/errors.js +3 -1
- package/dist/errors.js.map +1 -1
- package/dist/interface/config.d.ts +26 -0
- package/dist/interface/config.js +3 -0
- package/dist/interface/config.js.map +1 -0
- package/dist/interface/download.d.ts +2 -2
- package/dist/interface/events.d.ts +58 -20
- package/dist/interface/events.js +11 -1
- package/dist/interface/events.js.map +1 -1
- package/dist/interface/httpClient.d.ts +0 -14
- package/dist/interface/index.d.ts +11 -7
- package/dist/interface/index.js +2 -2
- package/dist/interface/index.js.map +1 -1
- package/dist/interface/nodes.d.ts +9 -0
- package/dist/interface/nodes.js.map +1 -1
- package/dist/interface/result.js.map +1 -1
- package/dist/interface/sharing.d.ts +2 -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 +7 -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 +32 -32
- 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 +6 -6
- 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 +5 -7
- package/dist/internal/events/apiService.js +19 -22
- package/dist/internal/events/apiService.js.map +1 -1
- package/dist/internal/events/coreEventManager.d.ts +9 -12
- package/dist/internal/events/coreEventManager.js +19 -36
- package/dist/internal/events/coreEventManager.js.map +1 -1
- package/dist/internal/events/coreEventManager.test.d.ts +1 -0
- package/dist/internal/events/coreEventManager.test.js +87 -0
- package/dist/internal/events/coreEventManager.test.js.map +1 -0
- package/dist/internal/events/eventManager.d.ts +11 -36
- package/dist/internal/events/eventManager.js +59 -106
- package/dist/internal/events/eventManager.js.map +1 -1
- package/dist/internal/events/eventManager.test.js +177 -83
- package/dist/internal/events/eventManager.test.js.map +1 -1
- package/dist/internal/events/index.d.ts +16 -36
- package/dist/internal/events/index.js +56 -72
- package/dist/internal/events/index.js.map +1 -1
- package/dist/internal/events/interface.d.ts +59 -14
- package/dist/internal/events/interface.js +12 -3
- package/dist/internal/events/interface.js.map +1 -1
- package/dist/internal/events/volumeEventManager.d.ts +9 -19
- package/dist/internal/events/volumeEventManager.js +58 -45
- package/dist/internal/events/volumeEventManager.js.map +1 -1
- package/dist/internal/events/volumeEventManager.test.d.ts +1 -0
- package/dist/internal/events/volumeEventManager.test.js +203 -0
- package/dist/internal/events/volumeEventManager.test.js.map +1 -0
- 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 +14 -5
- package/dist/internal/nodes/cache.js +31 -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 +4 -4
- 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 +8 -84
- package/dist/internal/nodes/events.js +43 -217
- package/dist/internal/nodes/events.js.map +1 -1
- package/dist/internal/nodes/events.test.js +35 -279
- 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 +12 -13
- package/dist/internal/nodes/index.js +5 -5
- package/dist/internal/nodes/index.js.map +1 -1
- package/dist/internal/nodes/index.test.js +24 -32
- package/dist/internal/nodes/index.test.js.map +1 -1
- package/dist/internal/nodes/interface.d.ts +2 -2
- package/dist/internal/nodes/nodesAccess.d.ts +22 -7
- package/dist/internal/nodes/nodesAccess.js +65 -16
- package/dist/internal/nodes/nodesAccess.js.map +1 -1
- package/dist/internal/nodes/nodesAccess.test.js +165 -101
- package/dist/internal/nodes/nodesAccess.test.js.map +1 -1
- package/dist/internal/nodes/nodesManagement.d.ts +7 -9
- package/dist/internal/nodes/nodesManagement.js +21 -33
- package/dist/internal/nodes/nodesManagement.js.map +1 -1
- package/dist/internal/nodes/nodesManagement.test.js +42 -21
- 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 +4 -2
- package/dist/internal/shares/cache.js +14 -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 +8 -7
- package/dist/internal/shares/manager.js +3 -0
- 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 +5 -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 -4
- 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 +24 -56
- package/dist/internal/sharing/events.js +45 -138
- package/dist/internal/sharing/events.js.map +1 -1
- package/dist/internal/sharing/events.test.js +85 -189
- package/dist/internal/sharing/events.test.js.map +1 -1
- package/dist/internal/sharing/index.d.ts +8 -9
- package/dist/internal/sharing/index.js +5 -5
- package/dist/internal/sharing/index.js.map +1 -1
- package/dist/internal/sharing/interface.d.ts +8 -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 +5 -6
- package/dist/internal/sharing/sharingManagement.js +12 -16
- package/dist/internal/sharing/sharingManagement.js.map +1 -1
- package/dist/internal/sharing/sharingManagement.test.js +305 -286
- 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 +5 -6
- package/dist/internal/upload/apiService.js +8 -5
- 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 +6 -6
- package/dist/internal/upload/index.js +3 -3
- package/dist/internal/upload/index.js.map +1 -1
- package/dist/internal/upload/interface.d.ts +5 -3
- package/dist/internal/upload/manager.d.ts +8 -8
- package/dist/internal/upload/manager.js +23 -52
- package/dist/internal/upload/manager.js.map +1 -1
- package/dist/internal/upload/manager.test.js +185 -147
- 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 +9 -8
- package/dist/internal/upload/streamUploader.js.map +1 -1
- package/dist/internal/upload/streamUploader.test.js +17 -12
- 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 +27 -170
- package/dist/protonDriveClient.js +37 -198
- package/dist/protonDriveClient.js.map +1 -1
- package/dist/protonDrivePhotosClient.js +3 -2
- 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 +3 -3
- package/src/cache/index.ts +1 -0
- package/src/cache/interface.ts +22 -22
- package/src/cache/memoryCache.test.ts +7 -7
- package/src/cache/memoryCache.ts +5 -5
- package/src/cache/nullCache.ts +38 -0
- package/src/config.ts +17 -2
- 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 +76 -94
- package/src/crypto/utils.ts +1 -1
- package/src/diagnostic/eventsGenerator.ts +48 -0
- package/src/diagnostic/httpClient.ts +84 -0
- package/src/diagnostic/index.ts +40 -0
- package/src/diagnostic/integrityVerificationStream.ts +55 -0
- package/src/diagnostic/interface.ts +158 -0
- package/src/diagnostic/sdkDiagnostic.ts +249 -0
- package/src/diagnostic/sdkDiagnosticFull.ts +37 -0
- package/src/diagnostic/telemetry.ts +74 -0
- package/src/diagnostic/zipGenerators.test.ts +177 -0
- package/src/diagnostic/zipGenerators.ts +70 -0
- package/src/errors.ts +25 -22
- 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 +28 -0
- package/src/interface/devices.ts +6 -6
- package/src/interface/download.ts +12 -9
- package/src/interface/events.ts +76 -25
- package/src/interface/httpClient.ts +11 -27
- package/src/interface/index.ts +81 -20
- package/src/interface/nodes.ts +67 -60
- package/src/interface/result.ts +1 -3
- package/src/interface/sharing.ts +60 -56
- package/src/interface/telemetry.ts +74 -74
- package/src/interface/thumbnail.ts +5 -6
- package/src/interface/upload.ts +25 -11
- 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 +72 -52
- package/src/internal/download/cryptoService.ts +34 -18
- package/src/internal/download/fileDownloader.test.ts +25 -9
- package/src/internal/download/fileDownloader.ts +38 -20
- 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 +46 -36
- package/src/internal/events/coreEventManager.test.ts +101 -0
- package/src/internal/events/coreEventManager.ts +26 -48
- package/src/internal/events/eventManager.test.ts +211 -93
- package/src/internal/events/eventManager.ts +72 -117
- package/src/internal/events/index.ts +71 -91
- package/src/internal/events/interface.ts +92 -29
- package/src/internal/events/volumeEventManager.test.ts +239 -0
- package/src/internal/events/volumeEventManager.ts +68 -57
- 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 +79 -45
- 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 +171 -89
- package/src/internal/nodes/events.test.ts +48 -344
- package/src/internal/nodes/events.ts +48 -254
- package/src/internal/nodes/extendedAttributes.test.ts +28 -24
- package/src/internal/nodes/extendedAttributes.ts +20 -15
- package/src/internal/nodes/index.test.ts +51 -55
- package/src/internal/nodes/index.ts +32 -22
- package/src/internal/nodes/interface.ts +44 -31
- package/src/internal/nodes/nodesAccess.test.ts +237 -130
- package/src/internal/nodes/nodesAccess.ts +113 -50
- package/src/internal/nodes/nodesManagement.test.ts +64 -39
- package/src/internal/nodes/nodesManagement.ts +51 -62
- 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 +25 -14
- 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 +27 -23
- package/src/internal/sharing/apiService.ts +283 -175
- package/src/internal/sharing/cache.test.ts +35 -35
- package/src/internal/sharing/cache.ts +3 -3
- package/src/internal/sharing/cryptoService.test.ts +58 -46
- package/src/internal/sharing/cryptoService.ts +121 -83
- package/src/internal/sharing/events.test.ts +97 -207
- package/src/internal/sharing/events.ts +46 -157
- package/src/internal/sharing/index.ts +24 -16
- package/src/internal/sharing/interface.ts +46 -42
- package/src/internal/sharing/sharingAccess.test.ts +71 -65
- package/src/internal/sharing/sharingAccess.ts +39 -21
- package/src/internal/sharing/sharingManagement.test.ts +405 -335
- package/src/internal/sharing/sharingManagement.ts +144 -75
- package/src/internal/uids.ts +1 -1
- package/src/internal/upload/apiService.ts +168 -119
- 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 +17 -18
- package/src/internal/upload/interface.ts +79 -77
- package/src/internal/upload/manager.test.ts +222 -175
- package/src/internal/upload/manager.ts +74 -80
- package/src/internal/upload/queue.ts +3 -3
- package/src/internal/upload/streamUploader.test.ts +40 -27
- package/src/internal/upload/streamUploader.ts +87 -71
- 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 +189 -276
- package/src/protonDrivePhotosClient.ts +20 -13
- 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
- package/dist/internal/events/cache.d.ts +0 -28
- package/dist/internal/events/cache.js +0 -67
- package/dist/internal/events/cache.js.map +0 -1
- package/dist/internal/events/cache.test.js +0 -43
- package/dist/internal/events/cache.test.js.map +0 -1
- package/src/internal/events/cache.test.ts +0 -47
- package/src/internal/events/cache.ts +0 -80
- /package/dist/{internal/events/cache.test.d.ts → diagnostic/zipGenerators.test.d.ts} +0 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ProtonDriveHTTPClient,
|
|
3
|
+
ProtonDriveHTTPClientBlobOptions,
|
|
4
|
+
ProtonDriveHTTPClientJsonOptions,
|
|
5
|
+
} from '../interface';
|
|
6
|
+
import { EventsGenerator } from './eventsGenerator';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Special HTTP client that is compatible with the SDK.
|
|
10
|
+
*
|
|
11
|
+
* It is a probe into SDK to observe whats going on and report any suspicious
|
|
12
|
+
* behavior.
|
|
13
|
+
*
|
|
14
|
+
* It should be used only for diagnostic purposes.
|
|
15
|
+
*/
|
|
16
|
+
export class DiagnosticHTTPClient extends EventsGenerator implements ProtonDriveHTTPClient {
|
|
17
|
+
constructor(private httpClient: ProtonDriveHTTPClient) {
|
|
18
|
+
super();
|
|
19
|
+
this.httpClient = httpClient;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async fetchJson(options: ProtonDriveHTTPClientJsonOptions): Promise<Response> {
|
|
23
|
+
try {
|
|
24
|
+
const response = await this.httpClient.fetchJson(options);
|
|
25
|
+
|
|
26
|
+
if (response.status >= 400 && response.status !== 429) {
|
|
27
|
+
try {
|
|
28
|
+
const json = await response.json();
|
|
29
|
+
|
|
30
|
+
this.enqueueEvent({
|
|
31
|
+
type: 'http_error',
|
|
32
|
+
request: {
|
|
33
|
+
url: options.url,
|
|
34
|
+
method: options.method,
|
|
35
|
+
json: options.json,
|
|
36
|
+
},
|
|
37
|
+
response: {
|
|
38
|
+
status: response.status,
|
|
39
|
+
statusText: response.statusText,
|
|
40
|
+
json,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
return new Response(JSON.stringify(json), {
|
|
45
|
+
status: response.status,
|
|
46
|
+
statusText: response.statusText,
|
|
47
|
+
headers: response.headers,
|
|
48
|
+
});
|
|
49
|
+
} catch (jsonError: unknown) {
|
|
50
|
+
this.enqueueEvent({
|
|
51
|
+
type: 'http_error',
|
|
52
|
+
request: {
|
|
53
|
+
url: options.url,
|
|
54
|
+
method: options.method,
|
|
55
|
+
json: options.json,
|
|
56
|
+
},
|
|
57
|
+
response: {
|
|
58
|
+
status: response.status,
|
|
59
|
+
statusText: response.statusText,
|
|
60
|
+
jsonError,
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return response;
|
|
67
|
+
} catch (error: unknown) {
|
|
68
|
+
this.enqueueEvent({
|
|
69
|
+
type: 'http_error',
|
|
70
|
+
request: {
|
|
71
|
+
url: options.url,
|
|
72
|
+
method: options.method,
|
|
73
|
+
json: options.json,
|
|
74
|
+
},
|
|
75
|
+
error,
|
|
76
|
+
});
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
fetchBlob(options: ProtonDriveHTTPClientBlobOptions): Promise<Response> {
|
|
82
|
+
return this.httpClient.fetchBlob(options);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { MemoryCache, NullCache } from '../cache';
|
|
2
|
+
import { ProtonDriveClientContructorParameters } from '../interface';
|
|
3
|
+
import { ProtonDriveClient } from '../protonDriveClient';
|
|
4
|
+
import { DiagnosticHTTPClient } from './httpClient';
|
|
5
|
+
import { Diagnostic } from './interface';
|
|
6
|
+
import { SDKDiagnostic } from './sdkDiagnostic';
|
|
7
|
+
import { FullSDKDiagnostic } from './sdkDiagnosticFull';
|
|
8
|
+
import { DiagnosticTelemetry } from './telemetry';
|
|
9
|
+
|
|
10
|
+
export type { Diagnostic, DiagnosticResult } from './interface';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Initializes the diagnostic tool. It creates the instance of
|
|
14
|
+
* ProtonDriveClient with the special probes to observe the logs,
|
|
15
|
+
* metrics and HTTP calls; and enforced null/empty cache to always
|
|
16
|
+
* start from scratch.
|
|
17
|
+
*/
|
|
18
|
+
export function initDiagnostic(
|
|
19
|
+
options: Omit<ProtonDriveClientContructorParameters, 'entitiesCache' | 'cryptoCache' | 'telemetry'>,
|
|
20
|
+
): Diagnostic {
|
|
21
|
+
const httpClient = new DiagnosticHTTPClient(options.httpClient);
|
|
22
|
+
const telemetry = new DiagnosticTelemetry();
|
|
23
|
+
|
|
24
|
+
const protonDriveClient = new ProtonDriveClient({
|
|
25
|
+
...options,
|
|
26
|
+
httpClient,
|
|
27
|
+
// Ensure we always start with a clean state.
|
|
28
|
+
// Do not use memory cache as diagnostic should visit each node
|
|
29
|
+
// only once and we don't want to grow memory usage.
|
|
30
|
+
entitiesCache: new NullCache(),
|
|
31
|
+
// However, we need to use memory cache for crypto cache to avoid
|
|
32
|
+
// re-fetching the same key for all the children.
|
|
33
|
+
cryptoCache: new MemoryCache(),
|
|
34
|
+
// Special telemetry that observes the logs and metrics.
|
|
35
|
+
telemetry,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const diagnostic = new SDKDiagnostic(protonDriveClient);
|
|
39
|
+
return new FullSDKDiagnostic(diagnostic, telemetry, httpClient);
|
|
40
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { sha1 } from '@noble/hashes/legacy';
|
|
2
|
+
import { bytesToHex } from '@noble/hashes/utils';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A WritableStream that computes SHA1 hash on the fly.
|
|
6
|
+
* The computed SHA1 hash is available after the stream is closed.
|
|
7
|
+
*/
|
|
8
|
+
export class IntegrityVerificationStream extends WritableStream<Uint8Array> {
|
|
9
|
+
private sha1Hash = sha1.create();
|
|
10
|
+
private _computedSha1: string | undefined = undefined;
|
|
11
|
+
private _computedSizeInBytes: number = 0;
|
|
12
|
+
private _isClosed = false;
|
|
13
|
+
|
|
14
|
+
constructor() {
|
|
15
|
+
super({
|
|
16
|
+
start: () => {},
|
|
17
|
+
write: (chunk: Uint8Array) => {
|
|
18
|
+
if (this._isClosed) {
|
|
19
|
+
throw new Error('Cannot write to a closed stream');
|
|
20
|
+
}
|
|
21
|
+
this.sha1Hash.update(chunk);
|
|
22
|
+
this._computedSizeInBytes += chunk.length;
|
|
23
|
+
},
|
|
24
|
+
close: () => {
|
|
25
|
+
if (!this._isClosed) {
|
|
26
|
+
this._computedSha1 = bytesToHex(this.sha1Hash.digest());
|
|
27
|
+
this._isClosed = true;
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
abort: () => {
|
|
31
|
+
this._isClosed = true;
|
|
32
|
+
this._computedSha1 = undefined;
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Get the computed SHA1 hash. Only available after the stream is closed.
|
|
39
|
+
* @returns The SHA1 hash as a hex string, or null if not yet computed or stream was aborted
|
|
40
|
+
*/
|
|
41
|
+
get computedSha1(): string | undefined {
|
|
42
|
+
return this._computedSha1;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get the computed size in bytes. Only available after the stream is closed.
|
|
47
|
+
* @returns The size in bytes, or 0 if not yet computed or stream was aborted
|
|
48
|
+
*/
|
|
49
|
+
get computedSizeInBytes(): number | undefined {
|
|
50
|
+
if (!this._isClosed) {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
return this._computedSizeInBytes;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { DegradedNode, MaybeNode, MetricEvent } from '../interface';
|
|
2
|
+
import { LogRecord } from '../telemetry';
|
|
3
|
+
|
|
4
|
+
export interface Diagnostic {
|
|
5
|
+
verifyMyFiles(options?: DiagnosticOptions): AsyncGenerator<DiagnosticResult>;
|
|
6
|
+
verifyNodeTree(node: MaybeNode, options?: DiagnosticOptions): AsyncGenerator<DiagnosticResult>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type DiagnosticOptions = {
|
|
10
|
+
verifyContent?: boolean;
|
|
11
|
+
verifyThumbnails?: boolean;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type DiagnosticResult =
|
|
15
|
+
| FatalErrorResult
|
|
16
|
+
| SdkErrorResult
|
|
17
|
+
| HttpErrorResult
|
|
18
|
+
| DegradedNodeResult
|
|
19
|
+
| UnverifiedAuthorResult
|
|
20
|
+
| ExtendedAttributesErrorResult
|
|
21
|
+
| ExtendedAttributesMissingFieldResult
|
|
22
|
+
| ContentFileMissingRevisionResult
|
|
23
|
+
| ContentIntegrityErrorResult
|
|
24
|
+
| ContentDownloadErrorResult
|
|
25
|
+
| ThumbnailsErrorResult
|
|
26
|
+
| LogErrorResult
|
|
27
|
+
| LogWarningResult
|
|
28
|
+
| MetricResult;
|
|
29
|
+
|
|
30
|
+
// Event representing that fatal error occurred during the diagnostic.
|
|
31
|
+
// This error prevents the diagnostic to finish.
|
|
32
|
+
export type FatalErrorResult = {
|
|
33
|
+
type: 'fatal_error';
|
|
34
|
+
message: string;
|
|
35
|
+
error?: unknown;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// Event representing that SDK call failed.
|
|
39
|
+
// It can be any throwable error from any SDK call. Normally no error should be thrown.
|
|
40
|
+
export type SdkErrorResult = {
|
|
41
|
+
type: 'sdk_error';
|
|
42
|
+
call: string;
|
|
43
|
+
error?: unknown;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Event representing that HTTP call failed.
|
|
47
|
+
// It can be any call from the SDK, including validation error. Normally no error should be present.
|
|
48
|
+
export type HttpErrorResult = {
|
|
49
|
+
type: 'http_error';
|
|
50
|
+
request: {
|
|
51
|
+
url: string;
|
|
52
|
+
method: string;
|
|
53
|
+
json: unknown;
|
|
54
|
+
};
|
|
55
|
+
// Error if the whole call failed (`fetch` failed).
|
|
56
|
+
error?: unknown;
|
|
57
|
+
// Response if the response is not 2xx or 3xx.
|
|
58
|
+
response?: {
|
|
59
|
+
status: number;
|
|
60
|
+
statusText: string;
|
|
61
|
+
// Either json object or error if the response is not JSON.
|
|
62
|
+
json?: object;
|
|
63
|
+
jsonError?: unknown;
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// Event representing that node has some decryption or other (e.g., invalid name) issues.
|
|
68
|
+
export type DegradedNodeResult = {
|
|
69
|
+
type: 'degraded_node';
|
|
70
|
+
nodeUid: string;
|
|
71
|
+
node: DegradedNode;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// Event representing that signature verification failing.
|
|
75
|
+
export type UnverifiedAuthorResult = {
|
|
76
|
+
type: 'unverified_author';
|
|
77
|
+
nodeUid: string;
|
|
78
|
+
revisionUid?: string;
|
|
79
|
+
authorType: string;
|
|
80
|
+
claimedAuthor?: string;
|
|
81
|
+
error: string;
|
|
82
|
+
node: MaybeNode;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// Event representing that field from the extended attributes is not valid format.
|
|
86
|
+
// Currently only `sha1` verification is supported.
|
|
87
|
+
export type ExtendedAttributesErrorResult = {
|
|
88
|
+
type: 'extended_attributes_error';
|
|
89
|
+
nodeUid: string;
|
|
90
|
+
revisionUid?: string;
|
|
91
|
+
field: 'sha1';
|
|
92
|
+
value: string;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// Event representing that field from the extended attributes is missing.
|
|
96
|
+
// Currently only `sha1` verification is supported.
|
|
97
|
+
export type ExtendedAttributesMissingFieldResult = {
|
|
98
|
+
type: 'extended_attributes_missing_field';
|
|
99
|
+
nodeUid: string;
|
|
100
|
+
revisionUid?: string;
|
|
101
|
+
missingField: 'sha1';
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// Event representing that file is missing the active revision.
|
|
105
|
+
export type ContentFileMissingRevisionResult = {
|
|
106
|
+
type: 'content_file_missing_revision';
|
|
107
|
+
nodeUid: string;
|
|
108
|
+
revisionUid?: string;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// Event representing that file content is not valid - either sha1 or size is not correct.
|
|
112
|
+
export type ContentIntegrityErrorResult = {
|
|
113
|
+
type: 'content_integrity_error';
|
|
114
|
+
nodeUid: string;
|
|
115
|
+
revisionUid?: string;
|
|
116
|
+
claimedSha1?: string;
|
|
117
|
+
computedSha1?: string;
|
|
118
|
+
claimedSizeInBytes?: number;
|
|
119
|
+
computedSizeInBytes?: number;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// Event representing that downloading the file content failed.
|
|
123
|
+
// This can be connection issue or server error. If its integrity issue,
|
|
124
|
+
// it should be reported as `ContentIntegrityErrorResult`.
|
|
125
|
+
export type ContentDownloadErrorResult = {
|
|
126
|
+
type: 'content_download_error';
|
|
127
|
+
nodeUid: string;
|
|
128
|
+
revisionUid?: string;
|
|
129
|
+
error: unknown;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
// Event representing that getting the thumbnails failed.
|
|
133
|
+
// This can be connection issue or server error.
|
|
134
|
+
export type ThumbnailsErrorResult = {
|
|
135
|
+
type: 'thumbnails_error';
|
|
136
|
+
nodeUid: string;
|
|
137
|
+
revisionUid?: string;
|
|
138
|
+
message?: string;
|
|
139
|
+
error?: unknown;
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// Event representing errors logged during the diagnostic.
|
|
143
|
+
export type LogErrorResult = {
|
|
144
|
+
type: 'log_error';
|
|
145
|
+
log: LogRecord;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// Event representing warnings logged during the diagnostic.
|
|
149
|
+
export type LogWarningResult = {
|
|
150
|
+
type: 'log_warning';
|
|
151
|
+
log: LogRecord;
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
// Event representing metrics logged during the diagnostic.
|
|
155
|
+
export type MetricResult = {
|
|
156
|
+
type: 'metric';
|
|
157
|
+
event: MetricEvent;
|
|
158
|
+
};
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { Author, FileDownloader, MaybeNode, NodeType, Revision, ThumbnailType } from '../interface';
|
|
2
|
+
import { ProtonDriveClient } from '../protonDriveClient';
|
|
3
|
+
import { Diagnostic, DiagnosticOptions, DiagnosticResult } from './interface';
|
|
4
|
+
import { IntegrityVerificationStream } from './integrityVerificationStream';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Diagnostic tool that uses SDK to traverse the node tree and verify
|
|
8
|
+
* the integrity of the node tree.
|
|
9
|
+
*
|
|
10
|
+
* It produces only events that can be read by direct SDK invocation.
|
|
11
|
+
* To get the full diagnostic, use {@link FullSDKDiagnostic}.
|
|
12
|
+
*/
|
|
13
|
+
export class SDKDiagnostic implements Diagnostic {
|
|
14
|
+
constructor(private protonDriveClient: ProtonDriveClient) {
|
|
15
|
+
this.protonDriveClient = protonDriveClient;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async *verifyMyFiles(options?: DiagnosticOptions): AsyncGenerator<DiagnosticResult> {
|
|
19
|
+
let myFilesRootFolder: MaybeNode;
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
myFilesRootFolder = await this.protonDriveClient.getMyFilesRootFolder();
|
|
23
|
+
} catch (error: unknown) {
|
|
24
|
+
yield {
|
|
25
|
+
type: 'fatal_error',
|
|
26
|
+
message: `Error getting my files root folder`,
|
|
27
|
+
error,
|
|
28
|
+
};
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
yield* this.verifyNodeTree(myFilesRootFolder, options);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async *verifyNodeTree(node: MaybeNode, options?: DiagnosticOptions): AsyncGenerator<DiagnosticResult> {
|
|
36
|
+
const isFolder = getNodeType(node) === NodeType.Folder;
|
|
37
|
+
|
|
38
|
+
yield* this.verifyNode(node, options);
|
|
39
|
+
|
|
40
|
+
if (isFolder) {
|
|
41
|
+
yield* this.verifyNodeChildren(node, options);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private async *verifyNode(node: MaybeNode, options?: DiagnosticOptions): AsyncGenerator<DiagnosticResult> {
|
|
46
|
+
const nodeUid = node.ok ? node.value.uid : node.error.uid;
|
|
47
|
+
|
|
48
|
+
if (!node.ok) {
|
|
49
|
+
yield {
|
|
50
|
+
type: 'degraded_node',
|
|
51
|
+
nodeUid,
|
|
52
|
+
node: node.error,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const activeRevision = getActiveRevision(node);
|
|
57
|
+
const nodeInfo = {
|
|
58
|
+
...getNodeUids(node),
|
|
59
|
+
node,
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
yield* this.verifyAuthor(node.ok ? node.value.keyAuthor : node.error.keyAuthor, {
|
|
63
|
+
...nodeInfo,
|
|
64
|
+
authorType: 'key',
|
|
65
|
+
});
|
|
66
|
+
yield* this.verifyAuthor(node.ok ? node.value.nameAuthor : node.error.nameAuthor, {
|
|
67
|
+
...nodeInfo,
|
|
68
|
+
authorType: 'name',
|
|
69
|
+
});
|
|
70
|
+
if (activeRevision) {
|
|
71
|
+
yield* this.verifyAuthor(activeRevision.contentAuthor, { ...nodeInfo, authorType: 'content' });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
yield* this.verifyFileExtendedAttributes(node);
|
|
75
|
+
|
|
76
|
+
if (options?.verifyContent) {
|
|
77
|
+
yield* this.verifyContent(node);
|
|
78
|
+
}
|
|
79
|
+
if (options?.verifyThumbnails) {
|
|
80
|
+
yield* this.verifyThumbnails(node);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private async *verifyAuthor(
|
|
85
|
+
author: Author,
|
|
86
|
+
info: { nodeUid: string; authorType: string; revisionUid?: string; node: MaybeNode },
|
|
87
|
+
): AsyncGenerator<DiagnosticResult> {
|
|
88
|
+
if (!author.ok) {
|
|
89
|
+
yield {
|
|
90
|
+
type: 'unverified_author',
|
|
91
|
+
claimedAuthor: author.error.claimedAuthor,
|
|
92
|
+
error: author.error.error,
|
|
93
|
+
...info,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private async *verifyFileExtendedAttributes(node: MaybeNode): AsyncGenerator<DiagnosticResult> {
|
|
99
|
+
const activeRevision = getActiveRevision(node);
|
|
100
|
+
|
|
101
|
+
const expectedAttributes = getNodeType(node) === NodeType.File;
|
|
102
|
+
|
|
103
|
+
const claimedSha1 = activeRevision?.claimedDigests?.sha1;
|
|
104
|
+
if (claimedSha1 && !/^[0-9a-f]{40}$/i.test(claimedSha1)) {
|
|
105
|
+
yield {
|
|
106
|
+
type: 'extended_attributes_error',
|
|
107
|
+
...getNodeUids(node),
|
|
108
|
+
field: 'sha1',
|
|
109
|
+
value: claimedSha1,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (expectedAttributes && !claimedSha1) {
|
|
114
|
+
yield {
|
|
115
|
+
type: 'extended_attributes_missing_field',
|
|
116
|
+
...getNodeUids(node),
|
|
117
|
+
missingField: 'sha1',
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
private async *verifyContent(node: MaybeNode): AsyncGenerator<DiagnosticResult> {
|
|
123
|
+
if (getNodeType(node) !== NodeType.File) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const activeRevision = getActiveRevision(node);
|
|
127
|
+
if (!activeRevision) {
|
|
128
|
+
yield {
|
|
129
|
+
type: 'content_file_missing_revision',
|
|
130
|
+
nodeUid: node.ok ? node.value.uid : node.error.uid,
|
|
131
|
+
};
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
let downloader: FileDownloader;
|
|
136
|
+
try {
|
|
137
|
+
downloader = await this.protonDriveClient.getFileRevisionDownloader(activeRevision.uid);
|
|
138
|
+
} catch (error: unknown) {
|
|
139
|
+
yield {
|
|
140
|
+
type: 'sdk_error',
|
|
141
|
+
call: `getFileRevisionDownloader(${activeRevision.uid})`,
|
|
142
|
+
error,
|
|
143
|
+
};
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const claimedSha1 = activeRevision.claimedDigests?.sha1;
|
|
148
|
+
const claimedSizeInBytes = downloader.getClaimedSizeInBytes();
|
|
149
|
+
|
|
150
|
+
const integrityVerificationStream = new IntegrityVerificationStream();
|
|
151
|
+
const controller = downloader.writeToStream(integrityVerificationStream);
|
|
152
|
+
|
|
153
|
+
try {
|
|
154
|
+
await controller.completion();
|
|
155
|
+
|
|
156
|
+
const computedSha1 = integrityVerificationStream.computedSha1;
|
|
157
|
+
const computedSizeInBytes = integrityVerificationStream.computedSizeInBytes;
|
|
158
|
+
if (claimedSha1 !== computedSha1 || claimedSizeInBytes !== computedSizeInBytes) {
|
|
159
|
+
yield {
|
|
160
|
+
type: 'content_integrity_error',
|
|
161
|
+
...getNodeUids(node),
|
|
162
|
+
claimedSha1,
|
|
163
|
+
computedSha1,
|
|
164
|
+
claimedSizeInBytes,
|
|
165
|
+
computedSizeInBytes,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
} catch (error: unknown) {
|
|
169
|
+
yield {
|
|
170
|
+
type: 'content_download_error',
|
|
171
|
+
...getNodeUids(node),
|
|
172
|
+
error,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private async *verifyThumbnails(node: MaybeNode): AsyncGenerator<DiagnosticResult> {
|
|
178
|
+
if (getNodeType(node) !== NodeType.File) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const nodeUid = node.ok ? node.value.uid : node.error.uid;
|
|
183
|
+
|
|
184
|
+
try {
|
|
185
|
+
const result = await Array.fromAsync(
|
|
186
|
+
this.protonDriveClient.iterateThumbnails([nodeUid], ThumbnailType.Type1),
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
if (result.length === 0) {
|
|
190
|
+
yield {
|
|
191
|
+
type: 'sdk_error',
|
|
192
|
+
call: `iterateThumbnails(${nodeUid})`,
|
|
193
|
+
error: new Error('No thumbnails found'),
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
// TODO: We should have better way to check if the thumbnail is not expected.
|
|
197
|
+
if (!result[0].ok && result[0].error !== 'Node has no thumbnail') {
|
|
198
|
+
yield {
|
|
199
|
+
type: 'thumbnails_error',
|
|
200
|
+
nodeUid,
|
|
201
|
+
error: result[0].error,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
} catch (error: unknown) {
|
|
205
|
+
yield {
|
|
206
|
+
type: 'sdk_error',
|
|
207
|
+
call: `iterateThumbnails(${nodeUid})`,
|
|
208
|
+
error,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
private async *verifyNodeChildren(node: MaybeNode, options?: DiagnosticOptions): AsyncGenerator<DiagnosticResult> {
|
|
214
|
+
const nodeUid = node.ok ? node.value.uid : node.error.uid;
|
|
215
|
+
try {
|
|
216
|
+
for await (const child of this.protonDriveClient.iterateFolderChildren(node)) {
|
|
217
|
+
yield* this.verifyNodeTree(child, options);
|
|
218
|
+
}
|
|
219
|
+
} catch (error: unknown) {
|
|
220
|
+
yield {
|
|
221
|
+
type: 'sdk_error',
|
|
222
|
+
call: `iterateFolderChildren(${nodeUid})`,
|
|
223
|
+
error,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function getNodeUids(node: MaybeNode): { nodeUid: string; revisionUid?: string } {
|
|
230
|
+
const activeRevision = getActiveRevision(node);
|
|
231
|
+
return {
|
|
232
|
+
nodeUid: node.ok ? node.value.uid : node.error.uid,
|
|
233
|
+
revisionUid: activeRevision?.uid,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function getNodeType(node: MaybeNode): NodeType {
|
|
238
|
+
return node.ok ? node.value.type : node.error.type;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function getActiveRevision(node: MaybeNode): Revision | undefined {
|
|
242
|
+
if (node.ok) {
|
|
243
|
+
return node.value.activeRevision;
|
|
244
|
+
}
|
|
245
|
+
if (node.error.activeRevision?.ok) {
|
|
246
|
+
return node.error.activeRevision.value;
|
|
247
|
+
}
|
|
248
|
+
return undefined;
|
|
249
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { MaybeNode } from '../interface';
|
|
2
|
+
import { DiagnosticHTTPClient } from './httpClient';
|
|
3
|
+
import { Diagnostic, DiagnosticOptions, DiagnosticResult } from './interface';
|
|
4
|
+
import { DiagnosticTelemetry } from './telemetry';
|
|
5
|
+
import { zipGenerators } from './zipGenerators';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Diagnostic tool that produces full diagnostic, including logs and metrics
|
|
9
|
+
* by reading the events from the telemetry and HTTP client.
|
|
10
|
+
*/
|
|
11
|
+
export class FullSDKDiagnostic implements Diagnostic {
|
|
12
|
+
constructor(
|
|
13
|
+
private diagnostic: Diagnostic,
|
|
14
|
+
private telemetry: DiagnosticTelemetry,
|
|
15
|
+
private httpClient: DiagnosticHTTPClient,
|
|
16
|
+
) {
|
|
17
|
+
this.diagnostic = diagnostic;
|
|
18
|
+
this.telemetry = telemetry;
|
|
19
|
+
this.httpClient = httpClient;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async *verifyMyFiles(options?: DiagnosticOptions): AsyncGenerator<DiagnosticResult> {
|
|
23
|
+
yield* this.yieldEvents(this.diagnostic.verifyMyFiles(options));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async *verifyNodeTree(node: MaybeNode, options?: DiagnosticOptions): AsyncGenerator<DiagnosticResult> {
|
|
27
|
+
yield* this.yieldEvents(this.diagnostic.verifyNodeTree(node, options));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
private async *yieldEvents(generator: AsyncGenerator<DiagnosticResult>): AsyncGenerator<DiagnosticResult> {
|
|
31
|
+
yield* zipGenerators(generator, this.internalGenerator(), { stopOnFirstDone: true });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private async *internalGenerator(): AsyncGenerator<DiagnosticResult> {
|
|
35
|
+
yield* zipGenerators(this.telemetry.iterateEvents(), this.httpClient.iterateEvents());
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { MetricEvent } from '../interface';
|
|
2
|
+
import { LogRecord, LogLevel } from '../telemetry';
|
|
3
|
+
import { EventsGenerator } from './eventsGenerator';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Special telemetry that is compatible with the SDK.
|
|
7
|
+
*
|
|
8
|
+
* It is a probe into SDK to observe whats going on and report any suspicious
|
|
9
|
+
* behavior.
|
|
10
|
+
*
|
|
11
|
+
* It should be used only for diagnostic purposes.
|
|
12
|
+
*/
|
|
13
|
+
export class DiagnosticTelemetry extends EventsGenerator {
|
|
14
|
+
getLogger(name: string): Logger {
|
|
15
|
+
return new Logger(name, (log) => {
|
|
16
|
+
this.enqueueEvent({
|
|
17
|
+
type: log.level === LogLevel.ERROR ? 'log_error' : 'log_warning',
|
|
18
|
+
log,
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
logEvent(event: MetricEvent): void {
|
|
24
|
+
if (event.eventName === 'download' && !event.error) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (event.eventName === 'volumeEventsSubscriptionsChanged') {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
this.enqueueEvent({
|
|
32
|
+
type: 'metric',
|
|
33
|
+
event,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
class Logger {
|
|
39
|
+
constructor(
|
|
40
|
+
private name: string,
|
|
41
|
+
private callback?: (log: LogRecord) => void,
|
|
42
|
+
) {
|
|
43
|
+
this.name = name;
|
|
44
|
+
this.callback = callback;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Debug or info logs are excluded from the diagnostic.
|
|
48
|
+
// These logs should not include any suspicious behavior.
|
|
49
|
+
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
51
|
+
debug(message: string) {}
|
|
52
|
+
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
54
|
+
info(message: string) {}
|
|
55
|
+
|
|
56
|
+
warn(message: string) {
|
|
57
|
+
this.callback?.({
|
|
58
|
+
time: new Date(),
|
|
59
|
+
level: LogLevel.WARNING,
|
|
60
|
+
loggerName: this.name,
|
|
61
|
+
message,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
error(message: string, error?: unknown) {
|
|
66
|
+
this.callback?.({
|
|
67
|
+
time: new Date(),
|
|
68
|
+
level: LogLevel.ERROR,
|
|
69
|
+
loggerName: this.name,
|
|
70
|
+
message,
|
|
71
|
+
error,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|