@protontech/drive-sdk 0.1.2 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/crypto/driveCrypto.d.ts +11 -0
- package/dist/crypto/driveCrypto.js +20 -7
- package/dist/crypto/driveCrypto.js.map +1 -1
- package/dist/crypto/interface.d.ts +10 -1
- package/dist/crypto/openPGPCrypto.d.ts +18 -2
- package/dist/crypto/openPGPCrypto.js +25 -6
- package/dist/crypto/openPGPCrypto.js.map +1 -1
- package/dist/diagnostic/telemetry.d.ts +1 -1
- package/dist/diagnostic/telemetry.js +1 -1
- package/dist/diagnostic/telemetry.js.map +1 -1
- package/dist/interface/download.d.ts +46 -0
- package/dist/interface/index.d.ts +2 -2
- package/dist/interface/index.js.map +1 -1
- package/dist/interface/nodes.d.ts +26 -1
- package/dist/interface/nodes.js.map +1 -1
- package/dist/interface/sharing.d.ts +3 -1
- package/dist/interface/telemetry.d.ts +5 -2
- package/dist/interface/telemetry.js.map +1 -1
- package/dist/internal/apiService/apiService.js +1 -1
- package/dist/internal/apiService/apiService.js.map +1 -1
- package/dist/internal/apiService/driveTypes.d.ts +78 -165
- package/dist/internal/apiService/errorCodes.d.ts +1 -0
- package/dist/internal/apiService/errors.js +1 -0
- package/dist/internal/apiService/errors.js.map +1 -1
- package/dist/internal/apiService/index.d.ts +1 -1
- package/dist/internal/apiService/index.js +2 -2
- package/dist/internal/apiService/index.js.map +1 -1
- package/dist/internal/apiService/transformers.d.ts +1 -1
- package/dist/internal/apiService/transformers.js +2 -2
- package/dist/internal/apiService/transformers.js.map +1 -1
- package/dist/internal/download/blockIndex.d.ts +11 -0
- package/dist/internal/download/blockIndex.js +35 -0
- package/dist/internal/download/blockIndex.js.map +1 -0
- package/dist/internal/download/blockIndex.test.d.ts +1 -0
- package/dist/internal/download/blockIndex.test.js +147 -0
- package/dist/internal/download/blockIndex.test.js.map +1 -0
- package/dist/internal/download/fileDownloader.d.ts +6 -2
- package/dist/internal/download/fileDownloader.js +83 -6
- package/dist/internal/download/fileDownloader.js.map +1 -1
- package/dist/internal/download/fileDownloader.test.js +69 -4
- package/dist/internal/download/fileDownloader.test.js.map +1 -1
- package/dist/internal/download/interface.d.ts +4 -4
- package/dist/internal/download/seekableStream.d.ts +80 -0
- package/dist/internal/download/seekableStream.js +163 -0
- package/dist/internal/download/seekableStream.js.map +1 -0
- package/dist/internal/download/seekableStream.test.d.ts +1 -0
- package/dist/internal/download/seekableStream.test.js +149 -0
- package/dist/internal/download/seekableStream.test.js.map +1 -0
- package/dist/internal/download/telemetry.js +1 -1
- package/dist/internal/download/telemetry.js.map +1 -1
- package/dist/internal/download/telemetry.test.js +7 -7
- package/dist/internal/download/telemetry.test.js.map +1 -1
- package/dist/internal/errors.d.ts +1 -1
- package/dist/internal/errors.js +7 -1
- package/dist/internal/errors.js.map +1 -1
- package/dist/internal/errors.test.js +44 -10
- package/dist/internal/errors.test.js.map +1 -1
- package/dist/internal/events/index.js +1 -1
- package/dist/internal/events/index.js.map +1 -1
- package/dist/internal/nodes/apiService.js +16 -3
- package/dist/internal/nodes/apiService.js.map +1 -1
- package/dist/internal/nodes/apiService.test.js +43 -7
- package/dist/internal/nodes/apiService.test.js.map +1 -1
- package/dist/internal/nodes/cache.js +12 -3
- package/dist/internal/nodes/cache.js.map +1 -1
- package/dist/internal/nodes/cache.test.js +31 -1
- package/dist/internal/nodes/cache.test.js.map +1 -1
- package/dist/internal/nodes/cryptoService.d.ts +4 -1
- package/dist/internal/nodes/cryptoService.js +66 -16
- package/dist/internal/nodes/cryptoService.js.map +1 -1
- package/dist/internal/nodes/cryptoService.test.js +129 -46
- package/dist/internal/nodes/cryptoService.test.js.map +1 -1
- package/dist/internal/nodes/extendedAttributes.d.ts +2 -1
- package/dist/internal/nodes/extendedAttributes.js +27 -1
- package/dist/internal/nodes/extendedAttributes.js.map +1 -1
- package/dist/internal/nodes/extendedAttributes.test.js +59 -6
- package/dist/internal/nodes/extendedAttributes.test.js.map +1 -1
- 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 +18 -2
- package/dist/internal/nodes/nodesAccess.js +11 -1
- package/dist/internal/nodes/nodesAccess.js.map +1 -1
- package/dist/internal/nodes/nodesManagement.js +1 -1
- package/dist/internal/nodes/nodesManagement.js.map +1 -1
- package/dist/internal/nodes/nodesRevisions.d.ts +4 -3
- package/dist/internal/nodes/nodesRevisions.js +2 -2
- package/dist/internal/nodes/nodesRevisions.js.map +1 -1
- package/dist/internal/shares/cryptoService.js +7 -4
- package/dist/internal/shares/cryptoService.js.map +1 -1
- package/dist/internal/shares/cryptoService.test.js +5 -3
- package/dist/internal/shares/cryptoService.test.js.map +1 -1
- package/dist/internal/sharing/apiService.js +5 -5
- package/dist/internal/sharing/apiService.js.map +1 -1
- package/dist/internal/sharing/cryptoService.d.ts +1 -0
- package/dist/internal/sharing/cryptoService.js +22 -10
- package/dist/internal/sharing/cryptoService.js.map +1 -1
- package/dist/internal/sharing/cryptoService.test.js +7 -4
- package/dist/internal/sharing/cryptoService.test.js.map +1 -1
- package/dist/internal/sharing/sharingAccess.js +4 -2
- package/dist/internal/sharing/sharingAccess.js.map +1 -1
- package/dist/internal/sharing/sharingAccess.test.js +6 -0
- package/dist/internal/sharing/sharingAccess.test.js.map +1 -1
- package/dist/internal/upload/telemetry.js +2 -2
- package/dist/internal/upload/telemetry.js.map +1 -1
- package/dist/internal/upload/telemetry.test.js +7 -7
- package/dist/internal/upload/telemetry.test.js.map +1 -1
- package/dist/telemetry.d.ts +2 -2
- package/dist/telemetry.js +2 -2
- package/dist/telemetry.js.map +1 -1
- package/dist/tests/telemetry.js +1 -1
- package/dist/tests/telemetry.js.map +1 -1
- package/dist/transformers.d.ts +1 -1
- package/dist/transformers.js +2 -1
- package/dist/transformers.js.map +1 -1
- package/package.json +1 -1
- package/src/crypto/driveCrypto.ts +70 -25
- package/src/crypto/interface.ts +15 -0
- package/src/crypto/openPGPCrypto.ts +37 -5
- package/src/diagnostic/telemetry.ts +1 -1
- package/src/interface/download.ts +46 -0
- package/src/interface/index.ts +2 -1
- package/src/interface/nodes.ts +28 -1
- package/src/interface/sharing.ts +3 -1
- package/src/interface/telemetry.ts +6 -1
- package/src/internal/apiService/apiService.ts +1 -1
- package/src/internal/apiService/driveTypes.ts +78 -165
- package/src/internal/apiService/errorCodes.ts +1 -0
- package/src/internal/apiService/errors.ts +1 -0
- package/src/internal/apiService/index.ts +1 -1
- package/src/internal/apiService/transformers.ts +1 -1
- package/src/internal/download/blockIndex.test.ts +158 -0
- package/src/internal/download/blockIndex.ts +36 -0
- package/src/internal/download/fileDownloader.test.ts +100 -7
- package/src/internal/download/fileDownloader.ts +109 -9
- package/src/internal/download/interface.ts +4 -4
- package/src/internal/download/seekableStream.test.ts +187 -0
- package/src/internal/download/seekableStream.ts +182 -0
- package/src/internal/download/telemetry.test.ts +7 -7
- package/src/internal/download/telemetry.ts +1 -1
- package/src/internal/errors.test.ts +45 -11
- package/src/internal/errors.ts +8 -0
- package/src/internal/events/index.ts +1 -1
- package/src/internal/nodes/apiService.test.ts +59 -15
- package/src/internal/nodes/apiService.ts +21 -4
- package/src/internal/nodes/cache.test.ts +34 -1
- package/src/internal/nodes/cache.ts +12 -3
- package/src/internal/nodes/cryptoService.test.ts +139 -47
- package/src/internal/nodes/cryptoService.ts +94 -9
- package/src/internal/nodes/extendedAttributes.test.ts +60 -7
- package/src/internal/nodes/extendedAttributes.ts +37 -1
- package/src/internal/nodes/index.test.ts +1 -1
- package/src/internal/nodes/interface.ts +19 -2
- package/src/internal/nodes/nodesAccess.ts +15 -1
- package/src/internal/nodes/nodesManagement.ts +1 -1
- package/src/internal/nodes/nodesRevisions.ts +14 -5
- package/src/internal/shares/cryptoService.test.ts +5 -3
- package/src/internal/shares/cryptoService.ts +7 -4
- package/src/internal/sharing/apiService.ts +6 -6
- package/src/internal/sharing/cryptoService.test.ts +7 -4
- package/src/internal/sharing/cryptoService.ts +27 -10
- package/src/internal/sharing/sharingAccess.test.ts +6 -0
- package/src/internal/sharing/sharingAccess.ts +4 -2
- package/src/internal/upload/telemetry.test.ts +7 -7
- package/src/internal/upload/telemetry.ts +2 -2
- package/src/telemetry.ts +2 -2
- package/src/tests/telemetry.ts +1 -1
- package/src/transformers.ts +4 -2
|
@@ -148,7 +148,7 @@ export class SharingCryptoService {
|
|
|
148
148
|
}
|
|
149
149
|
const addressPublicKeys = await this.account.getPublicKeys(share.creatorEmail);
|
|
150
150
|
|
|
151
|
-
const { key, passphraseSessionKey, verified } = await this.driveCrypto.decryptKey(
|
|
151
|
+
const { key, passphraseSessionKey, verified, verificationErrors } = await this.driveCrypto.decryptKey(
|
|
152
152
|
share.encryptedCrypto.armoredKey,
|
|
153
153
|
share.encryptedCrypto.armoredPassphrase,
|
|
154
154
|
share.encryptedCrypto.armoredPassphraseSignature,
|
|
@@ -161,7 +161,7 @@ export class SharingCryptoService {
|
|
|
161
161
|
? resultOk(share.creatorEmail)
|
|
162
162
|
: resultError({
|
|
163
163
|
claimedAuthor: share.creatorEmail,
|
|
164
|
-
error: getVerificationMessage(verified),
|
|
164
|
+
error: getVerificationMessage(verified, verificationErrors),
|
|
165
165
|
});
|
|
166
166
|
|
|
167
167
|
return {
|
|
@@ -411,10 +411,7 @@ export class SharingCryptoService {
|
|
|
411
411
|
};
|
|
412
412
|
case PublicLinkFlags.GeneratedPasswordIncluded:
|
|
413
413
|
case PublicLinkFlags.GeneratedPasswordWithCustomPassword:
|
|
414
|
-
return
|
|
415
|
-
password: password.substring(0, PUBLIC_LINK_GENERATED_PASSWORD_LENGTH),
|
|
416
|
-
customPassword: password.substring(PUBLIC_LINK_GENERATED_PASSWORD_LENGTH) || undefined,
|
|
417
|
-
};
|
|
414
|
+
return splitGeneratedAndCustomPassword(password);
|
|
418
415
|
default:
|
|
419
416
|
throw new Error(`Unsupported public link with flags: ${encryptedPublicLink.flags}`);
|
|
420
417
|
}
|
|
@@ -422,18 +419,24 @@ export class SharingCryptoService {
|
|
|
422
419
|
|
|
423
420
|
async decryptBookmark(encryptedBookmark: EncryptedBookmark): Promise<{
|
|
424
421
|
url: Result<string, Error>;
|
|
422
|
+
customPassword: Result<string | undefined, Error>;
|
|
425
423
|
nodeName: Result<string, Error | InvalidNameError>;
|
|
426
424
|
}> {
|
|
427
425
|
// TODO: Signatures are not checked and not specified in the interface.
|
|
428
426
|
// In the future, we will need to add authorship verification.
|
|
429
427
|
|
|
430
428
|
let urlPassword: string;
|
|
429
|
+
let customPassword: Result<string | undefined, Error>;
|
|
431
430
|
try {
|
|
432
|
-
|
|
431
|
+
const password = await this.decryptBookmarkUrlPassword(encryptedBookmark);
|
|
432
|
+
const result = splitGeneratedAndCustomPassword(password);
|
|
433
|
+
urlPassword = result.password;
|
|
434
|
+
customPassword = resultOk(result.customPassword);
|
|
433
435
|
} catch (originalError: unknown) {
|
|
434
436
|
const error = originalError instanceof Error ? originalError : new Error(c('Error').t`Unknown error`);
|
|
435
437
|
return {
|
|
436
438
|
url: resultError(error),
|
|
439
|
+
customPassword: resultError(error),
|
|
437
440
|
nodeName: resultError(error),
|
|
438
441
|
};
|
|
439
442
|
}
|
|
@@ -448,6 +451,7 @@ export class SharingCryptoService {
|
|
|
448
451
|
const error = originalError instanceof Error ? originalError : new Error(c('Error').t`Unknown error`);
|
|
449
452
|
return {
|
|
450
453
|
url,
|
|
454
|
+
customPassword,
|
|
451
455
|
nodeName: resultError(error),
|
|
452
456
|
};
|
|
453
457
|
}
|
|
@@ -456,6 +460,7 @@ export class SharingCryptoService {
|
|
|
456
460
|
|
|
457
461
|
return {
|
|
458
462
|
url,
|
|
463
|
+
customPassword,
|
|
459
464
|
nodeName,
|
|
460
465
|
};
|
|
461
466
|
}
|
|
@@ -478,11 +483,12 @@ export class SharingCryptoService {
|
|
|
478
483
|
|
|
479
484
|
return urlPassword;
|
|
480
485
|
} catch (error: unknown) {
|
|
481
|
-
this.telemetry.
|
|
486
|
+
this.telemetry.recordMetric({
|
|
482
487
|
eventName: 'decryptionError',
|
|
483
488
|
volumeType: MetricVolumeType.SharedPublic,
|
|
484
489
|
field: 'shareUrlPassword',
|
|
485
490
|
error,
|
|
491
|
+
uid: encryptedBookmark.tokenId,
|
|
486
492
|
});
|
|
487
493
|
|
|
488
494
|
const message = getErrorMessage(error);
|
|
@@ -503,11 +509,12 @@ export class SharingCryptoService {
|
|
|
503
509
|
|
|
504
510
|
return shareKey;
|
|
505
511
|
} catch (error: unknown) {
|
|
506
|
-
this.telemetry.
|
|
512
|
+
this.telemetry.recordMetric({
|
|
507
513
|
eventName: 'decryptionError',
|
|
508
514
|
volumeType: MetricVolumeType.SharedPublic,
|
|
509
515
|
field: 'shareKey',
|
|
510
516
|
error,
|
|
517
|
+
uid: encryptedBookmark.tokenId,
|
|
511
518
|
});
|
|
512
519
|
|
|
513
520
|
const message = getErrorMessage(error);
|
|
@@ -535,11 +542,12 @@ export class SharingCryptoService {
|
|
|
535
542
|
|
|
536
543
|
return resultOk(name);
|
|
537
544
|
} catch (error: unknown) {
|
|
538
|
-
this.telemetry.
|
|
545
|
+
this.telemetry.recordMetric({
|
|
539
546
|
eventName: 'decryptionError',
|
|
540
547
|
volumeType: MetricVolumeType.SharedPublic,
|
|
541
548
|
field: 'nodeName',
|
|
542
549
|
error,
|
|
550
|
+
uid: encryptedBookmark.tokenId,
|
|
543
551
|
});
|
|
544
552
|
|
|
545
553
|
const message = getErrorMessage(error);
|
|
@@ -548,3 +556,12 @@ export class SharingCryptoService {
|
|
|
548
556
|
}
|
|
549
557
|
}
|
|
550
558
|
}
|
|
559
|
+
|
|
560
|
+
function splitGeneratedAndCustomPassword(concatenatedPassword: string): {
|
|
561
|
+
password: string;
|
|
562
|
+
customPassword?: string;
|
|
563
|
+
} {
|
|
564
|
+
const password = concatenatedPassword.substring(0, PUBLIC_LINK_GENERATED_PASSWORD_LENGTH);
|
|
565
|
+
const customPassword = concatenatedPassword.substring(PUBLIC_LINK_GENERATED_PASSWORD_LENGTH) || undefined;
|
|
566
|
+
return { password, customPassword };
|
|
567
|
+
}
|
|
@@ -116,6 +116,7 @@ describe('SharingAccess', () => {
|
|
|
116
116
|
it('should return decrypted bookmark', async () => {
|
|
117
117
|
cryptoService.decryptBookmark = jest.fn().mockResolvedValue({
|
|
118
118
|
url: resultOk('url'),
|
|
119
|
+
customPassword: resultOk('customPassword'),
|
|
119
120
|
nodeName: resultOk('nodeName'),
|
|
120
121
|
});
|
|
121
122
|
|
|
@@ -126,6 +127,7 @@ describe('SharingAccess', () => {
|
|
|
126
127
|
uid: 'tokenId',
|
|
127
128
|
creationTime: new Date('2025-01-01'),
|
|
128
129
|
url: 'url',
|
|
130
|
+
customPassword: 'customPassword',
|
|
129
131
|
node: {
|
|
130
132
|
name: 'nodeName',
|
|
131
133
|
type: NodeType.File,
|
|
@@ -138,6 +140,7 @@ describe('SharingAccess', () => {
|
|
|
138
140
|
it('should return degraded bookmark if URL password cannot be decrypted', async () => {
|
|
139
141
|
cryptoService.decryptBookmark = jest.fn().mockResolvedValue({
|
|
140
142
|
url: resultError('url cannot be decrypted'),
|
|
143
|
+
customPassword: resultOk('url cannot be decrypted'),
|
|
141
144
|
nodeName: resultError('url cannot be decrypted'),
|
|
142
145
|
});
|
|
143
146
|
|
|
@@ -148,6 +151,7 @@ describe('SharingAccess', () => {
|
|
|
148
151
|
uid: 'tokenId',
|
|
149
152
|
creationTime: new Date('2025-01-01'),
|
|
150
153
|
url: resultError('url cannot be decrypted'),
|
|
154
|
+
customPassword: resultOk('url cannot be decrypted'),
|
|
151
155
|
node: {
|
|
152
156
|
name: resultError('url cannot be decrypted'),
|
|
153
157
|
type: NodeType.File,
|
|
@@ -160,6 +164,7 @@ describe('SharingAccess', () => {
|
|
|
160
164
|
it('should return degraded bookmark if node name cannot be decrypted', async () => {
|
|
161
165
|
cryptoService.decryptBookmark = jest.fn().mockResolvedValue({
|
|
162
166
|
url: resultOk('url'),
|
|
167
|
+
customPassword: resultOk(undefined),
|
|
163
168
|
nodeName: resultError('node name cannot be decrypted'),
|
|
164
169
|
});
|
|
165
170
|
|
|
@@ -170,6 +175,7 @@ describe('SharingAccess', () => {
|
|
|
170
175
|
uid: 'tokenId',
|
|
171
176
|
creationTime: new Date('2025-01-01'),
|
|
172
177
|
url: resultOk('url'),
|
|
178
|
+
customPassword: resultOk(undefined),
|
|
173
179
|
node: {
|
|
174
180
|
name: resultError('node name cannot be decrypted'),
|
|
175
181
|
type: NodeType.File,
|
|
@@ -140,13 +140,14 @@ export class SharingAccess {
|
|
|
140
140
|
|
|
141
141
|
async *iterateBookmarks(signal?: AbortSignal): AsyncGenerator<MaybeBookmark> {
|
|
142
142
|
for await (const bookmark of this.apiService.iterateBookmarks(signal)) {
|
|
143
|
-
const { url, nodeName } = await this.cryptoService.decryptBookmark(bookmark);
|
|
143
|
+
const { url, customPassword, nodeName } = await this.cryptoService.decryptBookmark(bookmark);
|
|
144
144
|
|
|
145
|
-
if (!url.ok || !nodeName.ok) {
|
|
145
|
+
if (!url.ok || !customPassword.ok || !nodeName.ok) {
|
|
146
146
|
yield resultError({
|
|
147
147
|
uid: bookmark.tokenId,
|
|
148
148
|
creationTime: bookmark.creationTime,
|
|
149
149
|
url: url,
|
|
150
|
+
customPassword,
|
|
150
151
|
node: {
|
|
151
152
|
name: nodeName,
|
|
152
153
|
type: bookmark.node.type,
|
|
@@ -158,6 +159,7 @@ export class SharingAccess {
|
|
|
158
159
|
uid: bookmark.tokenId,
|
|
159
160
|
creationTime: bookmark.creationTime,
|
|
160
161
|
url: url.value,
|
|
162
|
+
customPassword: customPassword.value,
|
|
161
163
|
node: {
|
|
162
164
|
name: nodeName.value,
|
|
163
165
|
type: bookmark.node.type,
|
|
@@ -14,7 +14,7 @@ describe('UploadTelemetry', () => {
|
|
|
14
14
|
|
|
15
15
|
beforeEach(() => {
|
|
16
16
|
mockTelemetry = {
|
|
17
|
-
|
|
17
|
+
recordMetric: jest.fn(),
|
|
18
18
|
getLogger: jest.fn().mockReturnValue({
|
|
19
19
|
info: jest.fn(),
|
|
20
20
|
warn: jest.fn(),
|
|
@@ -34,7 +34,7 @@ describe('UploadTelemetry', () => {
|
|
|
34
34
|
const error = new Error('Failed');
|
|
35
35
|
await uploadTelemetry.uploadInitFailed(parentNodeUid, error, 1000);
|
|
36
36
|
|
|
37
|
-
expect(mockTelemetry.
|
|
37
|
+
expect(mockTelemetry.recordMetric).toHaveBeenCalledWith({
|
|
38
38
|
eventName: 'upload',
|
|
39
39
|
volumeType: 'own_volume',
|
|
40
40
|
uploadedSize: 0,
|
|
@@ -48,7 +48,7 @@ describe('UploadTelemetry', () => {
|
|
|
48
48
|
const error = new Error('Failed');
|
|
49
49
|
await uploadTelemetry.uploadFailed(revisionUid, error, 500, 1000);
|
|
50
50
|
|
|
51
|
-
expect(mockTelemetry.
|
|
51
|
+
expect(mockTelemetry.recordMetric).toHaveBeenCalledWith({
|
|
52
52
|
eventName: 'upload',
|
|
53
53
|
volumeType: 'own_volume',
|
|
54
54
|
uploadedSize: 500,
|
|
@@ -61,7 +61,7 @@ describe('UploadTelemetry', () => {
|
|
|
61
61
|
it('should log successful upload (excludes error)', async () => {
|
|
62
62
|
await uploadTelemetry.uploadFinished(revisionUid, 1000);
|
|
63
63
|
|
|
64
|
-
expect(mockTelemetry.
|
|
64
|
+
expect(mockTelemetry.recordMetric).toHaveBeenCalledWith({
|
|
65
65
|
eventName: 'upload',
|
|
66
66
|
volumeType: 'own_volume',
|
|
67
67
|
uploadedSize: 1000,
|
|
@@ -71,7 +71,7 @@ describe('UploadTelemetry', () => {
|
|
|
71
71
|
|
|
72
72
|
describe('detect error category', () => {
|
|
73
73
|
const verifyErrorCategory = (error: string) => {
|
|
74
|
-
expect(mockTelemetry.
|
|
74
|
+
expect(mockTelemetry.recordMetric).toHaveBeenCalledWith(
|
|
75
75
|
expect.objectContaining({
|
|
76
76
|
error,
|
|
77
77
|
}),
|
|
@@ -81,7 +81,7 @@ describe('UploadTelemetry', () => {
|
|
|
81
81
|
it('should ignore ValidationError', async () => {
|
|
82
82
|
const error = new ValidationError('Validation error');
|
|
83
83
|
await uploadTelemetry.uploadFailed(revisionUid, error, 500, 1000);
|
|
84
|
-
expect(mockTelemetry.
|
|
84
|
+
expect(mockTelemetry.recordMetric).not.toHaveBeenCalled();
|
|
85
85
|
});
|
|
86
86
|
|
|
87
87
|
it('should ignore AbortError', async () => {
|
|
@@ -89,7 +89,7 @@ describe('UploadTelemetry', () => {
|
|
|
89
89
|
error.name = 'AbortError';
|
|
90
90
|
await uploadTelemetry.uploadFailed(revisionUid, error, 500, 1000);
|
|
91
91
|
|
|
92
|
-
expect(mockTelemetry.
|
|
92
|
+
expect(mockTelemetry.recordMetric).not.toHaveBeenCalled();
|
|
93
93
|
});
|
|
94
94
|
|
|
95
95
|
it('should detect "rate_limited" error for RateLimitedError', async () => {
|
|
@@ -23,7 +23,7 @@ export class UploadTelemetry {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
logBlockVerificationError(retryHelped: boolean) {
|
|
26
|
-
this.telemetry.
|
|
26
|
+
this.telemetry.recordMetric({
|
|
27
27
|
eventName: 'blockVerificationError',
|
|
28
28
|
retryHelped,
|
|
29
29
|
});
|
|
@@ -89,7 +89,7 @@ export class UploadTelemetry {
|
|
|
89
89
|
this.logger.error('Failed to get metric volume type', error);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
this.telemetry.
|
|
92
|
+
this.telemetry.recordMetric({
|
|
93
93
|
eventName: 'upload',
|
|
94
94
|
volumeType,
|
|
95
95
|
...options,
|
package/src/telemetry.ts
CHANGED
|
@@ -66,7 +66,7 @@ export interface MetricHandler<T extends MetricEvent> {
|
|
|
66
66
|
* const logger = telemetry.getLogger('myLogger');
|
|
67
67
|
* logger.debug('Debug message');
|
|
68
68
|
*
|
|
69
|
-
* telemetry.
|
|
69
|
+
* telemetry.recordMetric({ name: 'somethingHappened', value: 42 });
|
|
70
70
|
*
|
|
71
71
|
* const logs = memoryLogHandler.getLogs();
|
|
72
72
|
* // Process logs
|
|
@@ -91,7 +91,7 @@ export class Telemetry<T extends MetricEvent> {
|
|
|
91
91
|
return new Logger(name, this.logFilter, this.logHandlers);
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
recordMetric(event: T): void {
|
|
95
95
|
const metric = {
|
|
96
96
|
time: new Date(),
|
|
97
97
|
event,
|
package/src/tests/telemetry.ts
CHANGED
package/src/transformers.ts
CHANGED
|
@@ -18,7 +18,8 @@ type InternalPartialNode = Pick<
|
|
|
18
18
|
| 'name'
|
|
19
19
|
| 'keyAuthor'
|
|
20
20
|
| 'nameAuthor'
|
|
21
|
-
| '
|
|
21
|
+
| 'directRole'
|
|
22
|
+
| 'membership'
|
|
22
23
|
| 'type'
|
|
23
24
|
| 'mediaType'
|
|
24
25
|
| 'isShared'
|
|
@@ -84,7 +85,8 @@ export function convertInternalNode(node: InternalPartialNode): PublicMaybeNode
|
|
|
84
85
|
parentUid: node.parentUid,
|
|
85
86
|
keyAuthor: node.keyAuthor,
|
|
86
87
|
nameAuthor: node.nameAuthor,
|
|
87
|
-
|
|
88
|
+
directRole: node.directRole,
|
|
89
|
+
membership: node.membership,
|
|
88
90
|
type: node.type,
|
|
89
91
|
mediaType: node.mediaType,
|
|
90
92
|
isShared: node.isShared,
|