@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
|
@@ -14,6 +14,7 @@ export function apiErrorFactory({ response, result }: { response: Response, resu
|
|
|
14
14
|
const typedResult = result as {
|
|
15
15
|
Code?: number;
|
|
16
16
|
Error?: string;
|
|
17
|
+
Details?: object;
|
|
17
18
|
exception?: string;
|
|
18
19
|
message?: string;
|
|
19
20
|
file?: string;
|
|
@@ -21,7 +22,7 @@ export function apiErrorFactory({ response, result }: { response: Response, resu
|
|
|
21
22
|
trace?: object;
|
|
22
23
|
};
|
|
23
24
|
|
|
24
|
-
const [code, message] = [typedResult.Code || 0, typedResult.Error || c('Error').t`Unknown error
|
|
25
|
+
const [code, message, details] = [typedResult.Code || 0, typedResult.Error || c('Error').t`Unknown error`, typedResult.Details];
|
|
25
26
|
|
|
26
27
|
const debug = typedResult.exception ? {
|
|
27
28
|
exception: typedResult.exception,
|
|
@@ -55,7 +56,7 @@ export function apiErrorFactory({ response, result }: { response: Response, resu
|
|
|
55
56
|
case ErrorCode.INSUFFICIENT_SHARE_QUOTA:
|
|
56
57
|
case ErrorCode.INSUFFICIENT_SHARE_JOINED_QUOTA:
|
|
57
58
|
case ErrorCode.INSUFFICIENT_BOOKMARKS_QUOTA:
|
|
58
|
-
return new ValidationError(message, code);
|
|
59
|
+
return new ValidationError(message, code, details);
|
|
59
60
|
default:
|
|
60
61
|
return new APICodeError(message, code, debug);
|
|
61
62
|
}
|
|
@@ -6,6 +6,8 @@ export function nodeTypeNumberToNodeType(logger: Logger, nodeTypeNumber: number)
|
|
|
6
6
|
return NodeType.Folder;
|
|
7
7
|
case 2:
|
|
8
8
|
return NodeType.File;
|
|
9
|
+
case 3:
|
|
10
|
+
return NodeType.Album;
|
|
9
11
|
default:
|
|
10
12
|
logger.warn(`Unknown node type: ${nodeTypeNumber}`);
|
|
11
13
|
return NodeType.File;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { asyncIteratorMap } from './asyncIteratorMap';
|
|
2
|
+
|
|
3
|
+
// Helper function to create an async generator from array
|
|
4
|
+
async function* createAsyncGenerator<T>(items: T[]): AsyncGenerator<T> {
|
|
5
|
+
for (const item of items) {
|
|
6
|
+
yield item;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Helper function to collect all results from async generator
|
|
11
|
+
async function collectResults<T>(asyncGen: AsyncGenerator<T>): Promise<T[]> {
|
|
12
|
+
const results: T[] = [];
|
|
13
|
+
for await (const item of asyncGen) {
|
|
14
|
+
results.push(item);
|
|
15
|
+
}
|
|
16
|
+
return results;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
describe('asyncIteratorMap', () => {
|
|
20
|
+
test('works with empty input', async () => {
|
|
21
|
+
const inputGen = createAsyncGenerator([]);
|
|
22
|
+
const mapper = async (x: number) => x * 2;
|
|
23
|
+
|
|
24
|
+
const mappedGen = asyncIteratorMap(inputGen, mapper);
|
|
25
|
+
const results = await collectResults(mappedGen);
|
|
26
|
+
|
|
27
|
+
expect(results).toEqual([]);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('works with single item', async () => {
|
|
31
|
+
const inputGen = createAsyncGenerator([42]);
|
|
32
|
+
const mapper = async (x: number) => x * 2;
|
|
33
|
+
|
|
34
|
+
const mappedGen = asyncIteratorMap(inputGen, mapper);
|
|
35
|
+
const results = await collectResults(mappedGen);
|
|
36
|
+
|
|
37
|
+
expect(results).toEqual([84]);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('works with 5 values', async () => {
|
|
41
|
+
const inputGen = createAsyncGenerator([1, 2, 3, 4, 5]);
|
|
42
|
+
const mapper = async (x: number) => x * 2;
|
|
43
|
+
|
|
44
|
+
const mappedGen = asyncIteratorMap(inputGen, mapper);
|
|
45
|
+
const results = await collectResults(mappedGen);
|
|
46
|
+
|
|
47
|
+
expect(results).toEqual([2, 4, 6, 8, 10]);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('works with slow mapper - finishes as fast as the longest delay', async () => {
|
|
51
|
+
const delays: { [key: number]: number } = { 1: 100, 2: 50, 3: 200, 4: 30, 5: 80 };
|
|
52
|
+
const inputGen = createAsyncGenerator(Object.keys(delays).map(Number));
|
|
53
|
+
|
|
54
|
+
const slowMapper = async (x: number) => {
|
|
55
|
+
await new Promise(resolve => setTimeout(resolve, delays[x]));
|
|
56
|
+
return x * 2;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const startTime = Date.now();
|
|
60
|
+
const mappedGen = asyncIteratorMap(inputGen, slowMapper, 5);
|
|
61
|
+
const results = await collectResults(mappedGen);
|
|
62
|
+
const endTime = Date.now();
|
|
63
|
+
|
|
64
|
+
// Should complete in roughly the time of the longest delay (200ms) plus some overhead
|
|
65
|
+
const executionTime = endTime - startTime;
|
|
66
|
+
expect(executionTime).toBeGreaterThanOrEqual(195); // We had failures with 199ms - JS is not precise.
|
|
67
|
+
expect(executionTime).toBeLessThan(250);
|
|
68
|
+
|
|
69
|
+
// Results should be in the order of the delays
|
|
70
|
+
expect(results).toEqual([8, 4, 10, 2, 6]);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test('handles errors from input iterator properly', async () => {
|
|
74
|
+
const throwingInputGen = async function*() {
|
|
75
|
+
yield 1;
|
|
76
|
+
yield 2;
|
|
77
|
+
throw new Error('Error providing value: 3');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const mapper = async (x: number) => x * 2;
|
|
81
|
+
|
|
82
|
+
const mappedGen = asyncIteratorMap(throwingInputGen(), mapper);
|
|
83
|
+
|
|
84
|
+
const results: number[] = [];
|
|
85
|
+
let caughtError: Error | null = null;
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
for await (const item of mappedGen) {
|
|
89
|
+
results.push(item);
|
|
90
|
+
}
|
|
91
|
+
} catch (error) {
|
|
92
|
+
caughtError = error as Error;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
expect(caughtError?.message).toBe('Error providing value: 3');
|
|
96
|
+
expect(results).toEqual([2, 4]);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test('handles errors from mapper properly', async () => {
|
|
100
|
+
const inputGen = createAsyncGenerator([1, 2, 3, 4, 5]);
|
|
101
|
+
|
|
102
|
+
const throwingMapper = async (x: number) => {
|
|
103
|
+
if (x === 3) {
|
|
104
|
+
throw new Error(`Error processing value: ${x}`);
|
|
105
|
+
}
|
|
106
|
+
return x * 2;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const mappedGen = asyncIteratorMap(inputGen, throwingMapper);
|
|
110
|
+
|
|
111
|
+
const results: number[] = [];
|
|
112
|
+
let caughtError: Error | null = null;
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
for await (const item of mappedGen) {
|
|
116
|
+
results.push(item);
|
|
117
|
+
}
|
|
118
|
+
} catch (error) {
|
|
119
|
+
caughtError = error as Error;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
expect(caughtError?.message).toBe('Error processing value: 3');
|
|
123
|
+
expect(results).toEqual([2, 4]);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test('respects concurrency limit', async () => {
|
|
127
|
+
const inputGen = createAsyncGenerator([1, 2, 3, 4, 5, 6, 7, 8]);
|
|
128
|
+
|
|
129
|
+
let concurrentExecutions = 0;
|
|
130
|
+
let maxConcurrentExecutions = 0;
|
|
131
|
+
|
|
132
|
+
const mapper = async (x: number) => {
|
|
133
|
+
concurrentExecutions++;
|
|
134
|
+
maxConcurrentExecutions = Math.max(maxConcurrentExecutions, concurrentExecutions);
|
|
135
|
+
|
|
136
|
+
// Wait for 100ms to simulate work
|
|
137
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
138
|
+
|
|
139
|
+
concurrentExecutions--;
|
|
140
|
+
return x * 2;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const concurrencyLimit = 3;
|
|
144
|
+
const mappedGen = asyncIteratorMap(inputGen, mapper, concurrencyLimit);
|
|
145
|
+
const results = await collectResults(mappedGen);
|
|
146
|
+
|
|
147
|
+
expect(maxConcurrentExecutions).toBe(concurrencyLimit);
|
|
148
|
+
expect(results).toEqual([2, 4, 6, 8, 10, 12, 14, 16]);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const DEFAULT_CONCURRENCY = 10;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Maps values from an input iterator and produces a new iterator.
|
|
5
|
+
* The mapper function is not awaited immediately to allow for parallel
|
|
6
|
+
* execution. The order of the items in the output iterator is not the
|
|
7
|
+
* same as the order of the items in the input iterator.
|
|
8
|
+
*
|
|
9
|
+
* Any error from the input iterator or the mapper function is propagated
|
|
10
|
+
* to the output iterator.
|
|
11
|
+
*
|
|
12
|
+
* @param inputIterator - The input async iterator.
|
|
13
|
+
* @param mapper - The mapper function that maps the input values to output values.
|
|
14
|
+
* @param concurrency - The concurrency limit. How many parallel async mapper calls are allowed.
|
|
15
|
+
* @returns An async iterator that yields the mapped values.
|
|
16
|
+
*/
|
|
17
|
+
export async function* asyncIteratorMap<I, O>(
|
|
18
|
+
inputIterator: AsyncGenerator<I>,
|
|
19
|
+
mapper: (item: I) => Promise<O>,
|
|
20
|
+
concurrency: number = DEFAULT_CONCURRENCY,
|
|
21
|
+
): AsyncGenerator<O> {
|
|
22
|
+
let done = false;
|
|
23
|
+
|
|
24
|
+
const executing = new Set<Promise<void>>();
|
|
25
|
+
const results: Array<Promise<O>> = [];
|
|
26
|
+
|
|
27
|
+
const pump = async () => {
|
|
28
|
+
let next;
|
|
29
|
+
try {
|
|
30
|
+
next = await inputIterator.next();
|
|
31
|
+
} catch (error) {
|
|
32
|
+
results.push(Promise.reject(error));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (next.done) {
|
|
37
|
+
done = true;
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const promise = mapper(next.value)
|
|
42
|
+
.then((result) => {
|
|
43
|
+
results.push(Promise.resolve(result));
|
|
44
|
+
})
|
|
45
|
+
.catch((error) => {
|
|
46
|
+
results.push(Promise.reject(error));
|
|
47
|
+
});
|
|
48
|
+
executing.add(promise);
|
|
49
|
+
void promise.finally(() => executing.delete(promise));
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
while (!done || executing.size > 0 || results.length > 0) {
|
|
53
|
+
while (!done && executing.size < concurrency) {
|
|
54
|
+
await pump();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (results.length > 0) {
|
|
58
|
+
yield await results.shift()!;
|
|
59
|
+
} else if (executing.size > 0) {
|
|
60
|
+
// Wait for at least one task to complete
|
|
61
|
+
await Promise.race(Array.from(executing));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { c } from "ttag";
|
|
2
|
-
import { ValidationError } from "../../errors";
|
|
3
1
|
import { DriveAPIService, drivePaths, ObserverStream } from "../apiService";
|
|
4
2
|
import { makeNodeThumbnailUid, splitNodeRevisionUid, splitNodeThumbnailUid } from "../uids";
|
|
5
3
|
import { BlockMetadata } from "./interface";
|
|
@@ -85,19 +83,22 @@ export class DownloadAPIService {
|
|
|
85
83
|
return encryptedBlock;
|
|
86
84
|
}
|
|
87
85
|
|
|
88
|
-
// Improvement requested: support multiple volumes.
|
|
89
86
|
async* iterateThumbnails(thumbnailUids: string[], signal?: AbortSignal): AsyncGenerator<
|
|
90
87
|
{ uid: string, ok: true, bareUrl: string, token: string } |
|
|
91
88
|
{ uid: string, ok: false, error: string }
|
|
92
89
|
> {
|
|
93
|
-
const
|
|
90
|
+
const splitedThumbnailsIds = thumbnailUids.map(splitNodeThumbnailUid);
|
|
94
91
|
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
92
|
+
const thumbnailIdsByVolumeId = new Map<string, { volumeId: string, thumbnailId: string, nodeId: string }[]>();
|
|
93
|
+
for (const { volumeId, thumbnailId, nodeId } of splitedThumbnailsIds) {
|
|
94
|
+
if (!thumbnailIdsByVolumeId.has(volumeId)) {
|
|
95
|
+
thumbnailIdsByVolumeId.set(volumeId, []);
|
|
96
|
+
}
|
|
97
|
+
thumbnailIdsByVolumeId.get(volumeId)?.push({ volumeId, thumbnailId, nodeId });
|
|
98
98
|
}
|
|
99
|
-
const volumeId = thumbnailIds[0].volumeId;
|
|
100
99
|
|
|
100
|
+
|
|
101
|
+
for (const [volumeId, thumbnailIds] of thumbnailIdsByVolumeId.entries()) {
|
|
101
102
|
const result = await this.apiService.post<PostGetThumbnailsRequest, PostGetThumbnailsResponse>(
|
|
102
103
|
`drive/volumes/${volumeId}/thumbnails`,
|
|
103
104
|
{
|
|
@@ -130,6 +131,8 @@ export class DownloadAPIService {
|
|
|
130
131
|
error: error.Error,
|
|
131
132
|
};
|
|
132
133
|
}
|
|
134
|
+
|
|
135
|
+
}
|
|
133
136
|
}
|
|
134
137
|
}
|
|
135
138
|
|
|
@@ -49,7 +49,7 @@ export class FileDownloader {
|
|
|
49
49
|
return this.revision.claimedSize;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
writeToStream(stream: WritableStream, onProgress
|
|
52
|
+
writeToStream(stream: WritableStream, onProgress?: (downloadedBytes: number) => void): DownloadController {
|
|
53
53
|
if (this.controller.promise) {
|
|
54
54
|
throw new Error(`Download already started`);
|
|
55
55
|
}
|
|
@@ -57,7 +57,7 @@ export class FileDownloader {
|
|
|
57
57
|
return this.controller;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
unsafeWriteToStream(stream: WritableStream, onProgress
|
|
60
|
+
unsafeWriteToStream(stream: WritableStream, onProgress?: (downloadedBytes: number) => void): DownloadController {
|
|
61
61
|
if (this.controller.promise) {
|
|
62
62
|
throw new Error(`Download already started`);
|
|
63
63
|
}
|
|
@@ -1,31 +1,32 @@
|
|
|
1
|
-
import { Logger } from "../../interface";
|
|
2
1
|
import { DriveAPIService, drivePaths, corePaths } from "../apiService";
|
|
3
2
|
import { makeNodeUid } from "../uids";
|
|
4
|
-
import {
|
|
3
|
+
import { DriveEventsListWithStatus, DriveEvent, DriveEventType, NodeEvent, NodeEventType } from "./interface";
|
|
5
4
|
|
|
6
5
|
type GetCoreLatestEventResponse = corePaths['/core/{_version}/events/latest']['get']['responses']['200']['content']['application/json'];
|
|
7
6
|
type GetCoreEventResponse = corePaths['/core/{_version}/events/{id}']['get']['responses']['200']['content']['application/json'];
|
|
8
7
|
|
|
9
8
|
type GetVolumeLatestEventResponse = drivePaths['/drive/volumes/{volumeID}/events/latest']['get']['responses']['200']['content']['application/json'];
|
|
10
|
-
type
|
|
9
|
+
type GetVolumeEventResponse = drivePaths['/drive/v2/volumes/{volumeID}/events/{eventID}']['get']['responses']['200']['content']['application/json'];
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
interface VolumeEventTypeMap {
|
|
12
|
+
[key: number]: NodeEventType,
|
|
13
|
+
}
|
|
14
|
+
const VOLUME_EVENT_TYPE_MAP: VolumeEventTypeMap = {
|
|
13
15
|
0: DriveEventType.NodeDeleted,
|
|
14
16
|
1: DriveEventType.NodeCreated,
|
|
15
17
|
2: DriveEventType.NodeUpdated,
|
|
16
|
-
3: DriveEventType.
|
|
18
|
+
3: DriveEventType.NodeUpdated,
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
/**
|
|
20
22
|
* Provides API communication for fetching events.
|
|
21
|
-
*
|
|
23
|
+
*
|
|
22
24
|
* The service is responsible for transforming local objects to API payloads
|
|
23
25
|
* and vice versa. It should not contain any business logic.
|
|
24
26
|
*/
|
|
25
27
|
export class EventsAPIService {
|
|
26
|
-
constructor(private apiService: DriveAPIService
|
|
28
|
+
constructor(private apiService: DriveAPIService) {
|
|
27
29
|
this.apiService = apiService;
|
|
28
|
-
this.logger = logger;
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
async getCoreLatestEventId(): Promise<string> {
|
|
@@ -33,17 +34,19 @@ export class EventsAPIService {
|
|
|
33
34
|
return result.EventID as string;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
async getCoreEvents(eventId: string): Promise<
|
|
37
|
-
// TODO: Switch to v6 endpoint
|
|
37
|
+
async getCoreEvents(eventId: string): Promise<DriveEventsListWithStatus> {
|
|
38
|
+
// TODO: Switch to v6 endpoint?
|
|
38
39
|
const result = await this.apiService.get<GetCoreEventResponse>(`core/v5/events/${eventId}`);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
// in core/v5/events, refresh is always all apps, value 255
|
|
41
|
+
const refresh = result.Refresh > 0;
|
|
42
|
+
const events: DriveEvent[] = (refresh || result.DriveShareRefresh?.Action === 2) ? [{
|
|
43
|
+
type: DriveEventType.SharedWithMeUpdated,
|
|
44
|
+
eventId: result.EventID,
|
|
45
|
+
treeEventScopeId: 'core',
|
|
46
|
+
}] : [];
|
|
44
47
|
|
|
45
48
|
return {
|
|
46
|
-
|
|
49
|
+
latestEventId: result.EventID,
|
|
47
50
|
more: result.More === 1,
|
|
48
51
|
refresh: result.Refresh === 1,
|
|
49
52
|
events,
|
|
@@ -55,31 +58,25 @@ export class EventsAPIService {
|
|
|
55
58
|
return result.EventID;
|
|
56
59
|
}
|
|
57
60
|
|
|
58
|
-
async getVolumeEvents(volumeId: string, eventId: string
|
|
59
|
-
const result = await this.apiService.get<
|
|
61
|
+
async getVolumeEvents(volumeId: string, eventId: string): Promise<DriveEventsListWithStatus> {
|
|
62
|
+
const result = await this.apiService.get<GetVolumeEventResponse>(`drive/v2/volumes/${volumeId}/events/${eventId}`);
|
|
60
63
|
return {
|
|
61
|
-
|
|
64
|
+
latestEventId: result.EventID,
|
|
62
65
|
more: result.More,
|
|
63
66
|
refresh: result.Refresh,
|
|
64
|
-
events: result.Events.map((event):
|
|
67
|
+
events: result.Events.map((event): NodeEvent => {
|
|
65
68
|
const type = VOLUME_EVENT_TYPE_MAP[event.EventType];
|
|
66
69
|
const uids = {
|
|
67
70
|
nodeUid: makeNodeUid(volumeId, event.Link.LinkID),
|
|
68
71
|
parentNodeUid: makeNodeUid(volumeId, event.Link.ParentLinkID as string),
|
|
69
72
|
}
|
|
70
|
-
// VOLUME_EVENT_TYPE_MAP will never return this event type.
|
|
71
|
-
// It is here to satisfy the type checker. It is safe to do.
|
|
72
|
-
if (type === DriveEventType.ShareWithMeUpdated) {
|
|
73
|
-
return {
|
|
74
|
-
type,
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
73
|
return {
|
|
78
74
|
type,
|
|
79
75
|
...uids,
|
|
80
76
|
isTrashed: event.Link.IsTrashed,
|
|
81
77
|
isShared: event.Link.IsShared,
|
|
82
|
-
|
|
78
|
+
eventId: event.EventID,
|
|
79
|
+
treeEventScopeId: volumeId,
|
|
83
80
|
};
|
|
84
81
|
}),
|
|
85
82
|
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { getMockLogger } from "../../tests/logger";
|
|
2
|
+
import { EventsAPIService } from "./apiService";
|
|
3
|
+
import { DriveEvent, DriveEventsListWithStatus, DriveEventType } from "./interface";
|
|
4
|
+
import { CoreEventManager } from "./coreEventManager";
|
|
5
|
+
|
|
6
|
+
describe("CoreEventManager", () => {
|
|
7
|
+
let mockApiService: jest.Mocked<EventsAPIService>;
|
|
8
|
+
let coreEventManager: CoreEventManager;
|
|
9
|
+
const mockLogger = getMockLogger();
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
// Reset mocks
|
|
13
|
+
jest.clearAllMocks();
|
|
14
|
+
|
|
15
|
+
mockApiService = {
|
|
16
|
+
getCoreLatestEventId: jest.fn(),
|
|
17
|
+
getCoreEvents: jest.fn(),
|
|
18
|
+
getVolumeLatestEventId: jest.fn(),
|
|
19
|
+
getVolumeEvents: jest.fn(),
|
|
20
|
+
} as unknown as jest.Mocked<EventsAPIService>;
|
|
21
|
+
|
|
22
|
+
coreEventManager = new CoreEventManager(mockLogger, mockApiService);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe("getLatestEventId", () => {
|
|
26
|
+
it("should return the latest event ID from API service", async () => {
|
|
27
|
+
const expectedEventId = "event-123";
|
|
28
|
+
mockApiService.getCoreLatestEventId.mockResolvedValue(expectedEventId);
|
|
29
|
+
|
|
30
|
+
const result = await coreEventManager.getLatestEventId();
|
|
31
|
+
|
|
32
|
+
expect(result).toBe(expectedEventId);
|
|
33
|
+
expect(mockApiService.getCoreLatestEventId).toHaveBeenCalledTimes(1);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("should handle API service errors", async () => {
|
|
37
|
+
const error = new Error("API error");
|
|
38
|
+
mockApiService.getCoreLatestEventId.mockRejectedValue(error);
|
|
39
|
+
|
|
40
|
+
await expect(coreEventManager.getLatestEventId()).rejects.toThrow("API error");
|
|
41
|
+
expect(mockApiService.getCoreLatestEventId).toHaveBeenCalledTimes(1);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe("getEvents", () => {
|
|
46
|
+
const eventId = "event1";
|
|
47
|
+
const latestEventId = "event2";
|
|
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
|
+
it("should yield all events when there are actual events", async () => {
|
|
73
|
+
const mockEvent1: DriveEvent = {
|
|
74
|
+
type: DriveEventType.SharedWithMeUpdated,
|
|
75
|
+
eventId: "event-1",
|
|
76
|
+
treeEventScopeId: 'core',
|
|
77
|
+
};
|
|
78
|
+
const mockEvent2: DriveEvent = {
|
|
79
|
+
type: DriveEventType.SharedWithMeUpdated,
|
|
80
|
+
eventId: "event-2",
|
|
81
|
+
treeEventScopeId: 'core',
|
|
82
|
+
};
|
|
83
|
+
const mockEvents: DriveEventsListWithStatus = {
|
|
84
|
+
latestEventId,
|
|
85
|
+
more: false,
|
|
86
|
+
refresh: false,
|
|
87
|
+
events: [mockEvent1, mockEvent2],
|
|
88
|
+
};
|
|
89
|
+
mockApiService.getCoreEvents.mockResolvedValue(mockEvents);
|
|
90
|
+
|
|
91
|
+
const events = [];
|
|
92
|
+
for await (const event of coreEventManager.getEvents(eventId)) {
|
|
93
|
+
events.push(event);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
expect(events).toHaveLength(2);
|
|
97
|
+
expect(events[0]).toEqual(mockEvent1);
|
|
98
|
+
expect(events[1]).toEqual(mockEvent2);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
});
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { Logger } from "../../interface";
|
|
2
2
|
import { LoggerWithPrefix } from "../../telemetry";
|
|
3
3
|
import { EventsAPIService } from "./apiService";
|
|
4
|
-
import {
|
|
5
|
-
import { DriveEvent, DriveEventType } from "./interface";
|
|
6
|
-
import { EventManager } from "./eventManager";
|
|
4
|
+
import { DriveEvent, DriveEventType, EventManagerInterface } from "./interface";
|
|
7
5
|
|
|
8
6
|
/**
|
|
9
7
|
* Combines API and event manager to provide a service for listening to
|
|
@@ -11,59 +9,36 @@ import { EventManager } from "./eventManager";
|
|
|
11
9
|
* At this moment, Drive listenes only to shares with me updates from core
|
|
12
10
|
* events. Such even indicates that user was invited to the new share or
|
|
13
11
|
* that user's membership was removed from existing one and lost access.
|
|
14
|
-
*
|
|
12
|
+
*
|
|
15
13
|
* The client might be already using own core events, thus this service
|
|
16
14
|
* is here only in case the client is not connected to the Proton services
|
|
17
15
|
* with own implementation.
|
|
18
16
|
*/
|
|
19
|
-
export class CoreEventManager {
|
|
20
|
-
private
|
|
21
|
-
|
|
22
|
-
constructor(logger: Logger, private apiService: EventsAPIService, private cache: EventsCache) {
|
|
17
|
+
export class CoreEventManager implements EventManagerInterface<DriveEvent> {
|
|
18
|
+
constructor(private logger: Logger, private apiService: EventsAPIService) {
|
|
23
19
|
this.apiService = apiService;
|
|
24
20
|
|
|
25
|
-
this.
|
|
26
|
-
new LoggerWithPrefix(logger, `core`),
|
|
27
|
-
() => this.getLastEventId(),
|
|
28
|
-
(eventId) => this.apiService.getCoreEvents(eventId),
|
|
29
|
-
(lastEventId) => this.cache.setLastEventId('core', {
|
|
30
|
-
lastEventId,
|
|
31
|
-
pollingIntervalInSeconds: this.manager.pollingIntervalInSeconds,
|
|
32
|
-
isOwnVolume: false,
|
|
33
|
-
}),
|
|
34
|
-
);
|
|
21
|
+
this.logger = new LoggerWithPrefix(logger, `core`);
|
|
35
22
|
}
|
|
36
23
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (lastEventId) {
|
|
40
|
-
return lastEventId;
|
|
41
|
-
}
|
|
42
|
-
return this.apiService.getCoreLatestEventId();
|
|
24
|
+
async getLatestEventId(): Promise<string> {
|
|
25
|
+
return await this.apiService.getCoreLatestEventId();
|
|
43
26
|
}
|
|
44
27
|
|
|
45
|
-
async
|
|
46
|
-
await this.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
28
|
+
async * getEvents(eventId: string): AsyncIterable<DriveEvent> {
|
|
29
|
+
const events = await this.apiService.getCoreEvents(eventId);
|
|
30
|
+
if (events.events.length === 0 && events.latestEventId !== eventId) {
|
|
31
|
+
yield {
|
|
32
|
+
type: DriveEventType.SharedWithMeUpdated,
|
|
33
|
+
treeEventScopeId: 'core',
|
|
34
|
+
eventId: events.latestEventId,
|
|
35
|
+
};
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
yield* events.events;
|
|
51
39
|
}
|
|
52
40
|
|
|
53
|
-
|
|
54
|
-
this.
|
|
55
|
-
if (events) {
|
|
56
|
-
await callback(events);
|
|
57
|
-
}
|
|
58
|
-
if (fullRefresh) {
|
|
59
|
-
// Because only updates about shares that are shared with me
|
|
60
|
-
// are listened to from core events, in the case of core full
|
|
61
|
-
// refresh, we don't have to refresh anything more than this
|
|
62
|
-
// one specific event.
|
|
63
|
-
await callback([{
|
|
64
|
-
type: DriveEventType.ShareWithMeUpdated,
|
|
65
|
-
}]);
|
|
66
|
-
}
|
|
67
|
-
});
|
|
41
|
+
getLogger(): Logger {
|
|
42
|
+
return this.logger;
|
|
68
43
|
}
|
|
69
44
|
}
|