@secrecy/lib 1.61.2 → 1.62.0-feat-storage-providers.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.
@@ -50,7 +50,7 @@ export class SecrecyCloudClient {
50
50
  }
51
51
  return internalNodeFullToNodeFull(node);
52
52
  }
53
- async uploadData({ storageType, data, encrypted = true, encryptProgress, uploadProgress, signal, meta, }) {
53
+ async uploadData({ storage, data, encrypted = true, encryptProgress, uploadProgress, signal, meta, }) {
54
54
  const dataBuffer = data instanceof File ? new Uint8Array(await data.arrayBuffer()) : data;
55
55
  let filetype;
56
56
  if (meta === true) {
@@ -62,7 +62,8 @@ export class SecrecyCloudClient {
62
62
  else if (!encrypted) {
63
63
  filetype = await fileTypeFromBuffer(dataBuffer);
64
64
  }
65
- if (storageType === 'lite' && dataBuffer.byteLength > kiloToBytes(1024)) {
65
+ if (storage.protocol === 'mongo' &&
66
+ dataBuffer.byteLength > kiloToBytes(1024)) {
66
67
  throw new Error('The data is too big for lite upload!');
67
68
  }
68
69
  const compressed = encrypted ? compress(dataBuffer) : dataBuffer;
@@ -81,11 +82,11 @@ export class SecrecyCloudClient {
81
82
  current: 0,
82
83
  percent: 0,
83
84
  });
84
- if (storageType === 'lite') {
85
+ if (storage.protocol === 'mongo') {
85
86
  const uploadDataArgs = encryptedDataKey && md5Encrypted
86
87
  ? {
87
88
  type: 'encrypted',
88
- content: Buffer.from(encryptedData),
89
+ bytes: Buffer.from(encryptedData),
89
90
  sizeEncrypted: BigInt(encryptedData.byteLength),
90
91
  size: BigInt(dataBuffer.byteLength),
91
92
  key: sodium.to_hex(encryptedDataKey),
@@ -95,13 +96,13 @@ export class SecrecyCloudClient {
95
96
  }
96
97
  : {
97
98
  type: 'unencrypted',
98
- content: Buffer.from(encryptedData),
99
+ bytes: Buffer.from(encryptedData),
99
100
  md5: md5Data,
100
101
  sizeEncrypted: undefined,
101
102
  size: BigInt(dataBuffer.byteLength),
102
103
  ...filetype,
103
104
  };
104
- const uploadData = await this.#apiClient.cloud.uploadLiteData.mutate(uploadDataArgs, { signal });
105
+ const uploadData = await this.#apiClient.cloud.uploadMongoData.mutate(uploadDataArgs, { signal });
105
106
  await uploadProgress?.({
106
107
  total: encryptedData.byteLength,
107
108
  current: encryptedData.byteLength,
@@ -109,7 +110,7 @@ export class SecrecyCloudClient {
109
110
  });
110
111
  const localData = {
111
112
  id: uploadData.id,
112
- storageType: 'lite',
113
+ storage: storage,
113
114
  size: uploadDataArgs.size,
114
115
  sizeEncrypted: uploadDataArgs.sizeEncrypted ?? null,
115
116
  data: dataBuffer,
@@ -118,7 +119,7 @@ export class SecrecyCloudClient {
118
119
  dataContentCache.set(uploadData.id, localData);
119
120
  return localData;
120
121
  }
121
- if (storageType === 's3' || storageType === 'cold') {
122
+ if (storage.protocol === 's3') {
122
123
  const uploadDataArgs = encryptedDataKey && md5Encrypted
123
124
  ? {
124
125
  type: 'encrypted',
@@ -136,7 +137,7 @@ export class SecrecyCloudClient {
136
137
  sizeEncrypted: undefined,
137
138
  ...filetype,
138
139
  };
139
- const uploadDataCaller = storageType === 's3'
140
+ const uploadDataCaller = storage.protocol === 's3'
140
141
  ? this.#apiClient.cloud.uploadData
141
142
  : this.#apiClient.cloud.uploadColdData;
142
143
  const uploadData = await uploadDataCaller.mutate(uploadDataArgs, {
@@ -153,7 +154,7 @@ export class SecrecyCloudClient {
153
154
  });
154
155
  const localData = {
155
156
  id: uploadData.id,
156
- storageType: storageType,
157
+ storage: storage,
157
158
  size: uploadDataArgs.size,
158
159
  sizeEncrypted: uploadDataArgs.sizeEncrypted ?? null,
159
160
  data: dataBuffer,
@@ -210,7 +211,7 @@ export class SecrecyCloudClient {
210
211
  }));
211
212
  const localData = {
212
213
  id: uploadData.id,
213
- storageType: storageType,
214
+ storage: storage,
214
215
  size: uploadDataArgs.size,
215
216
  sizeEncrypted: uploadDataArgs.sizeEncrypted ?? null,
216
217
  data: dataBuffer,
@@ -219,11 +220,11 @@ export class SecrecyCloudClient {
219
220
  dataContentCache.set(uploadData.id, localData);
220
221
  return localData;
221
222
  }
222
- throw new Error(`The "${storageType}" is not implemented yet!`);
223
+ throw new Error(`Not implemented yet!`);
223
224
  }
224
- async uploadDataInCloud({ data, name, nodeId, encryptProgress, uploadProgress, storageType = 's3', signal, }) {
225
+ async uploadDataInCloud({ data, name, nodeId, encryptProgress, uploadProgress, storage, signal, }) {
225
226
  const uploadedData = await this.uploadData({
226
- storageType,
227
+ storage,
227
228
  data,
228
229
  encryptProgress,
229
230
  uploadProgress,
@@ -397,13 +398,13 @@ export class SecrecyCloudClient {
397
398
  id: data.id,
398
399
  size: data.size,
399
400
  sizeEncrypted: data.sizeEncrypted,
400
- storageType: data.storageType,
401
+ storage: data.storage,
401
402
  })),
402
403
  ...cachedData.map((data) => ({
403
404
  id: data.id,
404
405
  size: data.size,
405
406
  sizeEncrypted: data.sizeEncrypted,
406
- storageType: data.storageType,
407
+ storage: data.storage,
407
408
  })),
408
409
  ];
409
410
  const allDataContentsBytes = Number(allDataContents.reduce((curr, next) => curr + (next.sizeEncrypted ?? next.size), 0n));
@@ -532,15 +533,16 @@ export class SecrecyCloudClient {
532
533
  }
533
534
  perNode = async (nodeId, publicKey) => {
534
535
  let node = nodesCache.get(nodeId);
535
- if (node === undefined || !('history' in node)) {
536
+ if (node === undefined || (node.type === 'FILE' && !('history' in node))) {
536
537
  await this.node({ id: nodeId });
537
538
  node = nodesCache.get(nodeId);
538
539
  if (node === undefined) {
539
540
  return null;
540
541
  }
541
542
  }
542
- if (!('history' in node) || node.history.length === 0) {
543
- throw new Error("Can't share a node whitout data!");
543
+ if (node.type === 'FILE' &&
544
+ (!('history' in node) || node.history.length === 0)) {
545
+ throw new Error("Can't share a node without data!");
544
546
  }
545
547
  const nameKey = node.access?.nameKey;
546
548
  return {
@@ -572,13 +574,18 @@ export class SecrecyCloudClient {
572
574
  : null,
573
575
  });
574
576
  }
575
- async updateDataStorageType(input) {
577
+ async updateDataStorage(input) {
576
578
  const data = dataContentCache.get(input.dataId);
577
579
  if (data) {
578
- if (data.storageType === input.storageType) {
579
- throw new Error(`The data is already on "${data.storageType}`);
580
+ if (data.storage.protocol === input.protocol &&
581
+ data.storage.provider === input.provider &&
582
+ data.storage.mode === input.mode &&
583
+ data.storage.region === input.region) {
584
+ throw new Error(`The data is already on "${data.storage}`);
580
585
  }
581
- if (data.storageType === 'cold' && input.storageType === 'lite') {
586
+ if (data.storage.protocol === 's3' &&
587
+ data.storage.mode === 'glacier' &&
588
+ input.protocol === 'mongo') {
582
589
  throw new Error("It's not possible to transfer a cold stored data to a lite storage!");
583
590
  }
584
591
  }
@@ -640,19 +647,25 @@ export class SecrecyCloudClient {
640
647
  .sort((a, b) => a.order - b.order)
641
648
  .map((p) => p.data));
642
649
  };
643
- const encryptedContent = dataContent.type === 'lite'
644
- ? new Uint8Array(dataContent.content)
645
- : dataContent.type === 'cloud'
650
+ const encryptedContent = dataContent.type === 'mongo'
651
+ ? new Uint8Array(dataContent.bytes)
652
+ : dataContent.type === 's3'
646
653
  ? await encryptedContentFromParts({
647
654
  dataId: dataContent.id,
648
- dataParts: dataContent.parts,
655
+ dataParts: dataContent.parts.map(({ url, ...part }) => ({
656
+ ...part,
657
+ contentUrl: url,
658
+ })),
649
659
  })
650
- : dataContent.maybeContent !== null
651
- ? new Uint8Array(dataContent.maybeContent)
660
+ : dataContent.maybeBytes !== null
661
+ ? new Uint8Array(dataContent.maybeBytes)
652
662
  : dataContent.maybeParts !== null
653
663
  ? await encryptedContentFromParts({
654
664
  dataId: dataContent.id,
655
- dataParts: dataContent.maybeParts,
665
+ dataParts: dataContent.maybeParts.map(({ url, ...part }) => ({
666
+ ...part,
667
+ contentUrl: url,
668
+ })),
656
669
  })
657
670
  : null;
658
671
  if (encryptedContent === null) {
@@ -665,7 +678,7 @@ export class SecrecyCloudClient {
665
678
  const key = dataContent.key
666
679
  ? decryptCryptoBox(sodium.from_hex(dataContent.key), dataContent.type === 'received_mail'
667
680
  ? dataContent.senderPublicKey
668
- : dataContent.type === 'cloud'
681
+ : dataContent.type === 's3'
669
682
  ? dataContent.publicKey
670
683
  : this.#keys.publicKey, this.#keys.privateKey)
671
684
  : null;
@@ -677,11 +690,20 @@ export class SecrecyCloudClient {
677
690
  throw new Error(`Content does not match`);
678
691
  }
679
692
  const decompressed = decompress(src);
693
+ const storageOptions = dataContent.storage.protocol === 'mongo'
694
+ ? dataContent.storage.mongoStorageOptions
695
+ : dataContent.storage.s3StorageOptions;
696
+ const storage = {
697
+ protocol: dataContent.storage.protocol,
698
+ provider: dataContent.storage.provider,
699
+ mode: storageOptions.mode,
700
+ region: storageOptions.region,
701
+ };
680
702
  dataContentCache.set(dataContent.id, {
681
703
  id: dataContent.id,
682
704
  size: dataContent.size,
683
705
  sizeEncrypted: dataContent.sizeEncrypted,
684
- storageType: dataContent.storageType,
706
+ storage: storage,
685
707
  data: decompressed,
686
708
  mime: dataContent.mime ?? undefined,
687
709
  ext: dataContent.ext ?? undefined,
@@ -690,7 +712,7 @@ export class SecrecyCloudClient {
690
712
  id: dataContent.id,
691
713
  size: dataContent.size,
692
714
  sizeEncrypted: dataContent.sizeEncrypted,
693
- storageType: dataContent.storageType,
715
+ storage: storage,
694
716
  data: decompressed,
695
717
  mime: dataContent.mime ?? undefined,
696
718
  ext: dataContent.ext ?? undefined,
@@ -1,5 +1,5 @@
1
1
  import type { ProgressCallback, SecrecyClient } from '../index.js';
2
- import type { DataMetadata, DataStorageType, KeyPair, LocalData, Node, NodeFull, NodeType, Rights } from './types/index.js';
2
+ import type { DataMetadata, DataStorageInput, KeyPair, LocalData, Node, NodeFull, NodeType, Rights } from './types/index.js';
3
3
  import { type RouterInputs, type ApiClient, type RouterOutputs } from '../client.js';
4
4
  import { type DownloadProgress } from '../types.js';
5
5
  import { FileTypeResult } from 'file-type';
@@ -10,8 +10,8 @@ export declare class SecrecyCloudClient {
10
10
  dataId: string;
11
11
  nodeId: string;
12
12
  }): Promise<NodeFull>;
13
- uploadData({ storageType, data, encrypted, encryptProgress, uploadProgress, signal, meta, }: {
14
- storageType: DataStorageType;
13
+ uploadData({ storage, data, encrypted, encryptProgress, uploadProgress, signal, meta, }: {
14
+ storage: DataStorageInput;
15
15
  data: globalThis.File | Uint8Array;
16
16
  encrypted?: boolean;
17
17
  encryptProgress?: ProgressCallback;
@@ -19,14 +19,14 @@ export declare class SecrecyCloudClient {
19
19
  signal?: AbortSignal;
20
20
  meta?: FileTypeResult | true;
21
21
  }): Promise<LocalData>;
22
- uploadDataInCloud({ data, name, nodeId, encryptProgress, uploadProgress, storageType, signal, }: {
22
+ uploadDataInCloud({ data, name, nodeId, encryptProgress, uploadProgress, storage, signal, }: {
23
23
  data: globalThis.File | Uint8Array;
24
24
  name: string;
25
25
  nodeId?: string;
26
26
  encryptProgress?: ProgressCallback;
27
27
  uploadProgress?: ProgressCallback;
28
28
  signal?: AbortSignal;
29
- storageType?: DataStorageType;
29
+ storage: DataStorageInput;
30
30
  }): Promise<NodeFull>;
31
31
  deletedNodes(): Promise<Node[]>;
32
32
  sharedNodes(): Promise<Node[]>;
@@ -102,10 +102,14 @@ export declare class SecrecyCloudClient {
102
102
  }): Promise<NodeFull>;
103
103
  private readonly perNode;
104
104
  reportData({ id, reasons, }: Omit<RouterInputs['cloud']['reportData'], 'encryptedDataKey'>): Promise<RouterOutputs['cloud']['reportData']>;
105
- updateDataStorageType(input: RouterInputs['cloud']['moveToStorageType']): Promise<{
105
+ updateDataStorage(input: RouterInputs['cloud']['moveToStorageType']): Promise<{
106
106
  isMoved: boolean;
107
- fromType: "s3" | "cold" | "lite";
108
- toType: "s3" | "cold" | "lite";
107
+ fromProtocol?: "s3" | "mongo" | undefined;
108
+ fromMode?: "standard" | "glacier" | undefined;
109
+ fromRegion?: string | undefined;
110
+ toProtocol?: "s3" | "mongo" | undefined;
111
+ toMode?: "standard" | "glacier" | undefined;
112
+ toRegion?: string | undefined;
109
113
  }>;
110
114
  getPublicDataLink(input: RouterInputs['cloud']['dataLink']): Promise<{
111
115
  name: string;
@@ -1,10 +1,23 @@
1
1
  import { type RouterOutputs } from '../../client.js';
2
2
  export type ApiData = NonNullable<RouterOutputs['cloud']['dataById']>;
3
- export type ApiExtendedData = NonNullable<RouterOutputs['cloud']['dataContentByIds'][number]>;
4
- export type DataStorageType = ApiData['storageType'];
3
+ export type ApiExtendedData = NonNullable<RouterOutputs['cloud']['dataContentById']>;
4
+ export type DataStorageInput = {
5
+ protocol: 's3';
6
+ provider: 'scaleway' | 'ovh';
7
+ mode: 'standard' | 'glacier';
8
+ region: string;
9
+ } | {
10
+ protocol: 'mongo';
11
+ provider: 'secrecy';
12
+ mode: 'standard';
13
+ region: string;
14
+ };
15
+ export type DataStorage = ApiData['storage'];
16
+ export type DataStorageProtocol = ApiData['storage']['protocol'];
17
+ export type DataStorageProvider = ApiData['storage']['provider'];
5
18
  export type LocalData = {
6
19
  id: string;
7
- storageType: DataStorageType;
20
+ storage: DataStorageInput;
8
21
  size: bigint;
9
22
  sizeEncrypted: bigint | null;
10
23
  data: Uint8Array;