bedrock-ts-sdk 0.0.4 → 0.0.6

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/README.md CHANGED
@@ -34,7 +34,7 @@ const client = await BedrockClient.fromPrivateKey('0x...');
34
34
  // Upload a file
35
35
  const files = await client.files.uploadFiles([{
36
36
  name: 'hello.txt',
37
- path: 'documents/hello.txt',
37
+ path: '/documents/hello.txt',
38
38
  content: Buffer.from('Hello, Bedrock!'),
39
39
  }]);
40
40
 
@@ -74,7 +74,7 @@ const buffer = Buffer.from(await file.arrayBuffer());
74
74
 
75
75
  await client.files.uploadFiles([{
76
76
  name: file.name,
77
- path: `uploads/${file.name}`,
77
+ path: `/uploads/${file.name}`,
78
78
  content: buffer,
79
79
  }]);
80
80
  ```
@@ -121,17 +121,30 @@ const client = await BedrockClient.fromSignature(
121
121
  const files = await client.files.uploadFiles([
122
122
  {
123
123
  name: 'document.pdf',
124
- path: 'documents/document.pdf',
124
+ path: '/documents/document.pdf',
125
125
  content: fileBuffer, // Buffer or File
126
126
  },
127
127
  {
128
128
  name: 'image.jpg',
129
- path: 'images/image.jpg',
129
+ path: '/images/image.jpg',
130
130
  content: imageBuffer,
131
131
  },
132
132
  ]);
133
133
  ```
134
134
 
135
+ #### Edit Files
136
+
137
+ ```typescript
138
+ const [file] = await client.files.uploadFiles([
139
+ {
140
+ name: 'document.txt',
141
+ path: '/documents/document.txt',
142
+ content: fileBuffer, // Buffer or File
143
+ },
144
+ ]);
145
+
146
+ const editedFile = await client.files.editFileContent(file, editedFileBuffer);
147
+ ```
135
148
  #### List Files
136
149
 
137
150
  ```typescript
package/dist/index.d.mts CHANGED
@@ -661,7 +661,7 @@ interface FileInput {
661
661
  * File service for managing encrypted files
662
662
  */
663
663
  declare class FileService {
664
- private core;
664
+ private readonly core;
665
665
  constructor(core: BedrockCore);
666
666
  /**
667
667
  * Initialize file entries aggregate if it doesn't exist
@@ -674,6 +674,7 @@ declare class FileService {
674
674
  * @returns Array of uploaded file info
675
675
  */
676
676
  uploadFiles(files: FileInput[], directoryPath?: string): Promise<FileFullInfo[]>;
677
+ editFileContent(fileInfo: FileFullInfo, newContent: Buffer): Promise<FileFullInfo>;
677
678
  /**
678
679
  * Download and decrypt a file
679
680
  * @param fileInfo - File information
package/dist/index.d.ts CHANGED
@@ -661,7 +661,7 @@ interface FileInput {
661
661
  * File service for managing encrypted files
662
662
  */
663
663
  declare class FileService {
664
- private core;
664
+ private readonly core;
665
665
  constructor(core: BedrockCore);
666
666
  /**
667
667
  * Initialize file entries aggregate if it doesn't exist
@@ -674,6 +674,7 @@ declare class FileService {
674
674
  * @returns Array of uploaded file info
675
675
  */
676
676
  uploadFiles(files: FileInput[], directoryPath?: string): Promise<FileFullInfo[]>;
677
+ editFileContent(fileInfo: FileFullInfo, newContent: Buffer): Promise<FileFullInfo>;
677
678
  /**
678
679
  * Download and decrypt a file
679
680
  * @param fileInfo - File information
package/dist/index.js CHANGED
@@ -943,8 +943,16 @@ var FileService = class {
943
943
  const aleph = this.core.getAlephService();
944
944
  const publicKey = this.core.getPublicKey();
945
945
  const uploadedFiles = [];
946
+ const existingFiles = await this.listFiles();
947
+ const filesToUpload = files.filter((file) => {
948
+ const filterIn = !existingFiles.some(
949
+ (existingFile) => !existingFile.deleted_at && existingFile.path === (directoryPath ? `${directoryPath}${file.path}` : file.path)
950
+ );
951
+ console.log(`Keeping ${file} in ? ${filterIn ? "yes" : "no"}`);
952
+ return filterIn;
953
+ });
946
954
  try {
947
- for (const file of files) {
955
+ for (const file of filesToUpload) {
948
956
  const key = EncryptionService.generateKey();
949
957
  const iv = EncryptionService.generateIv();
950
958
  let fileBuffer;
@@ -985,6 +993,39 @@ var FileService = class {
985
993
  throw new FileError(`Failed to upload files: ${error.message}`);
986
994
  }
987
995
  }
996
+ async editFileContent(fileInfo, newContent) {
997
+ const aleph = this.core.getAlephService();
998
+ const privateKey = this.core.getSubAccountPrivateKey();
999
+ try {
1000
+ const postResult = await aleph.updatePost(
1001
+ POST_TYPES.FILE,
1002
+ fileInfo.post_hash,
1003
+ [aleph.getAddress()],
1004
+ FileMetaEncryptedSchema,
1005
+ async (encryptedMeta) => {
1006
+ const decryptedMeta = await this.decryptFileMeta(encryptedMeta);
1007
+ const encryptedContent = await EncryptionService.encryptFile(
1008
+ newContent,
1009
+ Buffer.from(decryptedMeta.key, "hex"),
1010
+ Buffer.from(decryptedMeta.iv, "hex")
1011
+ );
1012
+ const uploadResult = await aleph.uploadFile(encryptedContent);
1013
+ decryptedMeta.store_hash = uploadResult.item_hash;
1014
+ fileInfo.store_hash = decryptedMeta.store_hash;
1015
+ return await this.encryptFileMeta(decryptedMeta);
1016
+ }
1017
+ );
1018
+ fileInfo.post_hash = postResult.item_hash;
1019
+ await aleph.updateAggregate(AGGREGATE_KEYS.FILE_ENTRIES, FileEntriesAggregateSchema, async (aggregate) => ({
1020
+ files: aggregate.files.map(
1021
+ (entry) => fileInfo.path === EncryptionService.decryptEcies(entry.path, privateKey) ? { ...entry, post_hash: fileInfo.post_hash } : entry
1022
+ )
1023
+ }));
1024
+ return fileInfo;
1025
+ } catch (error) {
1026
+ throw new FileError(`Failed to edit file's content: ${error.message}`);
1027
+ }
1028
+ }
988
1029
  /**
989
1030
  * Download and decrypt a file
990
1031
  * @param fileInfo - File information
@@ -1087,10 +1128,10 @@ var FileService = class {
1087
1128
  try {
1088
1129
  for (const path of filePaths) {
1089
1130
  const file = await this.getFile(path);
1090
- await aleph.updatePost(
1131
+ const updatedPost = await aleph.updatePost(
1091
1132
  POST_TYPES.FILE,
1092
1133
  file.post_hash,
1093
- [this.core.getMainAddress()],
1134
+ [aleph.getAddress()],
1094
1135
  FileMetaEncryptedSchema,
1095
1136
  async (encryptedMeta) => {
1096
1137
  const decryptedMeta = await this.decryptFileMeta(encryptedMeta);
@@ -1098,6 +1139,11 @@ var FileService = class {
1098
1139
  return await this.encryptFileMeta(decryptedMeta);
1099
1140
  }
1100
1141
  );
1142
+ await aleph.updateAggregate(AGGREGATE_KEYS.FILE_ENTRIES, FileEntriesAggregateSchema, async (aggregate) => ({
1143
+ files: aggregate.files.map(
1144
+ (entry) => entry.post_hash === file.post_hash ? { ...entry, post_hash: updatedPost.item_hash } : entry
1145
+ )
1146
+ }));
1101
1147
  }
1102
1148
  } catch (error) {
1103
1149
  throw new FileError(`Failed to soft delete files: ${error.message}`);
@@ -1112,10 +1158,10 @@ var FileService = class {
1112
1158
  try {
1113
1159
  for (const path of filePaths) {
1114
1160
  const file = await this.getFile(path);
1115
- await aleph.updatePost(
1161
+ const updatedPost = await aleph.updatePost(
1116
1162
  POST_TYPES.FILE,
1117
1163
  file.post_hash,
1118
- [this.core.getMainAddress()],
1164
+ [aleph.getAddress()],
1119
1165
  FileMetaEncryptedSchema,
1120
1166
  async (encryptedMeta) => {
1121
1167
  const decryptedMeta = await this.decryptFileMeta(encryptedMeta);
@@ -1123,6 +1169,11 @@ var FileService = class {
1123
1169
  return await this.encryptFileMeta(decryptedMeta);
1124
1170
  }
1125
1171
  );
1172
+ await aleph.updateAggregate(AGGREGATE_KEYS.FILE_ENTRIES, FileEntriesAggregateSchema, async (aggregate) => ({
1173
+ files: aggregate.files.map(
1174
+ (entry) => entry.post_hash === file.post_hash ? { ...entry, post_hash: updatedPost.item_hash } : entry
1175
+ )
1176
+ }));
1126
1177
  }
1127
1178
  } catch (error) {
1128
1179
  throw new FileError(`Failed to restore files: ${error.message}`);
@@ -1155,10 +1206,10 @@ var FileService = class {
1155
1206
  try {
1156
1207
  for (const { oldPath, newPath } of moves) {
1157
1208
  const file = await this.getFile(oldPath);
1158
- await aleph.updatePost(
1209
+ const updatedPost = await aleph.updatePost(
1159
1210
  POST_TYPES.FILE,
1160
1211
  file.post_hash,
1161
- [this.core.getMainAddress()],
1212
+ [aleph.getAddress()],
1162
1213
  FileMetaEncryptedSchema,
1163
1214
  async (encryptedMeta) => {
1164
1215
  const decryptedMeta = await this.decryptFileMeta(encryptedMeta);
@@ -1170,7 +1221,7 @@ var FileService = class {
1170
1221
  const newEncryptedPath = EncryptionService.encryptEcies(newPath, publicKey);
1171
1222
  await aleph.updateAggregate(AGGREGATE_KEYS.FILE_ENTRIES, FileEntriesAggregateSchema, async (aggregate) => ({
1172
1223
  files: aggregate.files.map(
1173
- (entry) => entry.post_hash === file.post_hash ? { ...entry, path: newEncryptedPath } : entry
1224
+ (entry) => entry.post_hash === file.post_hash ? { ...entry, path: newEncryptedPath, post_hash: updatedPost.item_hash } : entry
1174
1225
  )
1175
1226
  }));
1176
1227
  }
@@ -1210,10 +1261,10 @@ var FileService = class {
1210
1261
  const file = await this.getFile(filePath);
1211
1262
  const encryptedKey = EncryptionService.encryptEcies(file.key, contactPublicKey);
1212
1263
  const encryptedIv = EncryptionService.encryptEcies(file.iv, contactPublicKey);
1213
- await aleph.updatePost(
1264
+ const updatedPost = await aleph.updatePost(
1214
1265
  POST_TYPES.FILE,
1215
1266
  file.post_hash,
1216
- [this.core.getMainAddress()],
1267
+ [aleph.getAddress()],
1217
1268
  FileMetaEncryptedSchema,
1218
1269
  async (encryptedMeta) => {
1219
1270
  const decryptedMeta = await this.decryptFileMeta(encryptedMeta);
@@ -1226,7 +1277,11 @@ var FileService = class {
1226
1277
  );
1227
1278
  await aleph.updateAggregate(AGGREGATE_KEYS.FILE_ENTRIES, FileEntriesAggregateSchema, async (aggregate) => ({
1228
1279
  files: aggregate.files.map(
1229
- (entry) => entry.post_hash === file.post_hash ? { ...entry, shared_with: [.../* @__PURE__ */ new Set([...entry.shared_with, contactPublicKey])] } : entry
1280
+ (entry) => entry.post_hash === file.post_hash ? {
1281
+ ...entry,
1282
+ post_hash: updatedPost.item_hash,
1283
+ shared_with: [.../* @__PURE__ */ new Set([...entry.shared_with, contactPublicKey])]
1284
+ } : entry
1230
1285
  )
1231
1286
  }));
1232
1287
  } catch (error) {
@@ -1242,10 +1297,10 @@ var FileService = class {
1242
1297
  const aleph = this.core.getAlephService();
1243
1298
  try {
1244
1299
  const file = await this.getFile(filePath);
1245
- await aleph.updatePost(
1300
+ const updatedPost = await aleph.updatePost(
1246
1301
  POST_TYPES.FILE,
1247
1302
  file.post_hash,
1248
- [this.core.getMainAddress()],
1303
+ [aleph.getAddress()],
1249
1304
  FileMetaEncryptedSchema,
1250
1305
  async (encryptedMeta) => {
1251
1306
  const decryptedMeta = await this.decryptFileMeta(encryptedMeta);
@@ -1255,7 +1310,11 @@ var FileService = class {
1255
1310
  );
1256
1311
  await aleph.updateAggregate(AGGREGATE_KEYS.FILE_ENTRIES, FileEntriesAggregateSchema, async (aggregate) => ({
1257
1312
  files: aggregate.files.map(
1258
- (entry) => entry.post_hash === file.post_hash ? { ...entry, shared_with: entry.shared_with.filter((pk) => pk !== contactPublicKey) } : entry
1313
+ (entry) => entry.post_hash === file.post_hash ? {
1314
+ ...entry,
1315
+ post_hash: updatedPost.item_hash,
1316
+ shared_with: entry.shared_with.filter((pk) => pk !== contactPublicKey)
1317
+ } : entry
1259
1318
  )
1260
1319
  }));
1261
1320
  } catch (error) {