@protontech/drive-sdk 0.0.12 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/nullCache.d.ts +14 -0
- package/dist/cache/nullCache.js +37 -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/openPGPCrypto.js +2 -0
- 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 +216 -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 +8 -3
- package/dist/errors.js +11 -4
- 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 +60 -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 +9 -5
- package/dist/interface/index.js +2 -1
- package/dist/interface/index.js.map +1 -1
- package/dist/interface/nodes.d.ts +21 -1
- package/dist/interface/nodes.js +11 -0
- package/dist/interface/nodes.js.map +1 -1
- package/dist/interface/sharing.d.ts +1 -0
- package/dist/interface/upload.d.ts +57 -3
- package/dist/internal/apiService/driveTypes.d.ts +1341 -465
- package/dist/internal/apiService/errors.js +2 -2
- package/dist/internal/apiService/errors.js.map +1 -1
- package/dist/internal/apiService/transformers.js +2 -0
- package/dist/internal/apiService/transformers.js.map +1 -1
- package/dist/internal/asyncIteratorMap.d.ts +15 -0
- package/dist/internal/asyncIteratorMap.js +59 -0
- package/dist/internal/asyncIteratorMap.js.map +1 -0
- package/dist/internal/asyncIteratorMap.test.js +120 -0
- package/dist/internal/asyncIteratorMap.test.js.map +1 -0
- package/dist/internal/download/apiService.js +32 -31
- package/dist/internal/download/apiService.js.map +1 -1
- package/dist/internal/download/fileDownloader.d.ts +2 -2
- package/dist/internal/download/fileDownloader.js.map +1 -1
- package/dist/internal/events/apiService.d.ts +4 -6
- package/dist/internal/events/apiService.js +15 -22
- package/dist/internal/events/apiService.js.map +1 -1
- package/dist/internal/events/coreEventManager.d.ts +7 -10
- 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 -105
- package/dist/internal/events/eventManager.js.map +1 -1
- package/dist/internal/events/eventManager.test.js +167 -82
- package/dist/internal/events/eventManager.test.js.map +1 -1
- package/dist/internal/events/index.d.ts +13 -33
- 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 +13 -3
- package/dist/internal/events/interface.js.map +1 -1
- package/dist/internal/events/volumeEventManager.d.ts +7 -17
- 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 +2 -2
- package/dist/internal/nodes/apiService.js +16 -6
- package/dist/internal/nodes/apiService.js.map +1 -1
- package/dist/internal/nodes/apiService.test.js +30 -8
- package/dist/internal/nodes/apiService.test.js.map +1 -1
- package/dist/internal/nodes/cache.d.ts +10 -1
- package/dist/internal/nodes/cache.js +18 -0
- package/dist/internal/nodes/cache.js.map +1 -1
- package/dist/internal/nodes/cache.test.js +1 -0
- package/dist/internal/nodes/cache.test.js.map +1 -1
- package/dist/internal/nodes/cryptoService.d.ts +1 -1
- package/dist/internal/nodes/cryptoService.js.map +1 -1
- package/dist/internal/nodes/cryptoService.test.js +34 -0
- package/dist/internal/nodes/cryptoService.test.js.map +1 -1
- package/dist/internal/nodes/events.d.ts +7 -83
- package/dist/internal/nodes/events.js +43 -217
- package/dist/internal/nodes/events.js.map +1 -1
- package/dist/internal/nodes/events.test.js +27 -277
- package/dist/internal/nodes/events.test.js.map +1 -1
- package/dist/internal/nodes/index.d.ts +3 -4
- package/dist/internal/nodes/index.js +5 -5
- package/dist/internal/nodes/index.js.map +1 -1
- package/dist/internal/nodes/interface.d.ts +3 -1
- package/dist/internal/nodes/nodesAccess.d.ts +15 -0
- package/dist/internal/nodes/nodesAccess.js +65 -7
- package/dist/internal/nodes/nodesAccess.js.map +1 -1
- package/dist/internal/nodes/nodesAccess.test.js +132 -93
- package/dist/internal/nodes/nodesAccess.test.js.map +1 -1
- package/dist/internal/nodes/nodesManagement.d.ts +1 -3
- package/dist/internal/nodes/nodesManagement.js +12 -26
- package/dist/internal/nodes/nodesManagement.js.map +1 -1
- package/dist/internal/nodes/nodesManagement.test.js +35 -14
- package/dist/internal/nodes/nodesManagement.test.js.map +1 -1
- package/dist/internal/shares/cache.d.ts +2 -0
- package/dist/internal/shares/cache.js +2 -0
- package/dist/internal/shares/cache.js.map +1 -1
- package/dist/internal/shares/manager.d.ts +1 -0
- package/dist/internal/shares/manager.js +3 -0
- package/dist/internal/shares/manager.js.map +1 -1
- package/dist/internal/sharing/apiService.js +20 -2
- package/dist/internal/sharing/apiService.js.map +1 -1
- package/dist/internal/sharing/cryptoService.js +1 -0
- package/dist/internal/sharing/cryptoService.js.map +1 -1
- package/dist/internal/sharing/events.d.ts +23 -55
- package/dist/internal/sharing/events.js +46 -138
- package/dist/internal/sharing/events.js.map +1 -1
- package/dist/internal/sharing/events.test.js +77 -180
- package/dist/internal/sharing/events.test.js.map +1 -1
- package/dist/internal/sharing/index.d.ts +4 -5
- package/dist/internal/sharing/index.js +5 -5
- package/dist/internal/sharing/index.js.map +1 -1
- package/dist/internal/sharing/interface.d.ts +3 -0
- package/dist/internal/sharing/sharingManagement.d.ts +2 -3
- package/dist/internal/sharing/sharingManagement.js +7 -9
- package/dist/internal/sharing/sharingManagement.js.map +1 -1
- package/dist/internal/sharing/sharingManagement.test.js +9 -39
- package/dist/internal/sharing/sharingManagement.test.js.map +1 -1
- package/dist/internal/upload/apiService.d.ts +2 -3
- package/dist/internal/upload/apiService.js +7 -4
- package/dist/internal/upload/apiService.js.map +1 -1
- package/dist/internal/upload/fileUploader.d.ts +49 -53
- package/dist/internal/upload/fileUploader.js +91 -395
- package/dist/internal/upload/fileUploader.js.map +1 -1
- package/dist/internal/upload/fileUploader.test.js +38 -292
- 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 +23 -44
- package/dist/internal/upload/index.js.map +1 -1
- package/dist/internal/upload/interface.d.ts +2 -0
- package/dist/internal/upload/manager.d.ts +6 -6
- package/dist/internal/upload/manager.js +32 -66
- package/dist/internal/upload/manager.js.map +1 -1
- package/dist/internal/upload/manager.test.js +100 -117
- package/dist/internal/upload/manager.test.js.map +1 -1
- package/dist/internal/upload/streamUploader.d.ts +62 -0
- package/dist/internal/upload/streamUploader.js +440 -0
- package/dist/internal/upload/streamUploader.js.map +1 -0
- package/dist/internal/upload/streamUploader.test.d.ts +1 -0
- package/dist/internal/upload/streamUploader.test.js +358 -0
- package/dist/internal/upload/streamUploader.test.js.map +1 -0
- package/dist/protonDriveClient.d.ts +22 -165
- package/dist/protonDriveClient.js +27 -191
- package/dist/protonDriveClient.js.map +1 -1
- package/dist/protonDrivePhotosClient.js +3 -2
- package/dist/protonDrivePhotosClient.js.map +1 -1
- package/package.json +4 -4
- package/src/cache/index.ts +1 -0
- package/src/cache/memoryCache.ts +1 -1
- package/src/cache/nullCache.ts +38 -0
- package/src/config.ts +17 -2
- package/src/crypto/openPGPCrypto.ts +2 -0
- package/src/diagnostic/eventsGenerator.ts +48 -0
- package/src/diagnostic/httpClient.ts +80 -0
- package/src/diagnostic/index.ts +38 -0
- package/src/diagnostic/integrityVerificationStream.ts +56 -0
- package/src/diagnostic/interface.ts +158 -0
- package/src/diagnostic/sdkDiagnostic.ts +238 -0
- package/src/diagnostic/sdkDiagnosticFull.ts +40 -0
- package/src/diagnostic/telemetry.ts +71 -0
- package/src/diagnostic/zipGenerators.test.ts +177 -0
- package/src/diagnostic/zipGenerators.ts +70 -0
- package/src/errors.ts +13 -4
- package/src/interface/config.ts +28 -0
- package/src/interface/download.ts +2 -2
- package/src/interface/events.ts +66 -21
- package/src/interface/httpClient.ts +0 -16
- package/src/interface/index.ts +9 -5
- package/src/interface/nodes.ts +32 -12
- package/src/interface/sharing.ts +1 -0
- package/src/interface/upload.ts +59 -3
- package/src/internal/apiService/driveTypes.ts +1341 -465
- package/src/internal/apiService/errors.ts +3 -2
- package/src/internal/apiService/transformers.ts +2 -0
- package/src/internal/asyncIteratorMap.test.ts +150 -0
- package/src/internal/asyncIteratorMap.ts +64 -0
- package/src/internal/download/apiService.ts +11 -8
- package/src/internal/download/fileDownloader.ts +2 -2
- package/src/internal/events/apiService.ts +25 -28
- package/src/internal/events/coreEventManager.test.ts +101 -0
- package/src/internal/events/coreEventManager.ts +20 -45
- package/src/internal/events/eventManager.test.ts +201 -88
- package/src/internal/events/eventManager.ts +69 -115
- package/src/internal/events/index.ts +54 -84
- package/src/internal/events/interface.ts +70 -15
- package/src/internal/events/volumeEventManager.test.ts +243 -0
- package/src/internal/events/volumeEventManager.ts +55 -53
- package/src/internal/nodes/apiService.test.ts +36 -7
- package/src/internal/nodes/apiService.ts +19 -7
- package/src/internal/nodes/cache.test.ts +1 -0
- package/src/internal/nodes/cache.ts +21 -2
- package/src/internal/nodes/cryptoService.test.ts +38 -0
- package/src/internal/nodes/cryptoService.ts +1 -1
- package/src/internal/nodes/events.test.ts +29 -335
- package/src/internal/nodes/events.ts +45 -253
- package/src/internal/nodes/index.ts +6 -8
- package/src/internal/nodes/interface.ts +6 -3
- package/src/internal/nodes/nodesAccess.test.ts +133 -91
- package/src/internal/nodes/nodesAccess.ts +70 -8
- package/src/internal/nodes/nodesManagement.test.ts +39 -15
- package/src/internal/nodes/nodesManagement.ts +12 -30
- package/src/internal/shares/cache.ts +4 -2
- package/src/internal/shares/manager.ts +9 -5
- package/src/internal/sharing/apiService.ts +25 -2
- package/src/internal/sharing/cache.ts +1 -1
- package/src/internal/sharing/cryptoService.ts +1 -0
- package/src/internal/sharing/events.test.ts +89 -195
- package/src/internal/sharing/events.ts +42 -156
- package/src/internal/sharing/index.ts +6 -9
- package/src/internal/sharing/interface.ts +6 -2
- package/src/internal/sharing/sharingManagement.test.ts +10 -40
- package/src/internal/sharing/sharingManagement.ts +7 -11
- package/src/internal/upload/apiService.ts +5 -6
- package/src/internal/upload/fileUploader.test.ts +46 -376
- package/src/internal/upload/fileUploader.ts +114 -494
- package/src/internal/upload/index.ts +30 -54
- package/src/internal/upload/interface.ts +2 -0
- package/src/internal/upload/manager.test.ts +107 -124
- package/src/internal/upload/manager.ts +48 -80
- package/src/internal/upload/streamUploader.test.ts +468 -0
- package/src/internal/upload/streamUploader.ts +550 -0
- package/src/protonDriveClient.ts +80 -248
- package/src/protonDrivePhotosClient.ts +4 -3
- 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/dist/internal/nodes/index.test.js +0 -112
- package/dist/internal/nodes/index.test.js.map +0 -1
- package/src/internal/events/cache.test.ts +0 -47
- package/src/internal/events/cache.ts +0 -80
- package/src/internal/nodes/index.test.ts +0 -135
- /package/dist/{internal/events/cache.test.d.ts → diagnostic/zipGenerators.test.d.ts} +0 -0
- /package/dist/internal/{nodes/index.test.d.ts → asyncIteratorMap.test.d.ts} +0 -0
|
@@ -3,16 +3,15 @@ import { DriveAPIService } from "../apiService";
|
|
|
3
3
|
import { DriveCrypto } from "../../crypto";
|
|
4
4
|
import { UploadAPIService } from "./apiService";
|
|
5
5
|
import { UploadCryptoService } from "./cryptoService";
|
|
6
|
+
import { FileUploader, FileRevisionUploader } from "./fileUploader";
|
|
7
|
+
import { NodesService, SharesService } from "./interface";
|
|
8
|
+
import { UploadManager } from "./manager";
|
|
6
9
|
import { UploadQueue } from "./queue";
|
|
7
|
-
import { NodesService, NodesEvents, SharesService } from "./interface";
|
|
8
|
-
import { Fileuploader } from "./fileUploader";
|
|
9
10
|
import { UploadTelemetry } from "./telemetry";
|
|
10
|
-
import { UploadManager } from "./manager";
|
|
11
|
-
import { BlockVerifier } from "./blockVerifier";
|
|
12
11
|
|
|
13
12
|
/**
|
|
14
13
|
* Provides facade for the upload module.
|
|
15
|
-
*
|
|
14
|
+
*
|
|
16
15
|
* The upload module is responsible for handling file uploads, including
|
|
17
16
|
* metadata generation, content upload, API communication, encryption,
|
|
18
17
|
* and verifications.
|
|
@@ -23,95 +22,72 @@ export function initUploadModule(
|
|
|
23
22
|
driveCrypto: DriveCrypto,
|
|
24
23
|
sharesService: SharesService,
|
|
25
24
|
nodesService: NodesService,
|
|
26
|
-
|
|
25
|
+
clientUid?: string,
|
|
27
26
|
) {
|
|
28
|
-
const api = new UploadAPIService(apiService);
|
|
27
|
+
const api = new UploadAPIService(apiService, clientUid);
|
|
29
28
|
const cryptoService = new UploadCryptoService(driveCrypto, nodesService);
|
|
30
29
|
|
|
31
30
|
const uploadTelemetry = new UploadTelemetry(telemetry, sharesService);
|
|
32
|
-
const manager = new UploadManager(telemetry, api, cryptoService, nodesService,
|
|
31
|
+
const manager = new UploadManager(telemetry, api, cryptoService, nodesService, clientUid);
|
|
33
32
|
|
|
34
33
|
const queue = new UploadQueue();
|
|
35
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Returns a FileUploader instance that can be used to upload a file to
|
|
37
|
+
* a parent folder.
|
|
38
|
+
*
|
|
39
|
+
* This operation does not call the API, it only returns a FileUploader
|
|
40
|
+
* instance when the upload queue has capacity.
|
|
41
|
+
*/
|
|
36
42
|
async function getFileUploader(
|
|
37
43
|
parentFolderUid: string,
|
|
38
44
|
name: string,
|
|
39
45
|
metadata: UploadMetadata,
|
|
40
46
|
signal?: AbortSignal,
|
|
41
|
-
): Promise<
|
|
47
|
+
): Promise<FileUploader> {
|
|
42
48
|
await queue.waitForCapacity(signal);
|
|
43
49
|
|
|
44
|
-
|
|
45
|
-
try {
|
|
46
|
-
revisionDraft = await manager.createDraftNode(parentFolderUid, name, metadata);
|
|
47
|
-
|
|
48
|
-
blockVerifier = new BlockVerifier(api, cryptoService, revisionDraft.nodeKeys.key, revisionDraft.nodeRevisionUid);
|
|
49
|
-
await blockVerifier.loadVerificationData();
|
|
50
|
-
} catch (error: unknown) {
|
|
51
|
-
queue.releaseCapacity();
|
|
52
|
-
if (revisionDraft) {
|
|
53
|
-
await manager.deleteDraftNode(revisionDraft.nodeUid);
|
|
54
|
-
}
|
|
55
|
-
void uploadTelemetry.uploadInitFailed(parentFolderUid, error, metadata.expectedSize);
|
|
56
|
-
throw error;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const onFinish = async (failure: boolean) => {
|
|
50
|
+
const onFinish = () => {
|
|
60
51
|
queue.releaseCapacity();
|
|
61
|
-
if (failure) {
|
|
62
|
-
await manager.deleteDraftNode(revisionDraft.nodeUid);
|
|
63
|
-
}
|
|
64
52
|
}
|
|
65
53
|
|
|
66
|
-
return new
|
|
54
|
+
return new FileUploader(
|
|
67
55
|
uploadTelemetry,
|
|
68
56
|
api,
|
|
69
57
|
cryptoService,
|
|
70
58
|
manager,
|
|
71
|
-
|
|
72
|
-
|
|
59
|
+
parentFolderUid,
|
|
60
|
+
name,
|
|
73
61
|
metadata,
|
|
74
62
|
onFinish,
|
|
75
63
|
signal,
|
|
76
64
|
);
|
|
77
65
|
}
|
|
78
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Returns a FileUploader instance that can be used to upload a new
|
|
69
|
+
* revision of a file.
|
|
70
|
+
*
|
|
71
|
+
* This operation does not call the API, it only returns a
|
|
72
|
+
* FileRevisionUploader instance when the upload queue has capacity.
|
|
73
|
+
*/
|
|
79
74
|
async function getFileRevisionUploader(
|
|
80
75
|
nodeUid: string,
|
|
81
76
|
metadata: UploadMetadata,
|
|
82
77
|
signal?: AbortSignal,
|
|
83
|
-
): Promise<
|
|
78
|
+
): Promise<FileRevisionUploader> {
|
|
84
79
|
await queue.waitForCapacity(signal);
|
|
85
80
|
|
|
86
|
-
|
|
87
|
-
try {
|
|
88
|
-
revisionDraft = await manager.createDraftRevision(nodeUid, metadata);
|
|
89
|
-
|
|
90
|
-
blockVerifier = new BlockVerifier(api, cryptoService, revisionDraft.nodeKeys.key, revisionDraft.nodeRevisionUid);
|
|
91
|
-
await blockVerifier.loadVerificationData();
|
|
92
|
-
} catch (error: unknown) {
|
|
93
|
-
queue.releaseCapacity();
|
|
94
|
-
if (revisionDraft) {
|
|
95
|
-
await manager.deleteDraftRevision(revisionDraft.nodeRevisionUid);
|
|
96
|
-
}
|
|
97
|
-
void uploadTelemetry.uploadInitFailed(nodeUid, error, metadata.expectedSize);
|
|
98
|
-
throw error;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const onFinish = async (failure: boolean) => {
|
|
81
|
+
const onFinish = () => {
|
|
102
82
|
queue.releaseCapacity();
|
|
103
|
-
if (failure) {
|
|
104
|
-
await manager.deleteDraftNode(revisionDraft.nodeUid);
|
|
105
|
-
}
|
|
106
83
|
}
|
|
107
84
|
|
|
108
|
-
return new
|
|
85
|
+
return new FileRevisionUploader(
|
|
109
86
|
uploadTelemetry,
|
|
110
87
|
api,
|
|
111
88
|
cryptoService,
|
|
112
89
|
manager,
|
|
113
|
-
|
|
114
|
-
revisionDraft,
|
|
90
|
+
nodeUid,
|
|
115
91
|
metadata,
|
|
116
92
|
onFinish,
|
|
117
93
|
signal,
|
|
@@ -105,6 +105,7 @@ export interface NodesService {
|
|
|
105
105
|
addressKey: PrivateKey,
|
|
106
106
|
addressKeyId: string,
|
|
107
107
|
}>,
|
|
108
|
+
notifyChildCreated(nodeUid: string): Promise<void>;
|
|
108
109
|
}
|
|
109
110
|
|
|
110
111
|
/**
|
|
@@ -117,6 +118,7 @@ export interface NodesEvents {
|
|
|
117
118
|
|
|
118
119
|
export interface NodesServiceNode {
|
|
119
120
|
uid: string,
|
|
121
|
+
parentUid?: string,
|
|
120
122
|
activeRevision?: Result<Revision, Error>,
|
|
121
123
|
}
|
|
122
124
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { ValidationError } from "../../errors";
|
|
2
|
-
import {
|
|
2
|
+
import { ProtonDriveTelemetry, UploadMetadata } from "../../interface";
|
|
3
3
|
import { getMockTelemetry } from "../../tests/telemetry";
|
|
4
4
|
import { ErrorCode } from "../apiService";
|
|
5
5
|
import { UploadAPIService } from "./apiService";
|
|
6
6
|
import { UploadCryptoService } from "./cryptoService";
|
|
7
|
-
import { NodesService
|
|
7
|
+
import { NodesService } from "./interface";
|
|
8
8
|
import { UploadManager } from './manager';
|
|
9
9
|
|
|
10
10
|
describe("UploadManager", () => {
|
|
@@ -12,10 +12,11 @@ describe("UploadManager", () => {
|
|
|
12
12
|
let apiService: UploadAPIService;
|
|
13
13
|
let cryptoService: UploadCryptoService;
|
|
14
14
|
let nodesService: NodesService;
|
|
15
|
-
let nodesEvents: NodesEvents;
|
|
16
15
|
|
|
17
16
|
let manager: UploadManager;
|
|
18
17
|
|
|
18
|
+
const clientUid = 'clientUid';
|
|
19
|
+
|
|
19
20
|
beforeEach(() => {
|
|
20
21
|
telemetry = getMockTelemetry();
|
|
21
22
|
// @ts-expect-error No need to implement all methods for mocking
|
|
@@ -73,8 +74,12 @@ describe("UploadManager", () => {
|
|
|
73
74
|
armoredExtendedAttributes: "newNode:armoredExtendedAttributes",
|
|
74
75
|
}),
|
|
75
76
|
}
|
|
76
|
-
// @ts-expect-error No need to implement all methods for mocking
|
|
77
77
|
nodesService = {
|
|
78
|
+
getNode: jest.fn(async (nodeUid: string) => ({
|
|
79
|
+
uid: nodeUid,
|
|
80
|
+
parentUid: 'parentUid',
|
|
81
|
+
|
|
82
|
+
})),
|
|
78
83
|
getNodeKeys: jest.fn().mockResolvedValue({
|
|
79
84
|
hashKey: 'parentNode:hashKey',
|
|
80
85
|
key: 'parentNode:nodekey',
|
|
@@ -83,13 +88,10 @@ describe("UploadManager", () => {
|
|
|
83
88
|
email: "signatureEmail",
|
|
84
89
|
addressId: "addressId",
|
|
85
90
|
}),
|
|
86
|
-
|
|
87
|
-
nodesEvents = {
|
|
88
|
-
nodeCreated: jest.fn(),
|
|
89
|
-
nodeUpdated: jest.fn(),
|
|
91
|
+
notifyChildCreated: jest.fn(async (nodeUid: string) => { return }),
|
|
90
92
|
}
|
|
91
93
|
|
|
92
|
-
manager = new UploadManager(telemetry, apiService, cryptoService, nodesService,
|
|
94
|
+
manager = new UploadManager(telemetry, apiService, cryptoService, nodesService, clientUid);
|
|
93
95
|
});
|
|
94
96
|
|
|
95
97
|
describe("createDraftNode", () => {
|
|
@@ -135,14 +137,18 @@ describe("UploadManager", () => {
|
|
|
135
137
|
armoredContentKeyPacketSignature: "newNode:armoredContentKeyPacketSignature",
|
|
136
138
|
signatureEmail: "signatureEmail",
|
|
137
139
|
});
|
|
138
|
-
expect(apiService.checkAvailableHashes).not.toHaveBeenCalled();
|
|
139
140
|
});
|
|
140
141
|
|
|
141
|
-
it("should
|
|
142
|
-
let
|
|
142
|
+
it("should delete existing draft and trying again", async () => {
|
|
143
|
+
let firstCall = true;
|
|
143
144
|
apiService.createDraft = jest.fn().mockImplementation(() => {
|
|
144
|
-
if (
|
|
145
|
-
|
|
145
|
+
if (firstCall) {
|
|
146
|
+
firstCall = false;
|
|
147
|
+
throw new ValidationError("Draft already exists", ErrorCode.ALREADY_EXISTS, {
|
|
148
|
+
ConflictLinkID: "existingLinkId",
|
|
149
|
+
ConflictDraftRevisionID: "existingDraftRevisionId",
|
|
150
|
+
ConflictDraftClientUID: clientUid,
|
|
151
|
+
});
|
|
146
152
|
}
|
|
147
153
|
return {
|
|
148
154
|
nodeUid: "newNode:nodeUid",
|
|
@@ -150,27 +156,8 @@ describe("UploadManager", () => {
|
|
|
150
156
|
};
|
|
151
157
|
});
|
|
152
158
|
|
|
153
|
-
|
|
154
|
-
if (!hashChecked) {
|
|
155
|
-
hashChecked = true;
|
|
156
|
-
return {
|
|
157
|
-
availalbleHashes: ["name1Hash"],
|
|
158
|
-
pendingHashes: [{
|
|
159
|
-
hash: "newNode:hash",
|
|
160
|
-
nodeUid: "nodeUidToDelete"
|
|
161
|
-
}],
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
return {
|
|
165
|
-
availalbleHashes: ["name1Hash"],
|
|
166
|
-
pendingHashes: [],
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
const result = await manager.createDraftNode("parentUid", "name", {} as UploadMetadata);
|
|
159
|
+
const result = await manager.createDraftNode("volumeId~parentUid", "name", {} as UploadMetadata);
|
|
171
160
|
|
|
172
|
-
expect(apiService.checkAvailableHashes).toHaveBeenCalledTimes(1);
|
|
173
|
-
expect(apiService.deleteDraft).toHaveBeenCalledTimes(1);
|
|
174
161
|
expect(result).toEqual({
|
|
175
162
|
nodeUid: "newNode:nodeUid",
|
|
176
163
|
nodeRevisionUid: "newNode:nodeRevisionUid",
|
|
@@ -182,60 +169,57 @@ describe("UploadManager", () => {
|
|
|
182
169
|
},
|
|
183
170
|
},
|
|
184
171
|
newNodeInfo: {
|
|
185
|
-
parentUid: "parentUid",
|
|
172
|
+
parentUid: "volumeId~parentUid",
|
|
186
173
|
name: "name",
|
|
187
174
|
encryptedName: "newNode:encryptedName",
|
|
188
175
|
hash: "newNode:hash",
|
|
189
176
|
},
|
|
190
177
|
});
|
|
191
|
-
expect(apiService.deleteDraft).
|
|
178
|
+
expect(apiService.deleteDraft).toHaveBeenCalledTimes(1);
|
|
179
|
+
expect(apiService.deleteDraft).toHaveBeenCalledWith("volumeId~existingLinkId");
|
|
192
180
|
});
|
|
193
181
|
|
|
194
|
-
it("should
|
|
195
|
-
let
|
|
182
|
+
it("should not delete existing draft if client UID does not match", async () => {
|
|
183
|
+
let firstCall = true;
|
|
196
184
|
apiService.createDraft = jest.fn().mockImplementation(() => {
|
|
197
|
-
if (
|
|
198
|
-
|
|
185
|
+
if (firstCall) {
|
|
186
|
+
firstCall = false;
|
|
187
|
+
throw new ValidationError("Draft already exists", ErrorCode.ALREADY_EXISTS, {
|
|
188
|
+
ConflictLinkID: "existingLinkId",
|
|
189
|
+
ConflictDraftRevisionID: "existingDraftRevisionId",
|
|
190
|
+
ConflictDraftClientUID: "anotherClientUid",
|
|
191
|
+
});
|
|
199
192
|
}
|
|
200
193
|
return {
|
|
201
194
|
nodeUid: "newNode:nodeUid",
|
|
202
195
|
nodeRevisionUid: "newNode:nodeRevisionUid",
|
|
203
196
|
};
|
|
204
197
|
});
|
|
205
|
-
apiService.deleteDraft = jest.fn().mockImplementation(() => {
|
|
206
|
-
throw new Error("Failed to delete draft");
|
|
207
|
-
});
|
|
208
198
|
|
|
209
|
-
|
|
210
|
-
if (!hashChecked) {
|
|
211
|
-
hashChecked = true;
|
|
212
|
-
return {
|
|
213
|
-
availalbleHashes: ["name1Hash"],
|
|
214
|
-
pendingHashes: [{
|
|
215
|
-
hash: "newNode:hash",
|
|
216
|
-
nodeUid: "nodeUidToDelete"
|
|
217
|
-
}],
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
return {
|
|
221
|
-
availalbleHashes: ["name1Hash"],
|
|
222
|
-
pendingHashes: [],
|
|
223
|
-
}
|
|
224
|
-
});
|
|
199
|
+
const promise = manager.createDraftNode("volumeId~parentUid", "name", {} as UploadMetadata);
|
|
225
200
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
201
|
+
try {
|
|
202
|
+
await promise;
|
|
203
|
+
} catch (error: any) {
|
|
204
|
+
expect(error.message).toBe("Draft already exists");
|
|
205
|
+
expect(error.ongoingUploadByOtherClient).toBe(true);
|
|
206
|
+
}
|
|
207
|
+
expect(apiService.deleteDraft).not.toHaveBeenCalled();
|
|
231
208
|
});
|
|
232
209
|
|
|
233
|
-
it("should
|
|
234
|
-
|
|
210
|
+
it("should not delete existing draft if client UID is not set", async () => {
|
|
211
|
+
const clientUid = undefined;
|
|
212
|
+
manager = new UploadManager(telemetry, apiService, cryptoService, nodesService, clientUid);
|
|
213
|
+
|
|
214
|
+
let firstCall = true;
|
|
235
215
|
apiService.createDraft = jest.fn().mockImplementation(() => {
|
|
236
|
-
if (
|
|
237
|
-
|
|
238
|
-
throw new ValidationError("Draft already exists", ErrorCode.ALREADY_EXISTS
|
|
216
|
+
if (firstCall) {
|
|
217
|
+
firstCall = false;
|
|
218
|
+
throw new ValidationError("Draft already exists", ErrorCode.ALREADY_EXISTS, {
|
|
219
|
+
ConflictLinkID: "existingLinkId",
|
|
220
|
+
ConflictDraftRevisionID: "existingDraftRevisionId",
|
|
221
|
+
ConflictDraftClientUID: clientUid,
|
|
222
|
+
});
|
|
239
223
|
}
|
|
240
224
|
return {
|
|
241
225
|
nodeUid: "newNode:nodeUid",
|
|
@@ -243,33 +227,69 @@ describe("UploadManager", () => {
|
|
|
243
227
|
};
|
|
244
228
|
});
|
|
245
229
|
|
|
246
|
-
const
|
|
247
|
-
|
|
248
|
-
await expect(result).rejects.toThrow("Draft already exists");
|
|
249
|
-
expect(apiService.checkAvailableHashes).toHaveBeenCalledTimes(1);
|
|
230
|
+
const promise = manager.createDraftNode("volumeId~parentUid", "name", {} as UploadMetadata);
|
|
250
231
|
|
|
251
232
|
try {
|
|
252
|
-
await
|
|
233
|
+
await promise;
|
|
253
234
|
} catch (error: any) {
|
|
254
|
-
expect(error.
|
|
235
|
+
expect(error.message).toBe("Draft already exists");
|
|
236
|
+
expect(error.ongoingUploadByOtherClient).toBe(true);
|
|
255
237
|
}
|
|
238
|
+
expect(apiService.deleteDraft).not.toHaveBeenCalled();
|
|
256
239
|
});
|
|
257
240
|
|
|
258
|
-
it("should handle
|
|
259
|
-
let
|
|
241
|
+
it("should handle error when deleting existing draft", async () => {
|
|
242
|
+
let firstCall = true;
|
|
260
243
|
apiService.createDraft = jest.fn().mockImplementation(() => {
|
|
261
|
-
if (
|
|
262
|
-
|
|
244
|
+
if (firstCall) {
|
|
245
|
+
firstCall = false;
|
|
246
|
+
throw new ValidationError("Draft already exists", ErrorCode.ALREADY_EXISTS, {
|
|
247
|
+
ConflictLinkID: "existingLinkId",
|
|
248
|
+
ConflictDraftRevisionID: "existingDraftRevisionId",
|
|
249
|
+
ConflictDraftClientUID: clientUid,
|
|
250
|
+
});
|
|
263
251
|
}
|
|
264
252
|
return {
|
|
265
253
|
nodeUid: "newNode:nodeUid",
|
|
266
254
|
nodeRevisionUid: "newNode:nodeRevisionUid",
|
|
267
255
|
};
|
|
268
256
|
});
|
|
257
|
+
apiService.deleteDraft = jest.fn().mockImplementation(() => {
|
|
258
|
+
throw new Error("Failed to delete draft");
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
const result = manager.createDraftNode("volumeId~parentUid", "name", {} as UploadMetadata);
|
|
269
262
|
|
|
263
|
+
try {
|
|
264
|
+
await result;
|
|
265
|
+
} catch (error: any) {
|
|
266
|
+
expect(error.message).toBe("Draft already exists");
|
|
267
|
+
expect(error.existingNodeUid).toBe("volumeId~existingLinkId");
|
|
268
|
+
}
|
|
269
|
+
expect(apiService.deleteDraft).toHaveBeenCalledTimes(1);
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
describe("findAvailableName", () => {
|
|
274
|
+
it("should find available name", async () => {
|
|
270
275
|
apiService.checkAvailableHashes = jest.fn().mockImplementation(() => {
|
|
271
|
-
|
|
272
|
-
|
|
276
|
+
return {
|
|
277
|
+
availalbleHashes: ["name3Hash"],
|
|
278
|
+
pendingHashes: [],
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
const result = await manager.findAvailableName("parentUid", "name");
|
|
283
|
+
expect(result).toBe("name3");
|
|
284
|
+
expect(apiService.checkAvailableHashes).toHaveBeenCalledTimes(1);
|
|
285
|
+
expect(apiService.checkAvailableHashes).toHaveBeenCalledWith("parentUid", ["name1Hash", "name2Hash", "name3Hash"]);
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it("should find available name with multiple pages", async () => {
|
|
289
|
+
let firstCall = false;
|
|
290
|
+
apiService.checkAvailableHashes = jest.fn().mockImplementation(() => {
|
|
291
|
+
if (!firstCall) {
|
|
292
|
+
firstCall = true;
|
|
273
293
|
return {
|
|
274
294
|
// First page has no available hashes
|
|
275
295
|
availalbleHashes: [],
|
|
@@ -282,16 +302,10 @@ describe("UploadManager", () => {
|
|
|
282
302
|
}
|
|
283
303
|
});
|
|
284
304
|
|
|
285
|
-
const result = manager.
|
|
286
|
-
|
|
287
|
-
await expect(result).rejects.toThrow("Draft already exists");
|
|
305
|
+
const result = await manager.findAvailableName("parentUid", "name");
|
|
306
|
+
expect(result).toBe("name3");
|
|
288
307
|
expect(apiService.checkAvailableHashes).toHaveBeenCalledTimes(2);
|
|
289
|
-
|
|
290
|
-
try {
|
|
291
|
-
await result;
|
|
292
|
-
} catch (error: any) {
|
|
293
|
-
expect(error.availableName).toBe("name3");
|
|
294
|
-
}
|
|
308
|
+
expect(apiService.checkAvailableHashes).toHaveBeenCalledWith("parentUid", ["name1Hash", "name2Hash", "name3Hash"]);
|
|
295
309
|
});
|
|
296
310
|
});
|
|
297
311
|
|
|
@@ -300,7 +314,7 @@ describe("UploadManager", () => {
|
|
|
300
314
|
nodeUid: "newNode:nodeUid",
|
|
301
315
|
nodeRevisionUid: "newNode:nodeRevisionUid",
|
|
302
316
|
nodeKeys: {
|
|
303
|
-
key: {_idx: 32321},
|
|
317
|
+
key: { _idx: 32321 },
|
|
304
318
|
contentKeyPacketSessionKey: "newNode:contentKeyPacketSessionKey",
|
|
305
319
|
signatureAddress: {
|
|
306
320
|
email: "signatureEmail",
|
|
@@ -327,29 +341,11 @@ describe("UploadManager", () => {
|
|
|
327
341
|
manifest,
|
|
328
342
|
metadata,
|
|
329
343
|
extendedAttributes,
|
|
330
|
-
1234567,
|
|
331
344
|
);
|
|
332
345
|
|
|
333
346
|
expect(cryptoService.commitFile).toHaveBeenCalledWith(nodeRevisionDraft.nodeKeys, manifest, expect.anything());
|
|
334
347
|
expect(apiService.commitDraftRevision).toHaveBeenCalledWith(nodeRevisionDraft.nodeRevisionUid, expect.anything());
|
|
335
|
-
expect(
|
|
336
|
-
uid: "newNode:nodeUid",
|
|
337
|
-
activeRevision: {
|
|
338
|
-
ok: true,
|
|
339
|
-
value: {
|
|
340
|
-
uid: "newNode:nodeRevisionUid",
|
|
341
|
-
state: RevisionState.Active,
|
|
342
|
-
creationTime: expect.any(Date),
|
|
343
|
-
contentAuthor: { ok: true, value: "signatureEmail" },
|
|
344
|
-
storageSize: 1234567,
|
|
345
|
-
claimedSize: 123456,
|
|
346
|
-
claimedModificationTime: extendedAttributes.modificationTime,
|
|
347
|
-
claimedDigests: {
|
|
348
|
-
sha1: "sha1",
|
|
349
|
-
},
|
|
350
|
-
},
|
|
351
|
-
},
|
|
352
|
-
});
|
|
348
|
+
expect(nodesService.notifyChildCreated).toHaveBeenCalledWith("parentUid");
|
|
353
349
|
})
|
|
354
350
|
|
|
355
351
|
it("should commit node draft", async () => {
|
|
@@ -367,24 +363,11 @@ describe("UploadManager", () => {
|
|
|
367
363
|
manifest,
|
|
368
364
|
metadata,
|
|
369
365
|
extendedAttributes,
|
|
370
|
-
1234567,
|
|
371
366
|
);
|
|
372
367
|
|
|
373
368
|
expect(cryptoService.commitFile).toHaveBeenCalledWith(nodeRevisionDraft.nodeKeys, manifest, expect.anything());
|
|
374
369
|
expect(apiService.commitDraftRevision).toHaveBeenCalledWith(nodeRevisionDraft.nodeRevisionUid, expect.anything());
|
|
375
|
-
expect(
|
|
376
|
-
uid: "newNode:nodeUid",
|
|
377
|
-
parentUid: "parentUid",
|
|
378
|
-
type: NodeType.File,
|
|
379
|
-
totalStorageSize: 1234567,
|
|
380
|
-
activeRevision: {
|
|
381
|
-
ok: true,
|
|
382
|
-
value: expect.objectContaining({
|
|
383
|
-
uid: "newNode:nodeRevisionUid",
|
|
384
|
-
storageSize: 1234567,
|
|
385
|
-
}),
|
|
386
|
-
},
|
|
387
|
-
}));
|
|
370
|
+
expect(nodesService.notifyChildCreated).toHaveBeenCalledWith("parentUid");
|
|
388
371
|
});
|
|
389
372
|
});
|
|
390
373
|
});
|