@protontech/drive-sdk 0.9.8 → 0.10.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/crypto/driveCrypto.d.ts +15 -15
- package/dist/crypto/driveCrypto.js.map +1 -1
- package/dist/crypto/hmac.d.ts +3 -3
- package/dist/crypto/hmac.js.map +1 -1
- package/dist/crypto/interface.d.ts +45 -25
- package/dist/crypto/interface.js.map +1 -1
- package/dist/crypto/openPGPCrypto.d.ts +37 -37
- package/dist/crypto/openPGPCrypto.js.map +1 -1
- package/dist/crypto/utils.d.ts +1 -1
- package/dist/interface/index.d.ts +3 -3
- package/dist/interface/index.js.map +1 -1
- package/dist/interface/nodes.d.ts +8 -0
- package/dist/interface/photos.d.ts +18 -1
- package/dist/interface/sharing.d.ts +2 -0
- package/dist/interface/telemetry.d.ts +1 -0
- package/dist/interface/telemetry.js.map +1 -1
- package/dist/interface/thumbnail.d.ts +2 -2
- package/dist/internal/apiService/apiService.js +25 -12
- package/dist/internal/apiService/apiService.js.map +1 -1
- package/dist/internal/apiService/apiService.test.js +33 -5
- package/dist/internal/apiService/apiService.test.js.map +1 -1
- package/dist/internal/apiService/driveTypes.d.ts +2942 -3187
- package/dist/internal/apiService/errors.test.js +17 -7
- package/dist/internal/apiService/errors.test.js.map +1 -1
- package/dist/internal/devices/manager.d.ts +1 -0
- package/dist/internal/devices/manager.js +11 -0
- package/dist/internal/devices/manager.js.map +1 -1
- package/dist/internal/download/apiService.d.ts +1 -1
- package/dist/internal/download/cryptoService.d.ts +4 -4
- package/dist/internal/download/cryptoService.js.map +1 -1
- package/dist/internal/download/fileDownloader.js.map +1 -1
- package/dist/internal/download/fileDownloader.test.js.map +1 -1
- package/dist/internal/download/thumbnailDownloader.js.map +1 -1
- package/dist/internal/nodes/cryptoService.d.ts +4 -4
- package/dist/internal/nodes/cryptoService.js +5 -3
- package/dist/internal/nodes/cryptoService.js.map +1 -1
- package/dist/internal/nodes/cryptoService.test.js.map +1 -1
- package/dist/internal/nodes/interface.d.ts +1 -1
- package/dist/internal/nodes/nodesManagement.js +0 -1
- package/dist/internal/nodes/nodesManagement.js.map +1 -1
- package/dist/internal/photos/addToAlbum.d.ts +46 -0
- package/dist/internal/photos/addToAlbum.js +257 -0
- package/dist/internal/photos/addToAlbum.js.map +1 -0
- package/dist/internal/photos/addToAlbum.test.d.ts +1 -0
- package/dist/internal/photos/addToAlbum.test.js +409 -0
- package/dist/internal/photos/addToAlbum.test.js.map +1 -0
- package/dist/internal/photos/albums.d.ts +7 -2
- package/dist/internal/photos/albums.js +24 -1
- package/dist/internal/photos/albums.js.map +1 -1
- package/dist/internal/photos/albums.test.js +26 -1
- package/dist/internal/photos/albums.test.js.map +1 -1
- package/dist/internal/photos/albumsCrypto.d.ts +20 -3
- package/dist/internal/photos/albumsCrypto.js +27 -0
- package/dist/internal/photos/albumsCrypto.js.map +1 -1
- package/dist/internal/photos/apiService.d.ts +20 -0
- package/dist/internal/photos/apiService.js +142 -0
- package/dist/internal/photos/apiService.js.map +1 -1
- package/dist/internal/photos/apiService.test.d.ts +1 -0
- package/dist/internal/photos/apiService.test.js +199 -0
- package/dist/internal/photos/apiService.test.js.map +1 -0
- package/dist/internal/photos/errors.d.ts +4 -0
- package/dist/internal/photos/errors.js +17 -0
- package/dist/internal/photos/errors.js.map +1 -0
- package/dist/internal/photos/index.d.ts +1 -1
- package/dist/internal/photos/index.js +1 -1
- package/dist/internal/photos/index.js.map +1 -1
- package/dist/internal/photos/interface.d.ts +36 -1
- package/dist/internal/photos/interface.js +14 -0
- package/dist/internal/photos/interface.js.map +1 -1
- package/dist/internal/photos/nodes.js +32 -2
- package/dist/internal/photos/nodes.js.map +1 -1
- package/dist/internal/photos/nodes.test.js +25 -5
- package/dist/internal/photos/nodes.test.js.map +1 -1
- package/dist/internal/photos/timeline.d.ts +2 -5
- package/dist/internal/photos/timeline.js.map +1 -1
- package/dist/internal/photos/upload.d.ts +2 -2
- package/dist/internal/photos/upload.js.map +1 -1
- package/dist/internal/shares/apiService.js +1 -0
- package/dist/internal/shares/apiService.js.map +1 -1
- package/dist/internal/shares/interface.d.ts +1 -0
- package/dist/internal/sharing/apiService.d.ts +8 -1
- package/dist/internal/sharing/apiService.js +23 -1
- package/dist/internal/sharing/apiService.js.map +1 -1
- package/dist/internal/sharing/cryptoService.js +8 -4
- package/dist/internal/sharing/cryptoService.js.map +1 -1
- package/dist/internal/sharing/sharingManagement.d.ts +1 -0
- package/dist/internal/sharing/sharingManagement.js +15 -2
- package/dist/internal/sharing/sharingManagement.js.map +1 -1
- package/dist/internal/sharing/sharingManagement.test.js +30 -5
- package/dist/internal/sharing/sharingManagement.test.js.map +1 -1
- package/dist/internal/sharingPublic/nodes.d.ts +2 -2
- package/dist/internal/sharingPublic/nodes.js.map +1 -1
- package/dist/internal/upload/apiService.d.ts +5 -5
- package/dist/internal/upload/apiService.js.map +1 -1
- package/dist/internal/upload/blockVerifier.d.ts +2 -2
- package/dist/internal/upload/blockVerifier.js.map +1 -1
- package/dist/internal/upload/chunkStreamReader.d.ts +2 -2
- package/dist/internal/upload/chunkStreamReader.js.map +1 -1
- package/dist/internal/upload/chunkStreamReader.test.js.map +1 -1
- package/dist/internal/upload/cryptoService.d.ts +7 -7
- package/dist/internal/upload/cryptoService.js.map +1 -1
- package/dist/internal/upload/interface.d.ts +6 -6
- package/dist/internal/upload/manager.d.ts +1 -1
- package/dist/internal/upload/manager.js.map +1 -1
- package/dist/internal/upload/streamUploader.d.ts +1 -1
- package/dist/internal/utils.d.ts +1 -1
- package/dist/protonDriveClient.d.ts +8 -0
- package/dist/protonDriveClient.js +11 -0
- package/dist/protonDriveClient.js.map +1 -1
- package/dist/protonDrivePhotosClient.d.ts +42 -7
- package/dist/protonDrivePhotosClient.js +50 -2
- package/dist/protonDrivePhotosClient.js.map +1 -1
- package/dist/protonDrivePublicLinkClient.d.ts +9 -0
- package/dist/protonDrivePublicLinkClient.js +12 -0
- package/dist/protonDrivePublicLinkClient.js.map +1 -1
- package/dist/transformers.js +2 -0
- package/dist/transformers.js.map +1 -1
- package/package.json +4 -4
- package/src/crypto/driveCrypto.ts +15 -15
- package/src/crypto/hmac.ts +4 -4
- package/src/crypto/interface.ts +58 -27
- package/src/crypto/openPGPCrypto.ts +26 -26
- package/src/interface/index.ts +10 -2
- package/src/interface/nodes.ts +1 -0
- package/src/interface/photos.ts +19 -1
- package/src/interface/sharing.ts +2 -0
- package/src/interface/telemetry.ts +1 -0
- package/src/interface/thumbnail.ts +2 -2
- package/src/internal/apiService/apiService.test.ts +38 -6
- package/src/internal/apiService/apiService.ts +33 -12
- package/src/internal/apiService/driveTypes.ts +2942 -3187
- package/src/internal/devices/manager.ts +14 -0
- package/src/internal/download/apiService.ts +1 -1
- package/src/internal/download/cryptoService.ts +4 -4
- package/src/internal/download/fileDownloader.test.ts +4 -4
- package/src/internal/download/fileDownloader.ts +6 -6
- package/src/internal/download/thumbnailDownloader.ts +4 -4
- package/src/internal/nodes/cryptoService.test.ts +2 -2
- package/src/internal/nodes/cryptoService.ts +11 -8
- package/src/internal/nodes/interface.ts +1 -1
- package/src/internal/nodes/nodesManagement.ts +0 -1
- package/src/internal/photos/addToAlbum.test.ts +515 -0
- package/src/internal/photos/addToAlbum.ts +341 -0
- package/src/internal/photos/albums.test.ts +46 -22
- package/src/internal/photos/albums.ts +48 -2
- package/src/internal/photos/albumsCrypto.ts +54 -3
- package/src/internal/photos/apiService.test.ts +233 -0
- package/src/internal/photos/apiService.ts +234 -15
- package/src/internal/photos/errors.ts +11 -0
- package/src/internal/photos/index.ts +2 -2
- package/src/internal/photos/interface.ts +40 -1
- package/src/internal/photos/nodes.test.ts +27 -6
- package/src/internal/photos/nodes.ts +34 -2
- package/src/internal/photos/timeline.ts +2 -5
- package/src/internal/photos/upload.ts +2 -2
- package/src/internal/shares/apiService.ts +1 -0
- package/src/internal/shares/interface.ts +1 -0
- package/src/internal/sharing/apiService.ts +49 -5
- package/src/internal/sharing/cryptoService.ts +10 -4
- package/src/internal/sharing/sharingManagement.test.ts +33 -5
- package/src/internal/sharing/sharingManagement.ts +28 -6
- package/src/internal/sharingPublic/nodes.ts +1 -1
- package/src/internal/upload/apiService.ts +5 -5
- package/src/internal/upload/blockVerifier.ts +3 -3
- package/src/internal/upload/chunkStreamReader.test.ts +7 -7
- package/src/internal/upload/chunkStreamReader.ts +3 -3
- package/src/internal/upload/cryptoService.ts +9 -9
- package/src/internal/upload/interface.ts +6 -6
- package/src/internal/upload/manager.ts +2 -2
- package/src/internal/upload/streamUploader.ts +1 -1
- package/src/protonDriveClient.ts +15 -3
- package/src/protonDrivePhotosClient.ts +78 -22
- package/src/protonDrivePublicLinkClient.ts +13 -0
- package/src/transformers.ts +2 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { ChunkStreamReader } from './chunkStreamReader';
|
|
2
2
|
|
|
3
3
|
describe('ChunkStreamReader', () => {
|
|
4
|
-
let stream: ReadableStream<Uint8Array
|
|
4
|
+
let stream: ReadableStream<Uint8Array<ArrayBuffer>>;
|
|
5
5
|
|
|
6
6
|
beforeEach(() => {
|
|
7
|
-
stream = new ReadableStream<Uint8Array
|
|
7
|
+
stream = new ReadableStream<Uint8Array<ArrayBuffer>>({
|
|
8
8
|
start(controller) {
|
|
9
9
|
controller.enqueue(new Uint8Array([1, 2, 3]));
|
|
10
10
|
controller.enqueue(new Uint8Array([4, 5, 6]));
|
|
@@ -18,7 +18,7 @@ describe('ChunkStreamReader', () => {
|
|
|
18
18
|
it('should yield chunks as enqueued if matching the size', async () => {
|
|
19
19
|
const reader = new ChunkStreamReader(stream, 3);
|
|
20
20
|
|
|
21
|
-
const chunks: Uint8Array[] = [];
|
|
21
|
+
const chunks: Uint8Array<ArrayBuffer>[] = [];
|
|
22
22
|
for await (const chunk of reader.iterateChunks()) {
|
|
23
23
|
chunks.push(new Uint8Array(chunk));
|
|
24
24
|
}
|
|
@@ -33,7 +33,7 @@ describe('ChunkStreamReader', () => {
|
|
|
33
33
|
it('should yield smaller chunks than enqueued chunks', async () => {
|
|
34
34
|
const reader = new ChunkStreamReader(stream, 2);
|
|
35
35
|
|
|
36
|
-
const chunks: Uint8Array[] = [];
|
|
36
|
+
const chunks: Uint8Array<ArrayBuffer>[] = [];
|
|
37
37
|
for await (const chunk of reader.iterateChunks()) {
|
|
38
38
|
chunks.push(new Uint8Array(chunk));
|
|
39
39
|
}
|
|
@@ -50,7 +50,7 @@ describe('ChunkStreamReader', () => {
|
|
|
50
50
|
it('should yield bigger chunks than enqueued chunks', async () => {
|
|
51
51
|
const reader = new ChunkStreamReader(stream, 4);
|
|
52
52
|
|
|
53
|
-
const chunks: Uint8Array[] = [];
|
|
53
|
+
const chunks: Uint8Array<ArrayBuffer>[] = [];
|
|
54
54
|
for await (const chunk of reader.iterateChunks()) {
|
|
55
55
|
chunks.push(new Uint8Array(chunk));
|
|
56
56
|
}
|
|
@@ -64,7 +64,7 @@ describe('ChunkStreamReader', () => {
|
|
|
64
64
|
it('should yield last incomplete chunk', async () => {
|
|
65
65
|
const reader = new ChunkStreamReader(stream, 5);
|
|
66
66
|
|
|
67
|
-
const chunks: Uint8Array[] = [];
|
|
67
|
+
const chunks: Uint8Array<ArrayBuffer>[] = [];
|
|
68
68
|
for await (const chunk of reader.iterateChunks()) {
|
|
69
69
|
chunks.push(new Uint8Array(chunk));
|
|
70
70
|
}
|
|
@@ -78,7 +78,7 @@ describe('ChunkStreamReader', () => {
|
|
|
78
78
|
it('should yield as one big chunk', async () => {
|
|
79
79
|
const reader = new ChunkStreamReader(stream, 100);
|
|
80
80
|
|
|
81
|
-
const chunks: Uint8Array[] = [];
|
|
81
|
+
const chunks: Uint8Array<ArrayBuffer>[] = [];
|
|
82
82
|
for await (const chunk of reader.iterateChunks()) {
|
|
83
83
|
chunks.push(new Uint8Array(chunk));
|
|
84
84
|
}
|
|
@@ -6,16 +6,16 @@
|
|
|
6
6
|
* If you need to keep previous chunks, copy them to a new array.
|
|
7
7
|
*/
|
|
8
8
|
export class ChunkStreamReader {
|
|
9
|
-
private reader: ReadableStreamDefaultReader<Uint8Array
|
|
9
|
+
private reader: ReadableStreamDefaultReader<Uint8Array<ArrayBuffer>>;
|
|
10
10
|
|
|
11
11
|
private chunkSize: number;
|
|
12
12
|
|
|
13
|
-
constructor(stream: ReadableStream<Uint8Array
|
|
13
|
+
constructor(stream: ReadableStream<Uint8Array<ArrayBuffer>>, chunkSize: number) {
|
|
14
14
|
this.reader = stream.getReader();
|
|
15
15
|
this.chunkSize = chunkSize;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
async *iterateChunks(): AsyncGenerator<Uint8Array
|
|
18
|
+
async *iterateChunks(): AsyncGenerator<Uint8Array<ArrayBuffer>> {
|
|
19
19
|
const buffer = new Uint8Array(this.chunkSize);
|
|
20
20
|
|
|
21
21
|
let position = 0;
|
|
@@ -23,7 +23,7 @@ export class UploadCryptoService {
|
|
|
23
23
|
|
|
24
24
|
async generateFileCrypto(
|
|
25
25
|
parentUid: string,
|
|
26
|
-
parentKeys: { key: PrivateKey; hashKey: Uint8Array },
|
|
26
|
+
parentKeys: { key: PrivateKey; hashKey: Uint8Array<ArrayBuffer> },
|
|
27
27
|
name: string,
|
|
28
28
|
): Promise<NodeCrypto> {
|
|
29
29
|
const signingKeys = await this.getSigningKeys({ parentNodeUid: parentUid });
|
|
@@ -118,14 +118,14 @@ export class UploadCryptoService {
|
|
|
118
118
|
encryptedData: encryptedData,
|
|
119
119
|
originalSize: thumbnail.thumbnail.length,
|
|
120
120
|
encryptedSize: encryptedData.length,
|
|
121
|
-
hash: new Uint8Array(digest),
|
|
121
|
+
hash: new Uint8Array<ArrayBuffer>(digest),
|
|
122
122
|
};
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
async encryptBlock(
|
|
126
|
-
verifyBlock: (encryptedBlock: Uint8Array) => Promise<{ verificationToken: Uint8Array }>,
|
|
126
|
+
verifyBlock: (encryptedBlock: Uint8Array<ArrayBuffer>) => Promise<{ verificationToken: Uint8Array<ArrayBuffer> }>,
|
|
127
127
|
nodeRevisionDraftKeys: NodeRevisionDraftKeys,
|
|
128
|
-
block: Uint8Array
|
|
128
|
+
block: Uint8Array<ArrayBuffer>,
|
|
129
129
|
index: number,
|
|
130
130
|
): Promise<EncryptedBlock> {
|
|
131
131
|
const { encryptedData, armoredSignature } = await this.driveCrypto.encryptBlock(
|
|
@@ -145,13 +145,13 @@ export class UploadCryptoService {
|
|
|
145
145
|
verificationToken,
|
|
146
146
|
originalSize: block.length,
|
|
147
147
|
encryptedSize: encryptedData.length,
|
|
148
|
-
hash: new Uint8Array(digest),
|
|
148
|
+
hash: new Uint8Array<ArrayBuffer>(digest),
|
|
149
149
|
};
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
async commitFile(
|
|
153
153
|
nodeRevisionDraftKeys: NodeRevisionDraftKeys,
|
|
154
|
-
manifest: Uint8Array
|
|
154
|
+
manifest: Uint8Array<ArrayBuffer>,
|
|
155
155
|
extendedAttributes?: string,
|
|
156
156
|
): Promise<{
|
|
157
157
|
armoredManifestSignature: string;
|
|
@@ -190,10 +190,10 @@ export class UploadCryptoService {
|
|
|
190
190
|
|
|
191
191
|
async verifyBlock(
|
|
192
192
|
contentKeyPacketSessionKey: SessionKey,
|
|
193
|
-
verificationCode: Uint8Array
|
|
194
|
-
encryptedData: Uint8Array
|
|
193
|
+
verificationCode: Uint8Array<ArrayBuffer>,
|
|
194
|
+
encryptedData: Uint8Array<ArrayBuffer>,
|
|
195
195
|
): Promise<{
|
|
196
|
-
verificationToken: Uint8Array
|
|
196
|
+
verificationToken: Uint8Array<ArrayBuffer>;
|
|
197
197
|
}> {
|
|
198
198
|
// Attempt to decrypt data block, to try to detect bitflips / bad hardware
|
|
199
199
|
//
|
|
@@ -8,7 +8,7 @@ export type NodeRevisionDraft = {
|
|
|
8
8
|
nodeRevisionUid: string;
|
|
9
9
|
nodeKeys: NodeRevisionDraftKeys;
|
|
10
10
|
parentNodeKeys?: {
|
|
11
|
-
hashKey: Uint8Array
|
|
11
|
+
hashKey: Uint8Array<ArrayBuffer>;
|
|
12
12
|
};
|
|
13
13
|
// newNodeInfo is set only when revision is created with the new node.
|
|
14
14
|
newNodeInfo?: {
|
|
@@ -64,19 +64,19 @@ export type NodeCryptoSigningKeys = {
|
|
|
64
64
|
export type EncryptedBlockMetadata = {
|
|
65
65
|
encryptedSize: number;
|
|
66
66
|
originalSize: number;
|
|
67
|
-
hash: Uint8Array
|
|
67
|
+
hash: Uint8Array<ArrayBuffer>;
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
export type EncryptedBlock = EncryptedBlockMetadata & {
|
|
71
71
|
index: number;
|
|
72
|
-
encryptedData: Uint8Array
|
|
72
|
+
encryptedData: Uint8Array<ArrayBuffer>;
|
|
73
73
|
armoredSignature: string;
|
|
74
|
-
verificationToken: Uint8Array
|
|
74
|
+
verificationToken: Uint8Array<ArrayBuffer>;
|
|
75
75
|
};
|
|
76
76
|
|
|
77
77
|
export type EncryptedThumbnail = EncryptedBlockMetadata & {
|
|
78
78
|
type: ThumbnailType;
|
|
79
|
-
encryptedData: Uint8Array
|
|
79
|
+
encryptedData: Uint8Array<ArrayBuffer>;
|
|
80
80
|
};
|
|
81
81
|
|
|
82
82
|
export type UploadTokens = {
|
|
@@ -101,7 +101,7 @@ export interface NodesService {
|
|
|
101
101
|
key: PrivateKey;
|
|
102
102
|
passphraseSessionKey: SessionKey;
|
|
103
103
|
contentKeyPacketSessionKey?: SessionKey;
|
|
104
|
-
hashKey?: Uint8Array
|
|
104
|
+
hashKey?: Uint8Array<ArrayBuffer>;
|
|
105
105
|
}>;
|
|
106
106
|
getNodeSigningKeys(
|
|
107
107
|
uids: { nodeUid: string; parentNodeUid?: string } | { nodeUid?: string; parentNodeUid: string },
|
|
@@ -73,7 +73,7 @@ export class UploadManager {
|
|
|
73
73
|
|
|
74
74
|
private async createDraftOnAPI(
|
|
75
75
|
parentFolderUid: string,
|
|
76
|
-
parentHashKey: Uint8Array
|
|
76
|
+
parentHashKey: Uint8Array<ArrayBuffer>,
|
|
77
77
|
name: string,
|
|
78
78
|
metadata: UploadMetadata,
|
|
79
79
|
generatedNodeCrypto: NodeCrypto,
|
|
@@ -226,7 +226,7 @@ export class UploadManager {
|
|
|
226
226
|
|
|
227
227
|
async commitDraft(
|
|
228
228
|
nodeRevisionDraft: NodeRevisionDraft,
|
|
229
|
-
manifest: Uint8Array
|
|
229
|
+
manifest: Uint8Array<ArrayBuffer>,
|
|
230
230
|
extendedAttributes: {
|
|
231
231
|
modificationTime?: Date;
|
|
232
232
|
size: number;
|
|
@@ -655,7 +655,7 @@ export class StreamUploader {
|
|
|
655
655
|
return uploadedBlocks.map((block) => block.originalSize);
|
|
656
656
|
}
|
|
657
657
|
|
|
658
|
-
protected get manifest(): Uint8Array {
|
|
658
|
+
protected get manifest(): Uint8Array<ArrayBuffer> {
|
|
659
659
|
this.uploadedThumbnails.sort((a, b) => a.type - b.type);
|
|
660
660
|
this.uploadedBlocks.sort((a, b) => a.index - b.index);
|
|
661
661
|
const hashes = [
|
package/src/protonDriveClient.ts
CHANGED
|
@@ -223,12 +223,12 @@ export class ProtonDriveClient {
|
|
|
223
223
|
return keys.contentKeyPacketSessionKey;
|
|
224
224
|
},
|
|
225
225
|
getPublicLinkInfo: async (url: string) => {
|
|
226
|
-
const { token } = getTokenAndPasswordFromUrl(url)
|
|
226
|
+
const { token } = getTokenAndPasswordFromUrl(url);
|
|
227
227
|
this.logger.info(`Getting info for public link token ${token}`);
|
|
228
228
|
return this.publicSessionManager.getInfo(token);
|
|
229
229
|
},
|
|
230
230
|
authPublicLink: async (url: string, customPassword?: string, isAnonymousContext: boolean = false) => {
|
|
231
|
-
const { token, password: urlPassword } = getTokenAndPasswordFromUrl(url)
|
|
231
|
+
const { token, password: urlPassword } = getTokenAndPasswordFromUrl(url);
|
|
232
232
|
this.logger.info(`Authenticating public link token ${token}`);
|
|
233
233
|
|
|
234
234
|
const { httpClient, shareKey, rootUid, publicRole } = await this.publicSessionManager.auth(
|
|
@@ -681,7 +681,7 @@ export class ProtonDriveClient {
|
|
|
681
681
|
* @param customPassword - The optional custom password.
|
|
682
682
|
*/
|
|
683
683
|
async createBookmark(url: string, customPassword?: string): Promise<void> {
|
|
684
|
-
const { token, password: urlPassword } = getTokenAndPasswordFromUrl(url)
|
|
684
|
+
const { token, password: urlPassword } = getTokenAndPasswordFromUrl(url);
|
|
685
685
|
this.logger.info(`Creating bookmark for token ${token}`);
|
|
686
686
|
await this.sharing.access.createBookmark(token, urlPassword, customPassword);
|
|
687
687
|
}
|
|
@@ -912,6 +912,18 @@ export class ProtonDriveClient {
|
|
|
912
912
|
yield* this.devices.iterateDevices(signal);
|
|
913
913
|
}
|
|
914
914
|
|
|
915
|
+
/**
|
|
916
|
+
* Get the device entity by its UID.
|
|
917
|
+
*
|
|
918
|
+
* @param deviceOrUid - Device entity or its UID string.
|
|
919
|
+
* @returns The device entity.
|
|
920
|
+
* @throws {@link ValidationError} If the device is not found.
|
|
921
|
+
*/
|
|
922
|
+
async getDevice(deviceOrUid: DeviceOrUid): Promise<Device> {
|
|
923
|
+
this.logger.info(`Getting device ${getUid(deviceOrUid)}`);
|
|
924
|
+
return this.devices.getDevice(getUid(deviceOrUid));
|
|
925
|
+
}
|
|
926
|
+
|
|
915
927
|
/**
|
|
916
928
|
* Creates a new device.
|
|
917
929
|
*
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
NonProtonInvitationOrUid,
|
|
18
18
|
ProtonInvitationWithNode,
|
|
19
19
|
NodeResult,
|
|
20
|
+
NodeResultWithError,
|
|
20
21
|
} from './interface';
|
|
21
22
|
import { getConfig } from './config';
|
|
22
23
|
import { DriveCrypto } from './crypto';
|
|
@@ -38,6 +39,9 @@ import {
|
|
|
38
39
|
initPhotoSharesModule,
|
|
39
40
|
initPhotoUploadModule,
|
|
40
41
|
initPhotosNodesModule,
|
|
42
|
+
AlbumItem,
|
|
43
|
+
TimelineItem,
|
|
44
|
+
PhotoTag,
|
|
41
45
|
} from './internal/photos';
|
|
42
46
|
import { SDKEvents } from './internal/sdkEvents';
|
|
43
47
|
import { initSharesModule } from './internal/shares';
|
|
@@ -117,13 +121,7 @@ export class ProtonDrivePhotosClient {
|
|
|
117
121
|
this.photoShares,
|
|
118
122
|
fullConfig.clientUid,
|
|
119
123
|
);
|
|
120
|
-
this.photos = initPhotosModule(
|
|
121
|
-
telemetry,
|
|
122
|
-
apiService,
|
|
123
|
-
cryptoModule,
|
|
124
|
-
this.photoShares,
|
|
125
|
-
this.nodes.access,
|
|
126
|
-
);
|
|
124
|
+
this.photos = initPhotosModule(telemetry, apiService, cryptoModule, this.photoShares, this.nodes.access);
|
|
127
125
|
this.sharing = initSharingModule(
|
|
128
126
|
telemetry,
|
|
129
127
|
apiService,
|
|
@@ -224,12 +222,7 @@ export class ProtonDrivePhotosClient {
|
|
|
224
222
|
* The output is sorted by the capture time, starting from the
|
|
225
223
|
* the most recent photos.
|
|
226
224
|
*/
|
|
227
|
-
async *iterateTimeline(signal?: AbortSignal): AsyncGenerator<{
|
|
228
|
-
nodeUid: string;
|
|
229
|
-
captureTime: Date;
|
|
230
|
-
tags: number[];
|
|
231
|
-
}> {
|
|
232
|
-
// TODO: expose better type
|
|
225
|
+
async *iterateTimeline(signal?: AbortSignal): AsyncGenerator<TimelineItem> {
|
|
233
226
|
yield* this.photos.timeline.iterateTimeline(signal);
|
|
234
227
|
}
|
|
235
228
|
|
|
@@ -240,7 +233,7 @@ export class ProtonDrivePhotosClient {
|
|
|
240
233
|
*/
|
|
241
234
|
async *iterateTrashedNodes(signal?: AbortSignal): AsyncGenerator<MaybePhotoNode> {
|
|
242
235
|
this.logger.info('Iterating trashed nodes');
|
|
243
|
-
yield
|
|
236
|
+
yield* convertInternalPhotoNodeIterator(this.nodes.access.iterateTrashedNodes(signal));
|
|
244
237
|
}
|
|
245
238
|
|
|
246
239
|
/**
|
|
@@ -251,7 +244,7 @@ export class ProtonDrivePhotosClient {
|
|
|
251
244
|
async *iterateNodes(nodeUids: NodeOrUid[], signal?: AbortSignal): AsyncGenerator<MaybeMissingPhotoNode> {
|
|
252
245
|
this.logger.info(`Iterating ${nodeUids.length} nodes`);
|
|
253
246
|
// TODO: expose photo type
|
|
254
|
-
yield
|
|
247
|
+
yield* convertInternalMissingPhotoNodeIterator(this.nodes.access.iterateNodes(getUids(nodeUids), signal));
|
|
255
248
|
}
|
|
256
249
|
|
|
257
250
|
/**
|
|
@@ -301,7 +294,7 @@ export class ProtonDrivePhotosClient {
|
|
|
301
294
|
*/
|
|
302
295
|
async *deleteNodes(nodeUids: NodeOrUid[], signal?: AbortSignal): AsyncGenerator<NodeResult> {
|
|
303
296
|
this.logger.info(`Deleting ${nodeUids.length} nodes`);
|
|
304
|
-
yield
|
|
297
|
+
yield* this.nodes.management.deleteTrashedNodes(getUids(nodeUids), signal);
|
|
305
298
|
}
|
|
306
299
|
|
|
307
300
|
/**
|
|
@@ -319,7 +312,7 @@ export class ProtonDrivePhotosClient {
|
|
|
319
312
|
*/
|
|
320
313
|
async *iterateSharedNodes(signal?: AbortSignal): AsyncGenerator<MaybePhotoNode> {
|
|
321
314
|
this.logger.info('Iterating shared nodes by me');
|
|
322
|
-
yield
|
|
315
|
+
yield* convertInternalPhotoNodeIterator(this.sharing.access.iterateSharedNodes(signal));
|
|
323
316
|
}
|
|
324
317
|
|
|
325
318
|
/**
|
|
@@ -456,8 +449,7 @@ export class ProtonDrivePhotosClient {
|
|
|
456
449
|
metadata: UploadMetadata & {
|
|
457
450
|
captureTime?: Date;
|
|
458
451
|
mainPhotoLinkID?: string;
|
|
459
|
-
|
|
460
|
-
tags?: (0 | 3 | 1 | 2 | 7 | 4 | 5 | 6 | 8 | 9)[];
|
|
452
|
+
tags?: PhotoTag[];
|
|
461
453
|
},
|
|
462
454
|
signal?: AbortSignal,
|
|
463
455
|
): Promise<FileUploader> {
|
|
@@ -487,7 +479,9 @@ export class ProtonDrivePhotosClient {
|
|
|
487
479
|
*/
|
|
488
480
|
async isDuplicatePhoto(name: string, generateSha1: () => Promise<string>, signal?: AbortSignal): Promise<boolean> {
|
|
489
481
|
this.logger.info(`Checking if photo is a duplicate`);
|
|
490
|
-
return this.photos.timeline
|
|
482
|
+
return this.photos.timeline
|
|
483
|
+
.findPhotoDuplicates(name, generateSha1, signal)
|
|
484
|
+
.then((nodeUids) => nodeUids.length !== 0);
|
|
491
485
|
}
|
|
492
486
|
|
|
493
487
|
/**
|
|
@@ -508,7 +502,11 @@ export class ProtonDrivePhotosClient {
|
|
|
508
502
|
* @param signal - An optional abort signal to cancel the operation.
|
|
509
503
|
* @returns An array of node UIDs of duplicate photos. Empty array if no duplicates found.
|
|
510
504
|
*/
|
|
511
|
-
async findPhotoDuplicates(
|
|
505
|
+
async findPhotoDuplicates(
|
|
506
|
+
name: string,
|
|
507
|
+
generateSha1: () => Promise<string>,
|
|
508
|
+
signal?: AbortSignal,
|
|
509
|
+
): Promise<string[]> {
|
|
512
510
|
this.logger.info(`Checking if photo have duplicates`);
|
|
513
511
|
return this.photos.timeline.findPhotoDuplicates(name, generateSha1, signal);
|
|
514
512
|
}
|
|
@@ -578,6 +576,64 @@ export class ProtonDrivePhotosClient {
|
|
|
578
576
|
async *iterateAlbums(signal?: AbortSignal): AsyncGenerator<MaybePhotoNode> {
|
|
579
577
|
this.logger.info('Iterating albums');
|
|
580
578
|
// TODO: expose album type
|
|
581
|
-
yield
|
|
579
|
+
yield* convertInternalPhotoNodeIterator(this.photos.albums.iterateAlbums(signal));
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/**
|
|
583
|
+
* Iterates the photo placeholders of the given album.
|
|
584
|
+
*
|
|
585
|
+
* The output is sorted by the capture time, starting from the
|
|
586
|
+
* the most recent photos.
|
|
587
|
+
*
|
|
588
|
+
* @param albumNodeUid - The UID of the album.
|
|
589
|
+
* @param signal - An optional abort the operation.
|
|
590
|
+
*/
|
|
591
|
+
async *iterateAlbum(albumNodeUid: NodeOrUid, signal?: AbortSignal): AsyncGenerator<AlbumItem> {
|
|
592
|
+
this.logger.info(`Iterating photos of album ${getUid(albumNodeUid)}`);
|
|
593
|
+
yield* this.photos.albums.iterateAlbum(getUid(albumNodeUid), signal);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Adds photos to an album.
|
|
598
|
+
*
|
|
599
|
+
* Photos are added in batches. Each photo's related photos (e.g., live
|
|
600
|
+
* photo components) are always included with the main photo.
|
|
601
|
+
*
|
|
602
|
+
* The album has a limit of 10,000 photos. If the limit is reached,
|
|
603
|
+
* a `ValidationError` is thrown.
|
|
604
|
+
*
|
|
605
|
+
* @param albumNodeUid - The UID of the album to add photos to.
|
|
606
|
+
* @param photoNodeUids - The UIDs of the photos to add to the album.
|
|
607
|
+
* @param signal - An optional abort signal to cancel the operation.
|
|
608
|
+
* @returns An async generator of the added photo results.
|
|
609
|
+
*/
|
|
610
|
+
async *addPhotosToAlbum(
|
|
611
|
+
albumNodeUid: NodeOrUid,
|
|
612
|
+
photoNodeUids: NodeOrUid[],
|
|
613
|
+
signal?: AbortSignal,
|
|
614
|
+
): AsyncGenerator<NodeResultWithError> {
|
|
615
|
+
this.logger.info(`Adding ${photoNodeUids.length} photos to album ${getUid(albumNodeUid)}`);
|
|
616
|
+
yield* this.photos.albums.addPhotos(getUid(albumNodeUid), getUids(photoNodeUids), signal);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* Removes photos from an album.
|
|
621
|
+
*
|
|
622
|
+
* Photos are not deleted, they are just removed from the album.
|
|
623
|
+
* If a photo was added to the timeline by the user, it will remain
|
|
624
|
+
* in the timeline after being removed from the album.
|
|
625
|
+
*
|
|
626
|
+
* @param albumNodeUid - The UID of the album to remove photos from.
|
|
627
|
+
* @param photoNodeUids - The UIDs of the photos to remove from the album.
|
|
628
|
+
* @param signal - An optional abort signal to cancel the operation.
|
|
629
|
+
* @returns An async generator of the removed photo results.
|
|
630
|
+
*/
|
|
631
|
+
async *removePhotosFromAlbum(
|
|
632
|
+
albumNodeUid: NodeOrUid,
|
|
633
|
+
photoNodeUids: NodeOrUid[],
|
|
634
|
+
signal?: AbortSignal,
|
|
635
|
+
): AsyncGenerator<NodeResultWithError> {
|
|
636
|
+
this.logger.info(`Removing ${photoNodeUids.length} photos from album ${getUid(albumNodeUid)}`);
|
|
637
|
+
yield* this.photos.albums.removePhotos(getUid(albumNodeUid), getUids(photoNodeUids), signal);
|
|
582
638
|
}
|
|
583
639
|
}
|
|
@@ -350,4 +350,17 @@ export class ProtonDrivePublicLinkClient {
|
|
|
350
350
|
this.logger.info(`Getting file revision uploader for ${getUid(nodeUid)}`);
|
|
351
351
|
return this.upload.getFileRevisionUploader(getUid(nodeUid), metadata, signal);
|
|
352
352
|
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Returns the available name for the file in the given parent folder.
|
|
356
|
+
*
|
|
357
|
+
* The function will return a name that includes the original name with the
|
|
358
|
+
* available index. The name is guaranteed to be unique in the parent folder.
|
|
359
|
+
*
|
|
360
|
+
* Example new name: `file (2).txt`.
|
|
361
|
+
*/
|
|
362
|
+
async getAvailableName(parentFolderUid: NodeOrUid, name: string): Promise<string> {
|
|
363
|
+
this.logger.info(`Getting available name in folder ${getUid(parentFolderUid)}`);
|
|
364
|
+
return this.sharingPublic.nodes.management.findAvailableName(getUid(parentFolderUid), name);
|
|
365
|
+
}
|
|
353
366
|
}
|
package/src/transformers.ts
CHANGED
|
@@ -160,11 +160,13 @@ export function convertInternalPhotoNode(photoNode: InternalPartialPhotoNode): P
|
|
|
160
160
|
return resultOk({
|
|
161
161
|
...node.value,
|
|
162
162
|
photo: photoNode.photo,
|
|
163
|
+
album: photoNode.album,
|
|
163
164
|
} as PublicPhotoNode);
|
|
164
165
|
}
|
|
165
166
|
return resultError({
|
|
166
167
|
...node.error,
|
|
167
168
|
photo: photoNode.photo,
|
|
169
|
+
album: photoNode.album,
|
|
168
170
|
} as PublicDegradedPhotoNode);
|
|
169
171
|
}
|
|
170
172
|
|