@secrecy/lib 1.29.0-feat-manage-user-data.2 → 1.29.0-feat-rename-file.3

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/lib/cache.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { LRUCache } from 'lru-cache';
2
2
  import { gigaToBytes } from './utils.js';
3
- export const filesCache = new Map();
3
+ export const dataCache = new Map();
4
4
  export const nodesCache = new Map();
5
5
  export const usersCache = new Map();
6
6
  export const publicKeysCache = new Map();
7
- export const dataCache = new LRUCache({
7
+ export const lruCache = new LRUCache({
8
8
  max: 500,
9
9
  maxSize: gigaToBytes(0.5),
10
10
  sizeCalculation: (value) => {
@@ -82,8 +82,8 @@ export class SecrecyAppClient {
82
82
  async updateSettings(settings) {
83
83
  const updateAppSettings = await this.#apiClient.application.updateSettings.mutate({
84
84
  cloudNodeDaysForDelete: settings.cloudNodeDaysForDelete,
85
- historyFileDaysForDelete: settings.historyFileDaysForDelete,
86
- historyMaxFileCount: settings.historyMaxFileCount,
85
+ historyFileDaysForDelete: settings.historyDataDaysForDelete,
86
+ historyMaxFileCount: settings.historyDataMaxCount,
87
87
  });
88
88
  return updateAppSettings;
89
89
  }
@@ -1,15 +1,15 @@
1
1
  import axios from 'axios';
2
2
  import ky from 'ky';
3
3
  import { encryptName } from '../index.js';
4
- import { nodesCache, filesCache, dataCache } from '../cache.js';
5
- import { secretStreamKeygen } from '../crypto/file.js';
4
+ import { nodesCache, dataCache, lruCache } from '../cache.js';
5
+ import { secretStreamKeygen } from '../crypto/data.js';
6
6
  import { decryptCryptoBox, encryptCryptoBox } from '../crypto/index.js';
7
7
  import { compress, decompress } from '../minify/index.js';
8
8
  import { sodium } from '../sodium.js';
9
9
  import { enumerate, chunks, concatenate } from '../utils/array.js';
10
10
  import { md5 } from '../worker/md5.js';
11
11
  import { decrypt, encrypt } from '../worker/sodium.js';
12
- import { apiFileToExternal } from './convert/file.js';
12
+ import { apiDataToExternal } from './convert/data.js';
13
13
  import { apiNodeFullToInternalFull, apiNodeToExternal, apiNodeToExternalNodeFull, internalNodeFullToNodeFull, } from './convert/node.js';
14
14
  import { promiseAllLimit } from '../utils/promise.js';
15
15
  // import { md5 } from "../worker/index.js";
@@ -23,71 +23,71 @@ export class SecrecyCloudClient {
23
23
  this.#keys = keys;
24
24
  this.#apiClient = apiClient;
25
25
  }
26
- async addFileToHistory({ fileId, nodeId, }) {
27
- const addFileToHistory = await this.#apiClient.cloud.addFileToHistory.mutate({
28
- fileId,
26
+ async addDataToHistory({ dataId, nodeId, }) {
27
+ const addDataToHistory = await this.#apiClient.cloud.addDataToHistory.mutate({
28
+ dataId,
29
29
  nodeId,
30
30
  });
31
- const node = await apiNodeFullToInternalFull(addFileToHistory, this.#keys);
32
- const file = node.history.find((f) => f.id === fileId);
33
- if (file !== undefined) {
31
+ const node = await apiNodeFullToInternalFull(addDataToHistory, this.#keys);
32
+ const data = node.history.find((f) => f.id === dataId);
33
+ if (data !== undefined) {
34
34
  const users = node.users.filter(([u]) => u.id !== this.#client.app.userId);
35
- await this.#apiClient.cloud.shareFileInHistory.mutate({
36
- fileId: file.id,
35
+ await this.#apiClient.cloud.shareDataInHistory.mutate({
36
+ dataId: data.id,
37
37
  nodeId,
38
38
  users: await Promise.all(users.map(async ([u]) => {
39
39
  const userPubKey = await this.#client.app.userPublicKey(u.id);
40
40
  return {
41
41
  id: u.id,
42
- key: sodium.to_hex(encryptCryptoBox(sodium.from_hex(file.key), userPubKey, this.#keys.privateKey)),
42
+ key: sodium.to_hex(encryptCryptoBox(sodium.from_hex(data.key), userPubKey, this.#keys.privateKey)),
43
43
  };
44
44
  })),
45
45
  });
46
46
  }
47
47
  return internalNodeFullToNodeFull(node);
48
48
  }
49
- async uploadFile({ file, encryptProgress, uploadProgress, signal, }) {
50
- const fileKey = secretStreamKeygen();
51
- const fileBuffer = file instanceof File ? new Uint8Array(await file.arrayBuffer()) : file;
52
- const compressed = compress(fileBuffer);
53
- const { data: encryptedFile, md5: md5File, md5Encrypted, } = await encrypt(fileKey, compressed, encryptProgress, signal);
54
- const encryptedFileKey = encryptCryptoBox(fileKey, this.#keys.publicKey, this.#keys.privateKey);
55
- const uploadFile = await this.#apiClient.cloud.uploadFile.mutate({
56
- fileSize: BigInt(encryptedFile.byteLength),
57
- fileSizeBefore: BigInt(fileBuffer.byteLength),
58
- fileKey: sodium.to_hex(encryptedFileKey),
49
+ async uploadData({ data, encryptProgress, uploadProgress, signal, }) {
50
+ const dataKey = secretStreamKeygen();
51
+ const dataBuffer = data instanceof File ? new Uint8Array(await data.arrayBuffer()) : data;
52
+ const compressed = compress(dataBuffer);
53
+ const { data: encryptedData, md5: md5Data, md5Encrypted, } = await encrypt(dataKey, compressed, encryptProgress, signal);
54
+ const encryptedDataKey = encryptCryptoBox(dataKey, this.#keys.publicKey, this.#keys.privateKey);
55
+ const uploadData = await this.#apiClient.cloud.uploadData.mutate({
56
+ dataSize: BigInt(encryptedData.byteLength),
57
+ dataSizeBefore: BigInt(dataBuffer.byteLength),
58
+ dataKey: sodium.to_hex(encryptedDataKey),
59
59
  md5Encrypted,
60
- md5: md5File,
60
+ md5: md5Data,
61
61
  });
62
62
  await uploadProgress?.({
63
- total: encryptedFile.byteLength,
63
+ total: encryptedData.byteLength,
64
64
  current: 0,
65
65
  percent: 0,
66
66
  });
67
- if (uploadFile.parts.length === 0) {
67
+ if (uploadData.parts.length === 0) {
68
68
  await uploadProgress?.({
69
- total: encryptedFile.byteLength,
70
- current: encryptedFile.byteLength,
69
+ total: encryptedData.byteLength,
70
+ current: encryptedData.byteLength,
71
71
  percent: 1,
72
72
  });
73
- return uploadFile.fileId;
73
+ return uploadData.dataId;
74
74
  }
75
75
  const uploadPartEnded = async (md5, order) => {
76
- const { isUploadPartEnded } = await this.#apiClient.cloud.uploadFilePartEnd.mutate({
77
- fileId: uploadFile.fileId,
76
+ const { isUploadPartEnded } = await this.#apiClient.cloud.uploadDataPartEnd.mutate({
77
+ dataId: uploadData.dataId,
78
78
  md5,
79
79
  order,
80
80
  });
81
81
  return isUploadPartEnded;
82
82
  };
83
83
  const uploadEnded = async () => {
84
- const { isUploadEnded } = await this.#apiClient.cloud.uploadFileEnd.mutate({
85
- fileId: uploadFile.fileId,
84
+ const { isUploadEnded } = await this.#apiClient.cloud.uploadDataEnd.mutate({
85
+ dataId: uploadData.dataId,
86
86
  });
87
87
  return isUploadEnded;
88
88
  };
89
89
  const chunkParts = new Array();
90
- for (const [index, chunk] of enumerate(chunks(encryptedFile, Number(uploadFile.filePartSize)))) {
90
+ for (const [index, chunk] of enumerate(chunks(encryptedData, Number(uploadData.dataPartSize)))) {
91
91
  chunkParts.push({
92
92
  order: index + 1,
93
93
  data: chunk,
@@ -99,8 +99,8 @@ export class SecrecyCloudClient {
99
99
  progressParts[part] = progressEvent;
100
100
  const current = Object.values(progressParts).reduce((prv, cur) => prv + cur.loaded, 0);
101
101
  void uploadProgress?.({
102
- percent: current / encryptedFile.byteLength,
103
- total: encryptedFile.byteLength,
102
+ percent: current / encryptedData.byteLength,
103
+ total: encryptedData.byteLength,
104
104
  current,
105
105
  });
106
106
  };
@@ -113,7 +113,7 @@ export class SecrecyCloudClient {
113
113
  for (const [key, value] of Object.entries(part.fields)) {
114
114
  formData.append(key, value);
115
115
  }
116
- formData.append('file', new Blob([chunk.data]), `${uploadFile.fileId}-${chunk.order}`);
116
+ formData.append('data', new Blob([chunk.data]), `${uploadData.dataId}-${chunk.order}`);
117
117
  await axios.post(part.url, formData, {
118
118
  onUploadProgress: (progressEvent) => {
119
119
  onProgress(part.order, progressEvent);
@@ -122,22 +122,22 @@ export class SecrecyCloudClient {
122
122
  });
123
123
  await uploadPartEnded(chunk.md5, chunk.order);
124
124
  };
125
- await promiseAllLimit(3, uploadFile.parts.map((p) => async () => {
125
+ await promiseAllLimit(3, uploadData.parts.map((p) => async () => {
126
126
  await byPart(p);
127
127
  }));
128
128
  await uploadEnded();
129
- dataCache.set(uploadFile.fileId, fileBuffer);
130
- return uploadFile.fileId;
129
+ lruCache.set(uploadData.dataId, dataBuffer);
130
+ return uploadData.dataId;
131
131
  }
132
- async uploadFileInCloud({ file, name, nodeId, encryptProgress, uploadProgress, signal, }) {
133
- const fileId = await this.uploadFile({
134
- file,
132
+ async uploadDataInCloud({ data, name, nodeId, encryptProgress, uploadProgress, signal, }) {
133
+ const dataId = await this.uploadData({
134
+ data,
135
135
  encryptProgress,
136
136
  uploadProgress,
137
137
  signal,
138
138
  });
139
139
  return await this.saveInCloud({
140
- fileId,
140
+ dataId,
141
141
  name,
142
142
  nodeId,
143
143
  });
@@ -220,11 +220,11 @@ export class SecrecyCloudClient {
220
220
  });
221
221
  return await apiNodeToExternalNodeFull(node, this.#keys);
222
222
  }
223
- async fileMetadata({ id }) {
224
- const file = await this.#apiClient.cloud.fileById.query({
223
+ async dataMetadata({ id }) {
224
+ const data = await this.#apiClient.cloud.dataById.query({
225
225
  id,
226
226
  });
227
- return apiFileToExternal(file, this.#keys);
227
+ return apiDataToExternal(data, this.#keys);
228
228
  }
229
229
  async shareNode({ nodeId, userId, rights, }) {
230
230
  const publicKey = await this.#client.app.userPublicKey(userId);
@@ -270,26 +270,26 @@ export class SecrecyCloudClient {
270
270
  });
271
271
  return await apiNodeToExternalNodeFull(updateNode, this.#keys);
272
272
  }
273
- async fileContent({ fileId, onDownloadProgress, progressDecrypt, signal, }) {
274
- const cached = dataCache.get(fileId);
273
+ async dataContent({ dataId, onDownloadProgress, progressDecrypt, signal, }) {
274
+ const cached = lruCache.get(dataId);
275
275
  if (cached !== undefined) {
276
276
  return cached;
277
277
  }
278
- const fileContent = await this.#apiClient.cloud.fileContentById.query({
279
- id: fileId,
278
+ const dataContent = await this.#apiClient.cloud.dataContentById.query({
279
+ id: dataId,
280
280
  });
281
281
  const progressParts = {};
282
282
  const onProgress = (part, progressEvent) => {
283
283
  progressParts[part] = progressEvent;
284
284
  const transferredBytes = Object.values(progressParts).reduce((prv, cur) => prv + cur.transferredBytes, 0);
285
- const totalBytes = Number(fileContent.totalSize);
285
+ const totalBytes = Number(dataContent.totalSize);
286
286
  onDownloadProgress?.({
287
287
  percent: transferredBytes / totalBytes,
288
288
  totalBytes,
289
289
  transferredBytes,
290
290
  });
291
291
  };
292
- const encryptedContentFromParts = async (fileParts) => {
292
+ const encryptedContentFromParts = async (dataParts) => {
293
293
  const parts = new Array();
294
294
  const byPart = async (part) => {
295
295
  const buf = new Uint8Array(await ky
@@ -303,14 +303,14 @@ export class SecrecyCloudClient {
303
303
  .arrayBuffer());
304
304
  const md5Part = await md5(buf);
305
305
  if (md5Part !== part.md5) {
306
- throw new Error(`Invalid md5 for part ${part.order} of file ${fileId}`);
306
+ throw new Error(`Invalid md5 for part ${part.order} of data ${dataId}`);
307
307
  }
308
308
  parts.push({
309
309
  data: buf,
310
310
  order: part.order,
311
311
  });
312
312
  };
313
- await promiseAllLimit(3, fileParts.map((p) => async () => {
313
+ await promiseAllLimit(3, dataParts.map((p) => async () => {
314
314
  await byPart(p);
315
315
  }));
316
316
  return concatenate(...parts.sort((a, b) => a.order - b.order).map((p) => p.data));
@@ -318,42 +318,42 @@ export class SecrecyCloudClient {
318
318
  const finalize = async (encryptedContent) => {
319
319
  // const md5Encrypted = await firstValueFrom(md5(of(encryptedContent)));
320
320
  const md5Encrypted = await md5(encryptedContent);
321
- if (md5Encrypted !== fileContent.md5Encrypted) {
321
+ if (md5Encrypted !== dataContent.md5Encrypted) {
322
322
  throw new Error(`Encrypted content does not match`);
323
323
  }
324
- const key = decryptCryptoBox(sodium.from_hex(fileContent.key), fileContent.type === 'received_mail'
325
- ? fileContent.senderPublicKey
326
- : fileContent.type === 'cloud'
327
- ? fileContent.publicKey
324
+ const key = decryptCryptoBox(sodium.from_hex(dataContent.key), dataContent.type === 'received_mail'
325
+ ? dataContent.senderPublicKey
326
+ : dataContent.type === 'cloud'
327
+ ? dataContent.publicKey
328
328
  : this.#keys.publicKey, this.#keys.privateKey);
329
329
  const src = await decrypt(key, encryptedContent, progressDecrypt, signal);
330
330
  // const md5Content = await firstValueFrom(md5(of(src)));
331
331
  const md5Content = await md5(src);
332
- if (md5Content !== fileContent.md5) {
332
+ if (md5Content !== dataContent.md5) {
333
333
  throw new Error(`Content does not match`);
334
334
  }
335
335
  return decompress(src);
336
336
  };
337
- const encryptedContent = fileContent.type === 'lite'
338
- ? fileContent.content
339
- : fileContent.type === 'cloud'
340
- ? await encryptedContentFromParts(fileContent.parts)
337
+ const encryptedContent = dataContent.type === 'lite'
338
+ ? dataContent.content
339
+ : dataContent.type === 'cloud'
340
+ ? await encryptedContentFromParts(dataContent.parts)
341
341
  : // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
342
- fileContent.maybeContent !== null
343
- ? fileContent.maybeContent
344
- : fileContent.maybeParts !== null
345
- ? await encryptedContentFromParts(fileContent.maybeParts)
342
+ dataContent.maybeContent !== null
343
+ ? dataContent.maybeContent
344
+ : dataContent.maybeParts !== null
345
+ ? await encryptedContentFromParts(dataContent.maybeParts)
346
346
  : null;
347
347
  if (encryptedContent === null) {
348
- throw `Can't find content for file ${fileId}`;
348
+ throw `Can't find content for data ${dataId}`;
349
349
  }
350
350
  const data = await finalize(encryptedContent);
351
- dataCache.set(fileId, data);
351
+ lruCache.set(dataId, data);
352
352
  return data;
353
353
  }
354
- async deleteFile({ fileId, nodeId, }) {
355
- const { isDeleted } = await this.#apiClient.cloud.deleteFile.mutate({
356
- fileId,
354
+ async deleteData({ dataId, nodeId, }) {
355
+ const { isDeleted } = await this.#apiClient.cloud.deleteData.mutate({
356
+ dataId,
357
357
  nodeId,
358
358
  });
359
359
  return isDeleted;
@@ -381,7 +381,7 @@ export class SecrecyCloudClient {
381
381
  });
382
382
  return isMoved;
383
383
  }
384
- async saveInCloud({ fileId, name, nodeId, }) {
384
+ async saveInCloud({ dataId, name, nodeId, }) {
385
385
  if (nodeId !== undefined && !nodesCache.has(nodeId)) {
386
386
  await this.node({ id: nodeId });
387
387
  if (!nodesCache.has(nodeId)) {
@@ -394,50 +394,50 @@ export class SecrecyCloudClient {
394
394
  }
395
395
  }
396
396
  let key = '';
397
- const file = filesCache.get(fileId);
398
- if (file === undefined) {
399
- await this.fileMetadata({ id: fileId });
400
- const file = filesCache.get(fileId);
401
- if (file === undefined) {
397
+ const data = dataCache.get(dataId);
398
+ if (data === undefined) {
399
+ await this.dataMetadata({ id: dataId });
400
+ const data = dataCache.get(dataId);
401
+ if (data === undefined) {
402
402
  const receivedMails = await this.#client.mail.receivedMails();
403
- const mail = receivedMails.find((m) => m.files.some((f) => f.id === fileId));
403
+ const mail = receivedMails.find((m) => m.data.some((f) => f.id === dataId));
404
404
  if (mail === undefined) {
405
405
  const err = {
406
406
  name: 'ClientError',
407
407
  code: 'NOT_FOUND',
408
- message: `Can't find mail with the file ${fileId}`,
408
+ message: `Can't find mail with the data ${dataId}`,
409
409
  };
410
410
  throw err;
411
411
  }
412
- const fileMail = mail.files.find((f) => f.id === fileId);
413
- if (fileMail === undefined) {
412
+ const dataMail = mail.data.find((f) => f.id === dataId);
413
+ if (dataMail === undefined) {
414
414
  const err = {
415
415
  name: 'ClientError',
416
416
  code: 'NOT_FOUND',
417
- message: `Can't find mail with the file ${fileId}`,
417
+ message: `Can't find mail with the data ${dataId}`,
418
418
  };
419
419
  throw err;
420
420
  }
421
421
  const senderPubKey = await this.#client.app.userPublicKey(mail.sender.id);
422
- const fileKey = decryptCryptoBox(sodium.from_hex(fileMail.key), senderPubKey, this.#keys.privateKey);
423
- key = sodium.to_hex(fileKey);
422
+ const dataKey = decryptCryptoBox(sodium.from_hex(dataMail.key), senderPubKey, this.#keys.privateKey);
423
+ key = sodium.to_hex(dataKey);
424
424
  }
425
425
  else {
426
- key = file.key;
426
+ key = data.key;
427
427
  }
428
428
  }
429
429
  else {
430
- key = file.key;
430
+ key = data.key;
431
431
  }
432
432
  key = sodium.to_hex(encryptCryptoBox(sodium.from_hex(key), this.#keys.publicKey, this.#keys.privateKey));
433
433
  const nameKey = secretStreamKeygen();
434
434
  const encryptedName = await encryptName(name, sodium.to_hex(nameKey));
435
435
  const encryptedNameKey = sodium.to_hex(encryptCryptoBox(nameKey, this.#keys.publicKey, this.#keys.privateKey));
436
436
  const saveInCloud = await this.#apiClient.cloud.saveInCloud.mutate({
437
- fileId,
437
+ dataId,
438
438
  key,
439
439
  nodeId: nodeId ?? null,
440
- filename: encryptedName,
440
+ fileName: encryptedName,
441
441
  nameKey: encryptedNameKey,
442
442
  });
443
443
  const node = await apiNodeToExternalNodeFull(saveInCloud, this.#keys);
@@ -468,7 +468,7 @@ export class SecrecyCloudClient {
468
468
  nameKey: nameKey !== null
469
469
  ? sodium.to_hex(encryptCryptoBox(sodium.from_hex(nameKey), publicKey, this.#keys.privateKey))
470
470
  : null,
471
- files: 'history' in node
471
+ data: 'history' in node
472
472
  ? node.history.map((f) => ({
473
473
  id: f.id,
474
474
  key: sodium.to_hex(encryptCryptoBox(sodium.from_hex(f.key), publicKey, this.#keys.privateKey)),
@@ -1,4 +1,4 @@
1
- import { filesCache } from '../cache.js';
1
+ import { dataCache } from '../cache.js';
2
2
  import { encryptCryptoBox, sodium } from '../index.js';
3
3
  import { convertInternalMailToExternal } from './convert/mail.js';
4
4
  export class SecrecyMailClient {
@@ -67,11 +67,11 @@ export class SecrecyMailClient {
67
67
  }
68
68
  if (senderFiles !== undefined) {
69
69
  for (const f of senderFiles) {
70
- let file = filesCache.get(f.id);
71
- if (file === undefined) {
72
- await this.#client.cloud.fileMetadata({ id: f.id });
73
- file = filesCache.get(f.id);
74
- if (file === undefined) {
70
+ let data = dataCache.get(f.id);
71
+ if (data === undefined) {
72
+ await this.#client.cloud.dataMetadata({ id: f.id });
73
+ data = dataCache.get(f.id);
74
+ if (data === undefined) {
75
75
  throw new Error(`File ${f.name} (${f.id}) does not exists`);
76
76
  }
77
77
  }
@@ -132,7 +132,7 @@ export class SecrecyMailClient {
132
132
  if (email === undefined) {
133
133
  continue;
134
134
  }
135
- const input = await this._eachUser(draft.files, draft.subject, draft.body, email);
135
+ const input = await this._eachUser(draft.data, draft.subject, draft.body, email);
136
136
  if (input === null) {
137
137
  temporaryRecipients.push(email);
138
138
  }
@@ -141,7 +141,7 @@ export class SecrecyMailClient {
141
141
  }
142
142
  }
143
143
  for (const { id } of draft.recipients) {
144
- const input = await this._eachUser(draft.files, draft.subject, draft.body, id);
144
+ const input = await this._eachUser(draft.data, draft.subject, draft.body, id);
145
145
  if (input === null) {
146
146
  temporaryRecipients.push(id);
147
147
  }
@@ -167,13 +167,20 @@ export class SecrecyMailClient {
167
167
  continue;
168
168
  }
169
169
  try {
170
- const input = await this._eachUser(mail.files, mail.subject, mail.body, email);
170
+ const input = await this._eachUser(mail.data, mail.subject, mail.body, email);
171
171
  if (input === null) {
172
172
  continue;
173
173
  }
174
174
  await this.#apiClient.mail.sendOne.mutate({
175
175
  id: mail.mailIntegrityId,
176
- recipient: input,
176
+ recipient: {
177
+ ...input,
178
+ attachments: input.attachments.map((attachment) => ({
179
+ id: attachment.dataId,
180
+ key: attachment.key,
181
+ name: attachment.name,
182
+ })),
183
+ },
177
184
  });
178
185
  }
179
186
  catch {
@@ -186,16 +193,16 @@ export class SecrecyMailClient {
186
193
  const hashKey = sodium.randombytes_buf(sodium.crypto_generichash_KEYBYTES, 'hex');
187
194
  const hash = sodium.crypto_generichash(sodium.crypto_generichash_BYTES, JSON.stringify({ body, subject }), hashKey, 'hex');
188
195
  for (const f of senderFiles) {
189
- let file = filesCache.get(f.id);
190
- if (file === undefined) {
191
- await this.#client.cloud.fileMetadata({ id: f.id });
192
- file = filesCache.get(f.id);
193
- if (file === undefined) {
196
+ let data = dataCache.get(f.id);
197
+ if (data === undefined) {
198
+ await this.#client.cloud.dataMetadata({ id: f.id });
199
+ data = dataCache.get(f.id);
200
+ if (data === undefined) {
194
201
  throw new Error(`File ${f.name} (${f.id}) does not exists`);
195
202
  }
196
203
  }
197
204
  senderFiles.push({
198
- id: file.id,
205
+ id: data.id,
199
206
  name: sodium.to_hex(encryptCryptoBox(sodium.from_string(f.name), this.#keys.publicKey, this.#keys.privateKey)),
200
207
  });
201
208
  }
@@ -254,25 +261,25 @@ export class SecrecyMailClient {
254
261
  const unreadReceivedMailsCount = await this.#apiClient.mail.unreadReceivedCount.query({});
255
262
  return unreadReceivedMailsCount;
256
263
  }
257
- _eachUser = async (files, subject, body, idOrMail) => {
264
+ _eachUser = async (data, subject, body, idOrMail) => {
258
265
  // const pubKey = await this.#client.app.userPublicKey(userId)
259
266
  const pubKey = await this.#client.app.userPublicKey(idOrMail);
260
- // const recipientsFiles = new Array<MailFileInput>()
261
- const recipientsFiles = new Array();
262
- for (const f of files) {
263
- let fileInHistory = filesCache.get(f.id);
264
- if (fileInHistory === undefined) {
265
- await this.#client.cloud.fileMetadata({ id: f.id });
266
- fileInHistory = filesCache.get(f.id);
267
- if (fileInHistory === undefined) {
267
+ // const attachments = new Array<MailFileInput>()
268
+ const attachments = new Array();
269
+ for (const f of data) {
270
+ let dataInHistory = dataCache.get(f.id);
271
+ if (dataInHistory === undefined) {
272
+ await this.#client.cloud.dataMetadata({ id: f.id });
273
+ dataInHistory = dataCache.get(f.id);
274
+ if (dataInHistory === undefined) {
268
275
  throw new Error(`File ${f.name} (${f.id}) does not exists`);
269
276
  }
270
277
  }
271
- const key = fileInHistory.key;
272
- recipientsFiles.push({
278
+ const key = dataInHistory.key;
279
+ attachments.push({
273
280
  id: f.id,
274
281
  name: sodium.to_hex(encryptCryptoBox(sodium.from_string(f.name), pubKey, this.#keys.privateKey)),
275
- fileKey: sodium.to_hex(encryptCryptoBox(sodium.from_hex(key), pubKey, this.#keys.privateKey)),
282
+ dataKey: sodium.to_hex(encryptCryptoBox(sodium.from_hex(key), pubKey, this.#keys.privateKey)),
276
283
  });
277
284
  }
278
285
  return {
@@ -280,7 +287,7 @@ export class SecrecyMailClient {
280
287
  recipientId: idOrMail,
281
288
  body: sodium.to_hex(encryptCryptoBox(sodium.from_string(body), pubKey, this.#keys.privateKey)),
282
289
  subject: sodium.to_hex(encryptCryptoBox(sodium.from_string(subject), pubKey, this.#keys.privateKey)),
283
- files: recipientsFiles,
290
+ attachments,
284
291
  };
285
292
  };
286
293
  }
@@ -0,0 +1,29 @@
1
+ import { dataCache } from '../../cache.js';
2
+ import { decryptCryptoBox } from '../../crypto/index.js';
3
+ import { sodium } from '../../sodium.js';
4
+ export function apiDataToInternal(apiData, keyPair) {
5
+ const data = {
6
+ id: apiData.id,
7
+ md5: apiData.md5,
8
+ md5Encrypted: apiData.md5Encrypted,
9
+ createdAt: apiData.createdAt,
10
+ size: apiData.size,
11
+ sizeBefore: apiData.sizeBefore,
12
+ key: sodium.to_hex(decryptCryptoBox(sodium.from_hex(apiData.access.key), apiData.access.sharedByPubKey, keyPair.privateKey)),
13
+ };
14
+ dataCache.set(data.id, data);
15
+ return data;
16
+ }
17
+ export function internalDataToExternalData(internal) {
18
+ return {
19
+ id: internal.id,
20
+ md5: internal.md5,
21
+ md5Encrypted: internal.md5Encrypted,
22
+ createdAt: internal.createdAt,
23
+ size: internal.size,
24
+ sizeBefore: internal.sizeBefore,
25
+ };
26
+ }
27
+ export function apiDataToExternal(apiData, keyPair) {
28
+ return internalDataToExternalData(apiDataToInternal(apiData, keyPair));
29
+ }
@@ -30,12 +30,12 @@ export async function convertInternalMailToExternal({ client, mail, keyPair, })
30
30
  temporaryRecipients: [], // TODO
31
31
  recipients: mI.recipients,
32
32
  sender: mail.sender,
33
- files: mail.files.map((f) => {
34
- const name = sodium.to_string(decryptCryptoBox(sodium.from_hex(f.filename), pubKey, privateKey));
33
+ data: mail.attachments.map((f) => {
34
+ const name = sodium.to_string(decryptCryptoBox(sodium.from_hex(f.name), pubKey, privateKey));
35
35
  return {
36
- id: f.fileId,
36
+ id: f.dataId,
37
37
  name,
38
- key: f.fileKey,
38
+ key: f.key,
39
39
  };
40
40
  }),
41
41
  };
@@ -1,8 +1,8 @@
1
1
  import { sodium } from '../../sodium.js';
2
2
  import { decryptCryptoBox } from '../../crypto/index.js';
3
3
  import { nodesCache } from '../../cache.js';
4
- import { decryptSecretStream } from '../../crypto/file.js';
5
- import { apiFileToInternal, internalFileToFile } from './file.js';
4
+ import { decryptSecretStream } from '../../crypto/data.js';
5
+ import { apiDataToInternal, internalDataToExternalData } from './data.js';
6
6
  export async function apiNodeToInternal(apiNode, keyPair) {
7
7
  const internal = {
8
8
  id: apiNode.id,
@@ -23,7 +23,7 @@ export async function apiNodeToInternal(apiNode, keyPair) {
23
23
  deletedAt: apiNode.deletedAt,
24
24
  users: apiNode.users,
25
25
  parentId: apiNode.parentId ?? null,
26
- currentFileId: apiNode.currentFileId ?? null,
26
+ currentDataId: apiNode.currentDataId ?? null,
27
27
  };
28
28
  internal.access = { ...apiNode.access };
29
29
  if (apiNode.access.nameKey !== null) {
@@ -47,13 +47,13 @@ export async function apiNodeFullToInternalFull(apiNodeFull, keyPair) {
47
47
  return {
48
48
  ...f,
49
49
  current: apiNodeFull.current !== null
50
- ? apiFileToInternal(apiNodeFull.current, keyPair)
50
+ ? apiDataToInternal(apiNodeFull.current, keyPair)
51
51
  : undefined,
52
52
  parent: apiNodeFull.parent !== null
53
53
  ? await apiNodeToInternal(apiNodeFull.parent, keyPair)
54
54
  : null,
55
55
  children: await Promise.all(apiNodeFull.children.map(async (s) => await apiNodeToInternal(s, keyPair))),
56
- history: apiNodeFull.history.map((f) => apiFileToInternal(f, keyPair)),
56
+ history: apiNodeFull.history.map((f) => apiDataToInternal(f, keyPair)),
57
57
  };
58
58
  }
59
59
  export function internalNodeToNode(internal) {
@@ -76,9 +76,9 @@ export function internalNodeFullToNodeFull(internal) {
76
76
  ...internalNodeToNode(internal),
77
77
  parent: internal.parent !== null ? internalNodeToNode(internal.parent) : null,
78
78
  children: internal.children.map(internalNodeToNode),
79
- history: internal.history.map((f) => internalFileToFile(f)),
79
+ history: internal.history.map((f) => internalDataToExternalData(f)),
80
80
  current: internal.current !== null && internal.current !== undefined
81
- ? internalFileToFile(internal.current)
81
+ ? internalDataToExternalData(internal.current)
82
82
  : undefined,
83
83
  };
84
84
  }