@dignetwork/dig-sdk 0.0.1-alpha.15 → 0.0.1-alpha.17
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/DataIntegrityTree/DataIntegrityTree.d.ts +1 -1
- package/dist/DataIntegrityTree/DataIntegrityTree.d.ts.map +1 -1
- package/dist/DataIntegrityTree/DataIntegrityTree.js +40 -48
- package/dist/utils/directoryUtils.d.ts.map +1 -1
- package/dist/utils/directoryUtils.js +9 -12
- package/package.json +1 -1
|
@@ -106,7 +106,7 @@ declare class DataIntegrityTree {
|
|
|
106
106
|
* @param rootHash - The root hash of the tree. Defaults to the latest root hash.
|
|
107
107
|
* @returns The readable stream for the file.
|
|
108
108
|
*/
|
|
109
|
-
getValueStream(hexKey: string, rootHash?: string | null): Readable;
|
|
109
|
+
getValueStream(hexKey: string, rootHash?: string | null, byteOffset?: number | null, length?: number | null): Readable;
|
|
110
110
|
/**
|
|
111
111
|
* Delete all leaves from the Merkle tree.
|
|
112
112
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataIntegrityTree.d.ts","sourceRoot":"","sources":["../../src/DataIntegrityTree/DataIntegrityTree.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAuClC,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAGlB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;GAEG;AACH,cAAM,iBAAiB;IACrB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAS;IACjB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5D,OAAO,CAAC,IAAI,CAAa;gBAEb,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,wBAA6B;WAiDrD,IAAI,
|
|
1
|
+
{"version":3,"file":"DataIntegrityTree.d.ts","sourceRoot":"","sources":["../../src/DataIntegrityTree/DataIntegrityTree.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAuClC,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAGlB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;GAEG;AACH,cAAM,iBAAiB;IACrB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAS;IACjB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5D,OAAO,CAAC,IAAI,CAAa;gBAEb,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,wBAA6B;WAiDrD,IAAI,CAChB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,wBAAwB,GAChC,iBAAiB;IAOpB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAQrB;;;OAGG;IACH,OAAO,CAAC,eAAe;IAUvB;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IAa1B;;;;OAIG;YACW,WAAW;IAazB;;;;;OAKG;IACG,SAAS,CAAC,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqFjE;;;OAGG;IACH,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAW5B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,GAAE,MAAM,GAAG,IAAW,GAAG,MAAM,EAAE;IAalD;;;OAGG;IACH,OAAO,CAAC,YAAY;IAOpB;;;;OAIG;IACH,OAAO,IAAI,MAAM;IAIjB;;;;OAIG;IACH,SAAS,CAAC,QAAQ,GAAE,MAAM,GAAG,IAAW,GAAG,MAAM;IAqBjD;;;;OAIG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU;IAwB7C,OAAO,CAAC,wBAAwB;IAuBhC;;OAEG;IACH,MAAM,IAAI,MAAM,GAAG,SAAS;IAoC5B;;OAEG;IACH,gBAAgB,IAAI,IAAI;IAIxB;;;;;OAKG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,GAAG,IAAW,GAAG,OAAO;IA+B/D;;;;;OAKG;IACH,cAAc,CACZ,MAAM,EAAE,MAAM,EACd,QAAQ,GAAE,MAAM,GAAG,IAAW,EAC9B,UAAU,GAAE,MAAM,GAAG,IAAW,EAChC,MAAM,GAAE,MAAM,GAAG,IAAW,GAC3B,QAAQ;IA4DX;;OAEG;IACH,eAAe,IAAI,IAAI;IAKvB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAUhE;;;;;;OAMG;IACH,QAAQ,CACN,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,QAAQ,GAAE,MAAM,GAAG,IAAW,GAC7B,MAAM;IAsCT;;;;;OAKG;IACH,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IA4B5D;;;;;OAKG;IACH,WAAW,CACT,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB;QAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE;IA+B/D;;;;;OAKG;IACG,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA0D5E;;;;;;;;;OASG;IACH,MAAM,CAAC,mCAAmC,CACxC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM,EACtB,gBAAgB,EAAE,MAAM,GACvB,OAAO;CAgDX;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -111,7 +111,10 @@ class DataIntegrityTree {
|
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
static from(storeId, options) {
|
|
114
|
-
return new DataIntegrityTree(storeId, {
|
|
114
|
+
return new DataIntegrityTree(storeId, {
|
|
115
|
+
...options,
|
|
116
|
+
disableInitialize: true,
|
|
117
|
+
});
|
|
115
118
|
}
|
|
116
119
|
/**
|
|
117
120
|
* Load the manifest file.
|
|
@@ -188,81 +191,54 @@ class DataIntegrityTree {
|
|
|
188
191
|
const tempFilePath = path.join(tempDir, `${crypto.randomUUID()}.gz`);
|
|
189
192
|
return new Promise((resolve, reject) => {
|
|
190
193
|
const tempWriteStream = fs.createWriteStream(tempFilePath);
|
|
191
|
-
// Update the hash with the original data
|
|
192
194
|
readStream.on("data", (chunk) => {
|
|
193
195
|
uncompressedHash.update(chunk);
|
|
194
196
|
});
|
|
195
|
-
// Pipe the read stream through gzip into the temporary write stream
|
|
196
197
|
readStream.pipe(gzip).pipe(tempWriteStream);
|
|
197
198
|
tempWriteStream.on("finish", async () => {
|
|
198
|
-
|
|
199
|
+
sha256 = uncompressedHash.digest("hex");
|
|
200
|
+
const finalWriteStream = this._createWriteStream(sha256);
|
|
201
|
+
const finalPath = finalWriteStream.path;
|
|
202
|
+
// Ensure the directory exists before copying the file
|
|
203
|
+
const finalDir = path.dirname(finalPath);
|
|
204
|
+
if (!fs.existsSync(finalDir)) {
|
|
205
|
+
fs.mkdirSync(finalDir, { recursive: true });
|
|
206
|
+
}
|
|
199
207
|
try {
|
|
200
|
-
sha256 = uncompressedHash.digest("hex");
|
|
201
|
-
finalWriteStream = this._createWriteStream(sha256);
|
|
202
|
-
const finalPath = finalWriteStream.path;
|
|
203
|
-
// Ensure the directory exists
|
|
204
|
-
const finalDir = path.dirname(finalPath);
|
|
205
|
-
if (!fs.existsSync(finalDir)) {
|
|
206
|
-
fs.mkdirSync(finalDir, { recursive: true });
|
|
207
|
-
}
|
|
208
|
-
// Copy the temporary gzipped file to the final destination
|
|
209
208
|
await this._streamFile(tempFilePath, finalPath);
|
|
210
|
-
await unlink(tempFilePath);
|
|
209
|
+
await unlink(tempFilePath);
|
|
211
210
|
const combinedHash = crypto
|
|
212
211
|
.createHash("sha256")
|
|
213
212
|
.update(`${key}/${sha256}`)
|
|
214
213
|
.digest("hex");
|
|
215
|
-
// Check if the key already exists with the same hash
|
|
216
214
|
if (Array.from(this.files.values()).some((file) => file.hash === combinedHash)) {
|
|
217
215
|
console.log(`No changes detected for key: ${key}`);
|
|
218
216
|
return resolve();
|
|
219
217
|
}
|
|
220
|
-
// Delete existing key if present
|
|
221
218
|
if (this.files.has(key)) {
|
|
222
219
|
this.deleteKey(key);
|
|
223
220
|
}
|
|
224
|
-
// Insert the new key with the hash
|
|
225
221
|
console.log(`Inserted key: ${key}`);
|
|
226
222
|
this.files.set(key, {
|
|
227
223
|
hash: combinedHash,
|
|
228
224
|
sha256: sha256,
|
|
229
225
|
});
|
|
226
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
230
227
|
this._rebuildTree();
|
|
228
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
231
229
|
resolve();
|
|
232
230
|
}
|
|
233
231
|
catch (err) {
|
|
234
|
-
// On error, cleanup the temporary file and reject
|
|
235
|
-
await unlink(tempFilePath).catch(() => { });
|
|
236
232
|
reject(err);
|
|
237
233
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
if (finalWriteStream) {
|
|
241
|
-
finalWriteStream.end();
|
|
242
|
-
}
|
|
243
|
-
}
|
|
234
|
+
tempWriteStream.end();
|
|
235
|
+
finalWriteStream.end();
|
|
244
236
|
});
|
|
245
|
-
tempWriteStream.on("error",
|
|
246
|
-
|
|
247
|
-
tempWriteStream.destroy();
|
|
248
|
-
gzip.destroy();
|
|
249
|
-
readStream.destroy();
|
|
250
|
-
await unlink(tempFilePath).catch(() => { }); // Clean up the temp file
|
|
237
|
+
tempWriteStream.on("error", (err) => {
|
|
238
|
+
tempWriteStream.end();
|
|
251
239
|
reject(err);
|
|
252
240
|
});
|
|
253
|
-
readStream.on("error",
|
|
254
|
-
// Close streams and clean up in case of error
|
|
255
|
-
tempWriteStream.destroy();
|
|
256
|
-
gzip.destroy();
|
|
257
|
-
readStream.destroy();
|
|
258
|
-
await unlink(tempFilePath).catch(() => { }); // Clean up the temp file
|
|
259
|
-
reject(err);
|
|
260
|
-
});
|
|
261
|
-
gzip.on("error", (err) => {
|
|
262
|
-
// Handle errors in the gzip stream
|
|
263
|
-
tempWriteStream.destroy();
|
|
264
|
-
gzip.destroy();
|
|
265
|
-
readStream.destroy();
|
|
241
|
+
readStream.on("error", (err) => {
|
|
266
242
|
reject(err);
|
|
267
243
|
});
|
|
268
244
|
});
|
|
@@ -369,7 +345,9 @@ class DataIntegrityTree {
|
|
|
369
345
|
? fs.readFileSync(manifestPath, "utf-8").trim().split("\n")
|
|
370
346
|
: [];
|
|
371
347
|
// Check if the last entry is the same as the rootHash to avoid duplicates
|
|
372
|
-
const latestRootHash = manifestContent.length > 0
|
|
348
|
+
const latestRootHash = manifestContent.length > 0
|
|
349
|
+
? manifestContent[manifestContent.length - 1]
|
|
350
|
+
: null;
|
|
373
351
|
if (latestRootHash !== rootHash) {
|
|
374
352
|
// Append the new rootHash if it is not the same as the last one
|
|
375
353
|
fs.appendFileSync(manifestPath, `${rootHash}\n`);
|
|
@@ -445,7 +423,7 @@ class DataIntegrityTree {
|
|
|
445
423
|
* @param rootHash - The root hash of the tree. Defaults to the latest root hash.
|
|
446
424
|
* @returns The readable stream for the file.
|
|
447
425
|
*/
|
|
448
|
-
getValueStream(hexKey, rootHash = null) {
|
|
426
|
+
getValueStream(hexKey, rootHash = null, byteOffset = null, length = null) {
|
|
449
427
|
if (!isHexString(hexKey)) {
|
|
450
428
|
throw new Error("key must be a valid hex string");
|
|
451
429
|
}
|
|
@@ -468,8 +446,22 @@ class DataIntegrityTree {
|
|
|
468
446
|
if (!fs.existsSync(filePath)) {
|
|
469
447
|
throw new Error(`File at path ${filePath} does not exist`);
|
|
470
448
|
}
|
|
471
|
-
|
|
472
|
-
|
|
449
|
+
const fileSize = fs.statSync(filePath).size;
|
|
450
|
+
// Validate offset and length
|
|
451
|
+
if (byteOffset !== null && length !== null) {
|
|
452
|
+
if (byteOffset + length > fileSize) {
|
|
453
|
+
throw new Error(`Offset (${byteOffset}) and length (${length}) exceed the file size (${fileSize}).`);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
// Create the read stream with optional byte range
|
|
457
|
+
const options = {};
|
|
458
|
+
if (byteOffset !== null) {
|
|
459
|
+
options.start = byteOffset;
|
|
460
|
+
}
|
|
461
|
+
if (length !== null && byteOffset !== null) {
|
|
462
|
+
options.end = byteOffset + length - 1; // `end` is inclusive, hence `byteOffset + length - 1`
|
|
463
|
+
}
|
|
464
|
+
const readStream = fs.createReadStream(filePath, options);
|
|
473
465
|
const decompressStream = zlib.createGunzip();
|
|
474
466
|
// Return the combined stream as a generic Readable stream
|
|
475
467
|
return readStream.pipe(decompressStream);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"directoryUtils.d.ts","sourceRoot":"","sources":["../../src/utils/directoryUtils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"directoryUtils.d.ts","sourceRoot":"","sources":["../../src/utils/directoryUtils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AA+BzD,eAAO,MAAM,YAAY,cACZ,iBAAiB,WACnB,MAAM,YACN,MAAM,KACd,OAAO,CAAC,IAAI,CA4Cd,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,eAAgB,MAAM,KAAG,MAiBxD,CAAC"}
|
|
@@ -32,22 +32,23 @@ const fs = __importStar(require("fs"));
|
|
|
32
32
|
const ignore_1 = __importDefault(require("ignore"));
|
|
33
33
|
// Custom concurrency handler
|
|
34
34
|
const limitConcurrency = async (concurrencyLimit, tasks) => {
|
|
35
|
-
const results = [];
|
|
36
35
|
const executing = [];
|
|
37
36
|
for (const task of tasks) {
|
|
38
37
|
const p = task();
|
|
39
|
-
|
|
38
|
+
// Add the new task to the executing array
|
|
39
|
+
executing.push(p);
|
|
40
|
+
// When a task completes, remove it from the executing array
|
|
41
|
+
const cleanup = p.finally(() => {
|
|
42
|
+
executing.splice(executing.indexOf(cleanup), 1);
|
|
43
|
+
});
|
|
40
44
|
// Once the limit is reached, wait for one to complete
|
|
41
45
|
if (executing.length >= concurrencyLimit) {
|
|
46
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
42
47
|
await Promise.race(executing);
|
|
43
48
|
}
|
|
44
|
-
// Add the new task to the executing array
|
|
45
|
-
executing.push(p);
|
|
46
|
-
// When a task completes, remove it from the executing array
|
|
47
|
-
p.finally(() => executing.splice(executing.indexOf(p), 1));
|
|
48
49
|
}
|
|
49
50
|
// Wait for all remaining tasks to complete
|
|
50
|
-
return Promise.all(
|
|
51
|
+
return Promise.all(executing);
|
|
51
52
|
};
|
|
52
53
|
const addDirectory = async (datalayer, dirPath, baseDir = dirPath) => {
|
|
53
54
|
const ig = (0, ignore_1.default)();
|
|
@@ -77,14 +78,10 @@ const addDirectory = async (datalayer, dirPath, baseDir = dirPath) => {
|
|
|
77
78
|
const stream = fs.createReadStream(filePath);
|
|
78
79
|
datalayer
|
|
79
80
|
.upsertKey(stream, Buffer.from(relativePath).toString("hex"))
|
|
80
|
-
.then(
|
|
81
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
82
|
-
resolve();
|
|
83
|
-
})
|
|
81
|
+
.then(() => resolve())
|
|
84
82
|
.catch(reject);
|
|
85
83
|
}));
|
|
86
84
|
}
|
|
87
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
88
85
|
}
|
|
89
86
|
// Run tasks with limited concurrency (set the concurrency limit as needed)
|
|
90
87
|
await limitConcurrency(10, tasks); // Adjust 10 based on your system limits
|