@protontech/drive-sdk 0.3.2 → 0.4.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/internal/apiService/errorCodes.d.ts +1 -0
- package/dist/internal/apiService/errors.d.ts +3 -0
- package/dist/internal/apiService/errors.js +7 -1
- package/dist/internal/apiService/errors.js.map +1 -1
- package/dist/internal/devices/interface.d.ts +1 -1
- package/dist/internal/devices/manager.js +1 -1
- package/dist/internal/devices/manager.js.map +1 -1
- package/dist/internal/devices/manager.test.js +3 -3
- package/dist/internal/devices/manager.test.js.map +1 -1
- package/dist/internal/events/apiService.js +1 -1
- package/dist/internal/events/apiService.js.map +1 -1
- package/dist/internal/events/coreEventManager.js +1 -1
- package/dist/internal/events/coreEventManager.js.map +1 -1
- package/dist/internal/events/coreEventManager.test.js +18 -24
- package/dist/internal/events/coreEventManager.test.js.map +1 -1
- package/dist/internal/events/index.d.ts +3 -4
- package/dist/internal/events/index.js +4 -4
- package/dist/internal/events/index.js.map +1 -1
- package/dist/internal/events/interface.d.ts +3 -0
- package/dist/internal/nodes/apiService.d.ts +12 -3
- package/dist/internal/nodes/apiService.js +53 -13
- package/dist/internal/nodes/apiService.js.map +1 -1
- package/dist/internal/nodes/apiService.test.js +19 -2
- package/dist/internal/nodes/apiService.test.js.map +1 -1
- package/dist/internal/nodes/cryptoService.d.ts +1 -1
- package/dist/internal/nodes/cryptoService.js +1 -1
- package/dist/internal/nodes/cryptoService.js.map +1 -1
- package/dist/internal/nodes/cryptoService.test.js +4 -4
- package/dist/internal/nodes/cryptoService.test.js.map +1 -1
- package/dist/internal/nodes/errors.d.ts +4 -0
- package/dist/internal/nodes/errors.js +9 -0
- package/dist/internal/nodes/errors.js.map +1 -0
- package/dist/internal/nodes/index.test.js +1 -1
- package/dist/internal/nodes/index.test.js.map +1 -1
- package/dist/internal/nodes/interface.d.ts +4 -1
- package/dist/internal/nodes/nodesAccess.d.ts +3 -3
- package/dist/internal/nodes/nodesAccess.js +25 -15
- package/dist/internal/nodes/nodesAccess.js.map +1 -1
- package/dist/internal/nodes/nodesAccess.test.js +48 -8
- package/dist/internal/nodes/nodesAccess.test.js.map +1 -1
- package/dist/internal/nodes/nodesManagement.d.ts +2 -0
- package/dist/internal/nodes/nodesManagement.js +86 -9
- package/dist/internal/nodes/nodesManagement.js.map +1 -1
- package/dist/internal/nodes/nodesManagement.test.js +81 -5
- package/dist/internal/nodes/nodesManagement.test.js.map +1 -1
- package/dist/internal/photos/albums.d.ts +9 -7
- package/dist/internal/photos/albums.js +26 -13
- package/dist/internal/photos/albums.js.map +1 -1
- package/dist/internal/photos/apiService.d.ts +34 -3
- package/dist/internal/photos/apiService.js +96 -3
- package/dist/internal/photos/apiService.js.map +1 -1
- package/dist/internal/photos/index.d.ts +20 -4
- package/dist/internal/photos/index.js +30 -7
- package/dist/internal/photos/index.js.map +1 -1
- package/dist/internal/photos/interface.d.ts +25 -1
- package/dist/internal/photos/shares.d.ts +43 -0
- package/dist/internal/photos/shares.js +112 -0
- package/dist/internal/photos/shares.js.map +1 -0
- package/dist/internal/photos/timeline.d.ts +15 -0
- package/dist/internal/photos/timeline.js +22 -0
- package/dist/internal/photos/timeline.js.map +1 -0
- package/dist/internal/shares/manager.d.ts +1 -1
- package/dist/internal/shares/manager.js +4 -4
- package/dist/internal/shares/manager.js.map +1 -1
- package/dist/internal/shares/manager.test.js +7 -7
- package/dist/internal/shares/manager.test.js.map +1 -1
- package/dist/internal/sharing/interface.d.ts +1 -1
- package/dist/internal/sharing/sharingAccess.js +1 -1
- package/dist/internal/sharing/sharingAccess.js.map +1 -1
- package/dist/internal/sharing/sharingAccess.test.js +1 -1
- package/dist/internal/sharing/sharingAccess.test.js.map +1 -1
- package/dist/protonDriveClient.d.ts +20 -3
- package/dist/protonDriveClient.js +23 -4
- package/dist/protonDriveClient.js.map +1 -1
- package/dist/protonDrivePhotosClient.d.ts +86 -12
- package/dist/protonDrivePhotosClient.js +132 -29
- package/dist/protonDrivePhotosClient.js.map +1 -1
- package/package.json +1 -1
- package/src/internal/apiService/errorCodes.ts +1 -0
- package/src/internal/apiService/errors.ts +6 -0
- package/src/internal/devices/interface.ts +1 -1
- package/src/internal/devices/manager.test.ts +3 -3
- package/src/internal/devices/manager.ts +1 -1
- package/src/internal/events/apiService.ts +1 -1
- package/src/internal/events/coreEventManager.test.ts +21 -27
- package/src/internal/events/coreEventManager.ts +1 -1
- package/src/internal/events/index.ts +3 -4
- package/src/internal/events/interface.ts +4 -0
- package/src/internal/nodes/apiService.test.ts +35 -1
- package/src/internal/nodes/apiService.ts +103 -17
- package/src/internal/nodes/cryptoService.test.ts +8 -8
- package/src/internal/nodes/cryptoService.ts +1 -1
- package/src/internal/nodes/errors.ts +5 -0
- package/src/internal/nodes/index.test.ts +1 -1
- package/src/internal/nodes/interface.ts +5 -1
- package/src/internal/nodes/nodesAccess.test.ts +68 -8
- package/src/internal/nodes/nodesAccess.ts +42 -15
- package/src/internal/nodes/nodesManagement.test.ts +100 -5
- package/src/internal/nodes/nodesManagement.ts +100 -13
- package/src/internal/photos/albums.ts +31 -12
- package/src/internal/photos/apiService.ts +159 -4
- package/src/internal/photos/index.ts +54 -9
- package/src/internal/photos/interface.ts +23 -1
- package/src/internal/photos/shares.ts +134 -0
- package/src/internal/photos/timeline.ts +24 -0
- package/src/internal/shares/manager.test.ts +7 -7
- package/src/internal/shares/manager.ts +4 -4
- package/src/internal/sharing/interface.ts +1 -1
- package/src/internal/sharing/sharingAccess.test.ts +1 -1
- package/src/internal/sharing/sharingAccess.ts +1 -1
- package/src/protonDriveClient.ts +33 -4
- package/src/protonDrivePhotosClient.ts +211 -32
- package/dist/internal/photos/cache.d.ts +0 -6
- package/dist/internal/photos/cache.js +0 -15
- package/dist/internal/photos/cache.js.map +0 -1
- package/dist/internal/photos/photosTimeline.d.ts +0 -10
- package/dist/internal/photos/photosTimeline.js +0 -19
- package/dist/internal/photos/photosTimeline.js.map +0 -1
- package/src/internal/photos/cache.ts +0 -11
- package/src/internal/photos/photosTimeline.ts +0 -17
|
@@ -1,16 +1,90 @@
|
|
|
1
|
-
import { ProtonDriveClientContructorParameters } from './interface';
|
|
1
|
+
import { ProtonDriveClientContructorParameters, NodeOrUid, MaybeMissingNode, UploadMetadata, FileDownloader, FileUploader, SDKEvent, MaybeNode } from './interface';
|
|
2
|
+
import { DriveListener, EventSubscription } from './internal/events';
|
|
3
|
+
/**
|
|
4
|
+
* ProtonDrivePhotosClient is the interface to access Photos functionality.
|
|
5
|
+
*
|
|
6
|
+
* The client provides high-level operations for managing photos, albums, sharing,
|
|
7
|
+
* and downloading/uploading photos.
|
|
8
|
+
*
|
|
9
|
+
* @deprecated This is an experimental feature that might change without a warning.
|
|
10
|
+
*/
|
|
2
11
|
export declare class ProtonDrivePhotosClient {
|
|
12
|
+
private logger;
|
|
13
|
+
private sdkEvents;
|
|
14
|
+
private events;
|
|
15
|
+
private photoShares;
|
|
3
16
|
private nodes;
|
|
17
|
+
private sharing;
|
|
18
|
+
private download;
|
|
19
|
+
private upload;
|
|
4
20
|
private photos;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
21
|
+
experimental: {
|
|
22
|
+
/**
|
|
23
|
+
* Experimental feature to return the URL of the node.
|
|
24
|
+
*
|
|
25
|
+
* See `ProtonDriveClient.experimental.getNodeUrl` for more information.
|
|
26
|
+
*/
|
|
27
|
+
getNodeUrl: (nodeUid: NodeOrUid) => Promise<string>;
|
|
28
|
+
};
|
|
29
|
+
constructor({ httpClient, entitiesCache, cryptoCache, account, openPGPCryptoModule, srpModule, config, telemetry, latestEventIdProvider, }: ProtonDriveClientContructorParameters);
|
|
30
|
+
/**
|
|
31
|
+
* Subscribes to the general SDK events.
|
|
32
|
+
*
|
|
33
|
+
* See `ProtonDriveClient.onMessage` for more information.
|
|
34
|
+
*/
|
|
35
|
+
onMessage(eventName: SDKEvent, callback: () => void): () => void;
|
|
36
|
+
/**
|
|
37
|
+
* Subscribes to the remote data updates for all files in a tree.
|
|
38
|
+
*
|
|
39
|
+
* See `ProtonDriveClient.subscribeToTreeEvents` for more information.
|
|
40
|
+
*/
|
|
41
|
+
subscribeToTreeEvents(treeEventScopeId: string, callback: DriveListener): Promise<EventSubscription>;
|
|
42
|
+
/**
|
|
43
|
+
* Subscribes to the remote general data updates.
|
|
44
|
+
*
|
|
45
|
+
* See `ProtonDriveClient.subscribeToDriveEvents` for more information.
|
|
46
|
+
*/
|
|
47
|
+
subscribeToDriveEvents(callback: DriveListener): Promise<EventSubscription>;
|
|
48
|
+
/**
|
|
49
|
+
* Iterates all the photos for the timeline view.
|
|
50
|
+
*
|
|
51
|
+
* The output includes only necessary information to quickly prepare
|
|
52
|
+
* the whole timeline view with the break-down per month/year and fast
|
|
53
|
+
* scrollbar.
|
|
54
|
+
*
|
|
55
|
+
* Individual photos details must be loaded separately based on what
|
|
56
|
+
* is visible in the UI.
|
|
57
|
+
*
|
|
58
|
+
* The output is sorted by the capture time, starting from the
|
|
59
|
+
* the most recent photos.
|
|
60
|
+
*/
|
|
61
|
+
iterateTimeline(signal?: AbortSignal): AsyncGenerator<{
|
|
62
|
+
nodeUid: string;
|
|
63
|
+
captureTime: Date;
|
|
64
|
+
tags: number[];
|
|
65
|
+
}>;
|
|
66
|
+
/**
|
|
67
|
+
* Iterates the nodes by their UIDs.
|
|
68
|
+
*
|
|
69
|
+
* See `ProtonDriveClient.iterateNodes` for more information.
|
|
70
|
+
*/
|
|
71
|
+
iterateNodes(nodeUids: NodeOrUid[], signal?: AbortSignal): AsyncGenerator<MaybeMissingNode>;
|
|
72
|
+
/**
|
|
73
|
+
* Iterates the albums.
|
|
74
|
+
*
|
|
75
|
+
* The output is not sorted and the order of the nodes is not guaranteed.
|
|
76
|
+
*/
|
|
77
|
+
iterateAlbums(signal?: AbortSignal): AsyncGenerator<MaybeNode>;
|
|
78
|
+
/**
|
|
79
|
+
* Get the file downloader to download the node content.
|
|
80
|
+
*
|
|
81
|
+
* See `ProtonDriveClient.getFileDownloader` for more information.
|
|
82
|
+
*/
|
|
83
|
+
getFileDownloader(nodeUid: NodeOrUid, signal?: AbortSignal): Promise<FileDownloader>;
|
|
84
|
+
/**
|
|
85
|
+
* Get the file uploader to upload a new file.
|
|
86
|
+
*
|
|
87
|
+
* See `ProtonDriveClient.getFileUploader` for more information.
|
|
88
|
+
*/
|
|
89
|
+
getFileUploader(name: string, metadata: UploadMetadata, signal?: AbortSignal): Promise<FileUploader>;
|
|
16
90
|
}
|
|
@@ -1,47 +1,150 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ProtonDrivePhotosClient = void 0;
|
|
4
|
-
const
|
|
4
|
+
const config_1 = require("./config");
|
|
5
5
|
const crypto_1 = require("./crypto");
|
|
6
|
-
const
|
|
6
|
+
const telemetry_1 = require("./telemetry");
|
|
7
|
+
const transformers_1 = require("./transformers");
|
|
8
|
+
const apiService_1 = require("./internal/apiService");
|
|
9
|
+
const download_1 = require("./internal/download");
|
|
10
|
+
const events_1 = require("./internal/events");
|
|
7
11
|
const nodes_1 = require("./internal/nodes");
|
|
8
12
|
const photos_1 = require("./internal/photos");
|
|
9
|
-
const events_1 = require("./internal/events");
|
|
10
13
|
const sdkEvents_1 = require("./internal/sdkEvents");
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
+
const shares_1 = require("./internal/shares");
|
|
15
|
+
const sharing_1 = require("./internal/sharing");
|
|
16
|
+
const upload_1 = require("./internal/upload");
|
|
17
|
+
/**
|
|
18
|
+
* ProtonDrivePhotosClient is the interface to access Photos functionality.
|
|
19
|
+
*
|
|
20
|
+
* The client provides high-level operations for managing photos, albums, sharing,
|
|
21
|
+
* and downloading/uploading photos.
|
|
22
|
+
*
|
|
23
|
+
* @deprecated This is an experimental feature that might change without a warning.
|
|
24
|
+
*/
|
|
14
25
|
class ProtonDrivePhotosClient {
|
|
26
|
+
logger;
|
|
27
|
+
sdkEvents;
|
|
28
|
+
events;
|
|
29
|
+
photoShares;
|
|
15
30
|
nodes;
|
|
31
|
+
sharing;
|
|
32
|
+
download;
|
|
33
|
+
upload;
|
|
16
34
|
photos;
|
|
17
|
-
|
|
35
|
+
experimental;
|
|
36
|
+
constructor({ httpClient, entitiesCache, cryptoCache, account, openPGPCryptoModule, srpModule, config, telemetry, latestEventIdProvider, }) {
|
|
18
37
|
if (!telemetry) {
|
|
19
38
|
telemetry = new telemetry_1.Telemetry();
|
|
20
39
|
}
|
|
40
|
+
this.logger = telemetry.getLogger('interface');
|
|
21
41
|
const fullConfig = (0, config_1.getConfig)(config);
|
|
22
|
-
|
|
42
|
+
this.sdkEvents = new sdkEvents_1.SDKEvents(telemetry);
|
|
23
43
|
const cryptoModule = new crypto_1.DriveCrypto(openPGPCryptoModule, srpModule);
|
|
24
|
-
const apiService = new apiService_1.DriveAPIService(telemetry, sdkEvents, httpClient, fullConfig.baseUrl, fullConfig.language);
|
|
25
|
-
const
|
|
26
|
-
this.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
this.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
const apiService = new apiService_1.DriveAPIService(telemetry, this.sdkEvents, httpClient, fullConfig.baseUrl, fullConfig.language);
|
|
45
|
+
const coreShares = (0, shares_1.initSharesModule)(telemetry, apiService, entitiesCache, cryptoCache, account, cryptoModule);
|
|
46
|
+
this.photoShares = (0, photos_1.initPhotoSharesModule)(telemetry, apiService, entitiesCache, cryptoCache, account, cryptoModule, coreShares);
|
|
47
|
+
this.nodes = (0, nodes_1.initNodesModule)(telemetry, apiService, entitiesCache, cryptoCache, account, cryptoModule, this.photoShares);
|
|
48
|
+
this.photos = (0, photos_1.initPhotosModule)(apiService, this.photoShares, this.nodes.access);
|
|
49
|
+
this.sharing = (0, sharing_1.initSharingModule)(telemetry, apiService, entitiesCache, account, cryptoModule, this.photoShares, this.nodes.access);
|
|
50
|
+
this.download = (0, download_1.initDownloadModule)(telemetry, apiService, cryptoModule, account, this.photoShares, this.nodes.access, this.nodes.revisions);
|
|
51
|
+
this.upload = (0, upload_1.initUploadModule)(telemetry, apiService, cryptoModule, this.photoShares, this.nodes.access, fullConfig.clientUid);
|
|
52
|
+
// These are used to keep the internal cache up to date
|
|
53
|
+
const cacheEventListeners = [
|
|
54
|
+
this.nodes.eventHandler.updateNodesCacheOnEvent.bind(this.nodes.eventHandler),
|
|
55
|
+
this.sharing.eventHandler.handleDriveEvent.bind(this.sharing.eventHandler),
|
|
56
|
+
];
|
|
57
|
+
this.events = new events_1.DriveEventsService(telemetry, apiService, this.photoShares, cacheEventListeners, latestEventIdProvider);
|
|
58
|
+
this.experimental = {
|
|
59
|
+
getNodeUrl: async (nodeUid) => {
|
|
60
|
+
this.logger.debug(`Getting node URL for ${(0, transformers_1.getUid)(nodeUid)}`);
|
|
61
|
+
return this.nodes.access.getNodeUrl((0, transformers_1.getUid)(nodeUid));
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Subscribes to the general SDK events.
|
|
67
|
+
*
|
|
68
|
+
* See `ProtonDriveClient.onMessage` for more information.
|
|
69
|
+
*/
|
|
70
|
+
onMessage(eventName, callback) {
|
|
71
|
+
this.logger.debug(`Subscribing to event ${eventName}`);
|
|
72
|
+
return this.sdkEvents.addListener(eventName, callback);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Subscribes to the remote data updates for all files in a tree.
|
|
76
|
+
*
|
|
77
|
+
* See `ProtonDriveClient.subscribeToTreeEvents` for more information.
|
|
78
|
+
*/
|
|
79
|
+
async subscribeToTreeEvents(treeEventScopeId, callback) {
|
|
80
|
+
this.logger.debug('Subscribing to node updates');
|
|
81
|
+
return this.events.subscribeToTreeEvents(treeEventScopeId, callback);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Subscribes to the remote general data updates.
|
|
85
|
+
*
|
|
86
|
+
* See `ProtonDriveClient.subscribeToDriveEvents` for more information.
|
|
87
|
+
*/
|
|
88
|
+
async subscribeToDriveEvents(callback) {
|
|
89
|
+
this.logger.debug('Subscribing to core updates');
|
|
90
|
+
return this.events.subscribeToCoreEvents(callback);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Iterates all the photos for the timeline view.
|
|
94
|
+
*
|
|
95
|
+
* The output includes only necessary information to quickly prepare
|
|
96
|
+
* the whole timeline view with the break-down per month/year and fast
|
|
97
|
+
* scrollbar.
|
|
98
|
+
*
|
|
99
|
+
* Individual photos details must be loaded separately based on what
|
|
100
|
+
* is visible in the UI.
|
|
101
|
+
*
|
|
102
|
+
* The output is sorted by the capture time, starting from the
|
|
103
|
+
* the most recent photos.
|
|
104
|
+
*/
|
|
105
|
+
async *iterateTimeline(signal) {
|
|
106
|
+
// TODO: expose better type
|
|
107
|
+
yield* this.photos.timeline.iterateTimeline(signal);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Iterates the nodes by their UIDs.
|
|
111
|
+
*
|
|
112
|
+
* See `ProtonDriveClient.iterateNodes` for more information.
|
|
113
|
+
*/
|
|
114
|
+
async *iterateNodes(nodeUids, signal) {
|
|
115
|
+
this.logger.info(`Iterating ${nodeUids.length} nodes`);
|
|
116
|
+
// TODO: expose photo type
|
|
117
|
+
yield* (0, transformers_1.convertInternalMissingNodeIterator)(this.nodes.access.iterateNodes((0, transformers_1.getUids)(nodeUids), signal));
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Iterates the albums.
|
|
121
|
+
*
|
|
122
|
+
* The output is not sorted and the order of the nodes is not guaranteed.
|
|
123
|
+
*/
|
|
124
|
+
async *iterateAlbums(signal) {
|
|
125
|
+
this.logger.info('Iterating albums');
|
|
126
|
+
// TODO: expose album type
|
|
127
|
+
yield* (0, transformers_1.convertInternalNodeIterator)(this.photos.albums.iterateAlbums(signal));
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Get the file downloader to download the node content.
|
|
131
|
+
*
|
|
132
|
+
* See `ProtonDriveClient.getFileDownloader` for more information.
|
|
133
|
+
*/
|
|
134
|
+
async getFileDownloader(nodeUid, signal) {
|
|
135
|
+
this.logger.info(`Getting file downloader for ${(0, transformers_1.getUid)(nodeUid)}`);
|
|
136
|
+
return this.download.getFileDownloader((0, transformers_1.getUid)(nodeUid), signal);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get the file uploader to upload a new file.
|
|
140
|
+
*
|
|
141
|
+
* See `ProtonDriveClient.getFileUploader` for more information.
|
|
142
|
+
*/
|
|
143
|
+
async getFileUploader(name, metadata, signal) {
|
|
144
|
+
this.logger.info(`Getting file uploader`);
|
|
145
|
+
const parentFolderUid = await this.nodes.access.getVolumeRootFolder();
|
|
146
|
+
return this.upload.getFileUploader((0, transformers_1.getUid)(parentFolderUid), name, metadata, signal);
|
|
147
|
+
}
|
|
45
148
|
}
|
|
46
149
|
exports.ProtonDrivePhotosClient = ProtonDrivePhotosClient;
|
|
47
150
|
//# sourceMappingURL=protonDrivePhotosClient.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protonDrivePhotosClient.js","sourceRoot":"","sources":["../src/protonDrivePhotosClient.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"protonDrivePhotosClient.js","sourceRoot":"","sources":["../src/protonDrivePhotosClient.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -57,6 +57,8 @@ export function apiErrorFactory({
|
|
|
57
57
|
// Here we convert only general enough codes. Specific cases that are
|
|
58
58
|
// not clear from the code itself must be handled by each module
|
|
59
59
|
// separately.
|
|
60
|
+
case ErrorCode.INVALID_REQUIREMENTS:
|
|
61
|
+
return new InvalidRequirementsAPIError(message, code, details);
|
|
60
62
|
case ErrorCode.INVALID_VALUE:
|
|
61
63
|
case ErrorCode.NOT_ENOUGH_PERMISSIONS:
|
|
62
64
|
case ErrorCode.NOT_ENOUGH_PERMISSIONS_TO_GRANT_PERMISSIONS:
|
|
@@ -108,3 +110,7 @@ export class APICodeError extends ServerError {
|
|
|
108
110
|
export class NotFoundAPIError extends ValidationError {
|
|
109
111
|
name = 'NotFoundAPIError';
|
|
110
112
|
}
|
|
113
|
+
|
|
114
|
+
export class InvalidRequirementsAPIError extends ValidationError {
|
|
115
|
+
name = 'InvalidRequirementsAPIError';
|
|
116
|
+
}
|
|
@@ -13,7 +13,7 @@ export type DeviceMetadata = {
|
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
export interface SharesService {
|
|
16
|
-
|
|
16
|
+
getOwnVolumeIDs(): Promise<{ volumeId: string }>;
|
|
17
17
|
getMyFilesShareMemberEmailKey(): Promise<{
|
|
18
18
|
addressId: string;
|
|
19
19
|
email: string;
|
|
@@ -30,7 +30,7 @@ describe('DevicesManager', () => {
|
|
|
30
30
|
};
|
|
31
31
|
// @ts-expect-error No need to implement all methods for mocking
|
|
32
32
|
sharesService = {
|
|
33
|
-
|
|
33
|
+
getOwnVolumeIDs: jest.fn(),
|
|
34
34
|
};
|
|
35
35
|
// @ts-expect-error No need to implement all methods for mocking
|
|
36
36
|
nodesService = {};
|
|
@@ -74,13 +74,13 @@ describe('DevicesManager', () => {
|
|
|
74
74
|
shareId: 'shareid',
|
|
75
75
|
} as DeviceMetadata;
|
|
76
76
|
|
|
77
|
-
sharesService.
|
|
77
|
+
sharesService.getOwnVolumeIDs.mockResolvedValue({ volumeId });
|
|
78
78
|
cryptoService.createDevice.mockResolvedValue({ address, shareKey, node });
|
|
79
79
|
apiService.createDevice.mockResolvedValue(createdDevice);
|
|
80
80
|
|
|
81
81
|
const result = await manager.createDevice(name, deviceType);
|
|
82
82
|
|
|
83
|
-
expect(sharesService.
|
|
83
|
+
expect(sharesService.getOwnVolumeIDs).toHaveBeenCalled();
|
|
84
84
|
expect(cryptoService.createDevice).toHaveBeenCalledWith(name);
|
|
85
85
|
expect(apiService.createDevice).toHaveBeenCalledWith(
|
|
86
86
|
{ volumeId, type: deviceType },
|
|
@@ -47,7 +47,7 @@ export class DevicesManager {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
async createDevice(name: string, deviceType: DeviceType): Promise<Device> {
|
|
50
|
-
const { volumeId } = await this.sharesService.
|
|
50
|
+
const { volumeId } = await this.sharesService.getOwnVolumeIDs();
|
|
51
51
|
const { address, shareKey, node } = await this.cryptoService.createDevice(name);
|
|
52
52
|
|
|
53
53
|
const device = await this.apiService.createDevice(
|
|
@@ -46,29 +46,6 @@ describe('CoreEventManager', () => {
|
|
|
46
46
|
const eventId = 'event1';
|
|
47
47
|
const latestEventId = 'event2';
|
|
48
48
|
|
|
49
|
-
it('should yield ShareWithMeUpdated event when refresh is true', async () => {
|
|
50
|
-
const mockEvents: DriveEventsListWithStatus = {
|
|
51
|
-
latestEventId,
|
|
52
|
-
more: false,
|
|
53
|
-
refresh: true,
|
|
54
|
-
events: [],
|
|
55
|
-
};
|
|
56
|
-
mockApiService.getCoreEvents.mockResolvedValue(mockEvents);
|
|
57
|
-
|
|
58
|
-
const events = [];
|
|
59
|
-
for await (const event of coreEventManager.getEvents(eventId)) {
|
|
60
|
-
events.push(event);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
expect(events).toHaveLength(1);
|
|
64
|
-
expect(events[0]).toEqual({
|
|
65
|
-
type: DriveEventType.SharedWithMeUpdated,
|
|
66
|
-
treeEventScopeId: 'core',
|
|
67
|
-
eventId: latestEventId,
|
|
68
|
-
});
|
|
69
|
-
expect(mockApiService.getCoreEvents).toHaveBeenCalledWith(eventId);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
49
|
it('should yield all events when there are actual events', async () => {
|
|
73
50
|
const mockEvent1: DriveEvent = {
|
|
74
51
|
type: DriveEventType.SharedWithMeUpdated,
|
|
@@ -88,14 +65,31 @@ describe('CoreEventManager', () => {
|
|
|
88
65
|
};
|
|
89
66
|
mockApiService.getCoreEvents.mockResolvedValue(mockEvents);
|
|
90
67
|
|
|
91
|
-
const events =
|
|
92
|
-
for await (const event of coreEventManager.getEvents(eventId)) {
|
|
93
|
-
events.push(event);
|
|
94
|
-
}
|
|
68
|
+
const events = await Array.fromAsync(coreEventManager.getEvents(eventId));
|
|
95
69
|
|
|
96
70
|
expect(events).toHaveLength(2);
|
|
97
71
|
expect(events[0]).toEqual(mockEvent1);
|
|
98
72
|
expect(events[1]).toEqual(mockEvent2);
|
|
99
73
|
});
|
|
74
|
+
|
|
75
|
+
it('should yield FastForward event there are no events but lastEventId changed', async () => {
|
|
76
|
+
const mockEvents: DriveEventsListWithStatus = {
|
|
77
|
+
latestEventId,
|
|
78
|
+
more: false,
|
|
79
|
+
refresh: false,
|
|
80
|
+
events: [],
|
|
81
|
+
};
|
|
82
|
+
mockApiService.getCoreEvents.mockResolvedValue(mockEvents);
|
|
83
|
+
|
|
84
|
+
const events = await Array.fromAsync(coreEventManager.getEvents(eventId));
|
|
85
|
+
|
|
86
|
+
expect(events).toHaveLength(1);
|
|
87
|
+
expect(events[0]).toEqual({
|
|
88
|
+
type: DriveEventType.FastForward,
|
|
89
|
+
treeEventScopeId: 'core',
|
|
90
|
+
eventId: latestEventId,
|
|
91
|
+
});
|
|
92
|
+
expect(mockApiService.getCoreEvents).toHaveBeenCalledWith(eventId);
|
|
93
|
+
});
|
|
100
94
|
});
|
|
101
95
|
});
|
|
@@ -32,7 +32,7 @@ export class CoreEventManager implements EventManagerInterface<DriveEvent> {
|
|
|
32
32
|
const events = await this.apiService.getCoreEvents(eventId);
|
|
33
33
|
if (events.events.length === 0 && events.latestEventId !== eventId) {
|
|
34
34
|
yield {
|
|
35
|
-
type: DriveEventType.
|
|
35
|
+
type: DriveEventType.FastForward,
|
|
36
36
|
treeEventScopeId: 'core',
|
|
37
37
|
eventId: events.latestEventId,
|
|
38
38
|
};
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { Logger, ProtonDriveTelemetry } from '../../interface';
|
|
2
2
|
import { DriveAPIService } from '../apiService';
|
|
3
|
-
import { DriveEvent, DriveListener, EventSubscription, LatestEventIdProvider } from './interface';
|
|
3
|
+
import { DriveEvent, DriveListener, EventSubscription, LatestEventIdProvider, SharesService } from './interface';
|
|
4
4
|
import { EventsAPIService } from './apiService';
|
|
5
5
|
import { CoreEventManager } from './coreEventManager';
|
|
6
6
|
import { VolumeEventManager } from './volumeEventManager';
|
|
7
7
|
import { EventManager } from './eventManager';
|
|
8
|
-
import { SharesManager } from '../shares/manager';
|
|
9
8
|
|
|
10
9
|
export type { DriveEvent, DriveListener, EventSubscription } from './interface';
|
|
11
10
|
export { DriveEventType } from './interface';
|
|
@@ -28,7 +27,7 @@ export class DriveEventsService {
|
|
|
28
27
|
constructor(
|
|
29
28
|
private telemetry: ProtonDriveTelemetry,
|
|
30
29
|
apiService: DriveAPIService,
|
|
31
|
-
private
|
|
30
|
+
private sharesService: SharesService,
|
|
32
31
|
private cacheEventListeners: DriveListener[] = [],
|
|
33
32
|
private latestEventIdProvider?: LatestEventIdProvider,
|
|
34
33
|
) {
|
|
@@ -104,7 +103,7 @@ export class DriveEventsService {
|
|
|
104
103
|
this.logger.debug(`Creating volume event manager for volume ${volumeId}`);
|
|
105
104
|
const volumeEventManager = new VolumeEventManager(this.logger, this.apiService, volumeId);
|
|
106
105
|
|
|
107
|
-
const isOwnVolume = await this.
|
|
106
|
+
const isOwnVolume = await this.sharesService.isOwnVolume(volumeId);
|
|
108
107
|
const pollingInterval = this.getDefaultVolumePollingInterval(isOwnVolume);
|
|
109
108
|
const latestEventId = this.latestEventIdProvider.getLatestEventId(volumeId);
|
|
110
109
|
const eventManager = new EventManager<DriveEvent>(volumeEventManager, pollingInterval, latestEventId);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { MemberRole, NodeType } from '../../interface';
|
|
2
2
|
import { getMockLogger } from '../../tests/logger';
|
|
3
|
-
import { DriveAPIService, ErrorCode } from '../apiService';
|
|
3
|
+
import { DriveAPIService, ErrorCode, InvalidRequirementsAPIError } from '../apiService';
|
|
4
4
|
import { NodeAPIService } from './apiService';
|
|
5
|
+
import { NodeOutOfSyncError } from './errors';
|
|
5
6
|
|
|
6
7
|
function generateAPIFileNode(linkOverrides = {}, overrides = {}) {
|
|
7
8
|
const node = generateAPINode();
|
|
@@ -542,4 +543,37 @@ describe('nodeAPIService', () => {
|
|
|
542
543
|
}
|
|
543
544
|
});
|
|
544
545
|
});
|
|
546
|
+
|
|
547
|
+
describe('renameNode', () => {
|
|
548
|
+
it('should rename node', async () => {
|
|
549
|
+
await api.renameNode(
|
|
550
|
+
'volumeId~nodeId1',
|
|
551
|
+
{ hash: 'originalHash' },
|
|
552
|
+
{ encryptedName: 'encryptedName1', nameSignatureEmail: 'nameSignatureEmail1', hash: 'newHash' },
|
|
553
|
+
);
|
|
554
|
+
|
|
555
|
+
expect(apiMock.put).toHaveBeenCalledWith(
|
|
556
|
+
'drive/v2/volumes/volumeId/links/nodeId1/rename',
|
|
557
|
+
{
|
|
558
|
+
Name: 'encryptedName1',
|
|
559
|
+
NameSignatureEmail: 'nameSignatureEmail1',
|
|
560
|
+
Hash: 'newHash',
|
|
561
|
+
OriginalHash: 'originalHash',
|
|
562
|
+
},
|
|
563
|
+
undefined,
|
|
564
|
+
);
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
it('should throw error if node is out of sync', async () => {
|
|
568
|
+
apiMock.put = jest.fn().mockRejectedValue(new InvalidRequirementsAPIError('Node is out of sync'));
|
|
569
|
+
|
|
570
|
+
await expect(
|
|
571
|
+
api.renameNode(
|
|
572
|
+
'volumeId~nodeId1',
|
|
573
|
+
{ hash: 'originalHash' },
|
|
574
|
+
{ encryptedName: 'encryptedName1', nameSignatureEmail: 'nameSignatureEmail1', hash: 'newHash' },
|
|
575
|
+
),
|
|
576
|
+
).rejects.toThrow(new NodeOutOfSyncError('Node is out of sync'));
|
|
577
|
+
});
|
|
578
|
+
});
|
|
545
579
|
});
|