@dignetwork/dig-sdk 0.0.1-alpha.71 → 0.0.1-alpha.72
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/DigNetwork/DigPeer.js +1 -1
- package/dist/DigNetwork/PropagationServer.d.ts +5 -29
- package/dist/DigNetwork/PropagationServer.d.ts.map +1 -1
- package/dist/DigNetwork/PropagationServer.js +212 -154
- package/dist/blockchain/DataStore.d.ts.map +1 -1
- package/dist/blockchain/DataStore.js +0 -5
- package/dist/utils/asyncPool.d.ts +9 -0
- package/dist/utils/asyncPool.d.ts.map +1 -0
- package/dist/utils/asyncPool.js +23 -0
- package/package.json +3 -2
|
@@ -112,7 +112,7 @@ class DigPeer {
|
|
|
112
112
|
await PropagationServer_1.PropagationServer.downloadStore(this.storeId, rootHash, this.IpAddress);
|
|
113
113
|
}
|
|
114
114
|
async downloadData(dataPath) {
|
|
115
|
-
await this.propagationServer.downloadFile(dataPath);
|
|
115
|
+
await this.propagationServer.downloadFile(dataPath, dataPath);
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
118
|
exports.DigPeer = DigPeer;
|
|
@@ -10,7 +10,6 @@ export declare class PropagationServer {
|
|
|
10
10
|
username: string | undefined;
|
|
11
11
|
password: string | undefined;
|
|
12
12
|
private static readonly port;
|
|
13
|
-
private static multiBar;
|
|
14
13
|
constructor(ipAddress: string, storeId: string);
|
|
15
14
|
/**
|
|
16
15
|
* Initialize the Wallet instance.
|
|
@@ -22,9 +21,6 @@ export declare class PropagationServer {
|
|
|
22
21
|
createHttpsAgent(): https.Agent;
|
|
23
22
|
/**
|
|
24
23
|
* Check if the store and optional root hash exist by making a HEAD request.
|
|
25
|
-
*
|
|
26
|
-
* @param {string} [rootHash] - Optional root hash to check for existence.
|
|
27
|
-
* @returns {Promise<{ storeExists: boolean, rootHashExists: boolean }>} - An object indicating if the store and root hash exist.
|
|
28
24
|
*/
|
|
29
25
|
checkStoreExists(rootHash?: string): Promise<{
|
|
30
26
|
storeExists: boolean;
|
|
@@ -32,14 +28,10 @@ export declare class PropagationServer {
|
|
|
32
28
|
}>;
|
|
33
29
|
/**
|
|
34
30
|
* Start an upload session by sending a POST request with the rootHash.dat file.
|
|
35
|
-
*
|
|
36
|
-
* @param {string} rootHash - The root hash used to name the .dat file.
|
|
37
|
-
* @param {string} datFilePath - The full path to the rootHash.dat file.
|
|
38
31
|
*/
|
|
39
32
|
startUploadSession(rootHash: string): Promise<void>;
|
|
40
33
|
/**
|
|
41
34
|
* Request a nonce for a file by sending a HEAD request to the server.
|
|
42
|
-
* Checks if the file already exists based on the 'x-file-exists' header.
|
|
43
35
|
*/
|
|
44
36
|
getFileNonce(filename: string): Promise<{
|
|
45
37
|
nonce: string;
|
|
@@ -47,36 +39,24 @@ export declare class PropagationServer {
|
|
|
47
39
|
}>;
|
|
48
40
|
/**
|
|
49
41
|
* Upload a file to the server by sending a PUT request.
|
|
50
|
-
* Logs progress using cli-progress
|
|
42
|
+
* Logs progress using a local cli-progress bar.
|
|
51
43
|
*/
|
|
52
|
-
uploadFile(label: string, dataPath: string): Promise<
|
|
44
|
+
uploadFile(label: string, dataPath: string): Promise<void>;
|
|
53
45
|
/**
|
|
54
46
|
* Commit the upload session by sending a POST request to the server.
|
|
55
|
-
* This finalizes the upload and moves files from the temporary session directory to the permanent location.
|
|
56
47
|
*/
|
|
57
48
|
commitUploadSession(): Promise<any>;
|
|
58
49
|
/**
|
|
59
50
|
* Static function to handle the entire upload process for multiple files based on rootHash.
|
|
60
|
-
* @param {string} storeId - The ID of the DataStore.
|
|
61
|
-
* @param {string} rootHash - The root hash used to derive the file set.
|
|
62
|
-
* @param {string} publicKey - The public key of the user.
|
|
63
|
-
* @param {string} ipAddress - The IP address of the server.
|
|
64
51
|
*/
|
|
65
52
|
static uploadStore(storeId: string, rootHash: string, ipAddress: string): Promise<void>;
|
|
66
53
|
/**
|
|
67
54
|
* Fetch a file from the server by sending a GET request and return its content in memory.
|
|
68
|
-
* Logs progress using cli-progress.
|
|
69
|
-
* @param {string} dataPath - The data path of the file to download.
|
|
70
|
-
* @returns {Promise<Buffer>} - The file content in memory as a Buffer.
|
|
55
|
+
* Logs progress using a local cli-progress bar.
|
|
71
56
|
*/
|
|
72
57
|
fetchFile(dataPath: string): Promise<Buffer>;
|
|
73
58
|
/**
|
|
74
59
|
* Get details of a file, including whether it exists and its size.
|
|
75
|
-
* Makes a HEAD request to the server and checks the response headers.
|
|
76
|
-
*
|
|
77
|
-
* @param {string} dataPath - The path of the file within the DataStore.
|
|
78
|
-
* @param {string} rootHash - The root hash associated with the DataStore.
|
|
79
|
-
* @returns {Promise<{ exists: boolean; size: number }>} - An object containing file existence and size information.
|
|
80
60
|
*/
|
|
81
61
|
getFileDetails(dataPath: string, rootHash: string): Promise<{
|
|
82
62
|
exists: boolean;
|
|
@@ -84,15 +64,11 @@ export declare class PropagationServer {
|
|
|
84
64
|
}>;
|
|
85
65
|
/**
|
|
86
66
|
* Download a file from the server by sending a GET request.
|
|
87
|
-
* Logs progress using cli-progress.
|
|
88
|
-
* @param {string} dataPath - The data path of the file to download.
|
|
67
|
+
* Logs progress using a local cli-progress bar.
|
|
89
68
|
*/
|
|
90
|
-
downloadFile(dataPath: string): Promise<void>;
|
|
69
|
+
downloadFile(label: string, dataPath: string): Promise<void>;
|
|
91
70
|
/**
|
|
92
71
|
* Static function to handle downloading multiple files from a DataStore based on file paths.
|
|
93
|
-
* @param {string} storeId - The ID of the DataStore.
|
|
94
|
-
* @param {string[]} dataPaths - The list of data paths to download.
|
|
95
|
-
* @param {string} ipAddress - The IP address of the server.
|
|
96
72
|
*/
|
|
97
73
|
static downloadStore(storeId: string, rootHash: string, ipAddress: string): Promise<void>;
|
|
98
74
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PropagationServer.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/PropagationServer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PropagationServer.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/PropagationServer.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,MAAM,OAAO,CAAC;AAoB1B,qBAAa,iBAAiB;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,GAAG,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAE7B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAQ;gBAExB,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAY9C;;OAEG;IACG,gBAAgB;IAOtB;;OAEG;IACH,gBAAgB;IAQhB;;OAEG;IACG,gBAAgB,CACpB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,WAAW,EAAE,OAAO,CAAC;QAAC,cAAc,EAAE,OAAO,CAAA;KAAE,CAAC;IAwC7D;;OAEG;IACG,kBAAkB,CAAC,QAAQ,EAAE,MAAM;IAiDzC;;OAEG;IACG,YAAY,CAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE,CAAC;IAyBlD;;;OAGG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAyFhD;;OAEG;IACG,mBAAmB;IAgCzB;;OAEG;WACU,WAAW,CACtB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM;IA4DnB;;;OAGG;IACG,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAwElD;;OAEG;IACG,cAAc,CAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IA0B7C;;;OAGG;IACG,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IA6ElD;;OAEG;WACU,aAAa,CACxB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM;CAuDpB"}
|
|
@@ -1,9 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
27
|
};
|
|
5
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
29
|
exports.PropagationServer = void 0;
|
|
30
|
+
// Import necessary modules and dependencies
|
|
7
31
|
const axios_1 = __importDefault(require("axios"));
|
|
8
32
|
const fs_1 = __importDefault(require("fs"));
|
|
9
33
|
const path_1 = __importDefault(require("path"));
|
|
@@ -13,24 +37,26 @@ const ssl_1 = require("../utils/ssl");
|
|
|
13
37
|
const credentialsUtils_1 = require("../utils/credentialsUtils");
|
|
14
38
|
const https_1 = __importDefault(require("https"));
|
|
15
39
|
const cli_progress_1 = __importDefault(require("cli-progress"));
|
|
16
|
-
const colorette_1 = require("colorette");
|
|
40
|
+
const colorette_1 = require("colorette");
|
|
17
41
|
const config_1 = require("../utils/config");
|
|
18
42
|
const hashUtils_1 = require("../utils/hashUtils");
|
|
19
43
|
const nanospinner_1 = require("nanospinner");
|
|
44
|
+
const progress_stream_1 = __importDefault(require("progress-stream"));
|
|
20
45
|
// Helper function to trim long filenames with ellipsis and ensure consistent padding
|
|
21
46
|
function formatFilename(filename, maxLength = 30) {
|
|
47
|
+
if (!filename) {
|
|
48
|
+
return "Unknown File".padEnd(maxLength, " ");
|
|
49
|
+
}
|
|
22
50
|
if (filename.length > maxLength) {
|
|
23
|
-
// Trim the filename and add ellipsis
|
|
24
51
|
return `...${filename.slice(-(maxLength - 3))}`.padEnd(maxLength, " ");
|
|
25
52
|
}
|
|
26
|
-
// For shorter filenames, just pad to the maxLength
|
|
27
53
|
return filename.padEnd(maxLength, " ");
|
|
28
54
|
}
|
|
29
55
|
class PropagationServer {
|
|
30
56
|
constructor(ipAddress, storeId) {
|
|
31
57
|
this.storeId = storeId;
|
|
32
|
-
this.sessionId = "";
|
|
33
|
-
this.publicKey = "";
|
|
58
|
+
this.sessionId = "";
|
|
59
|
+
this.publicKey = "";
|
|
34
60
|
this.ipAddress = ipAddress;
|
|
35
61
|
// Get or create SSL certificates
|
|
36
62
|
const { certPath, keyPath } = (0, ssl_1.getOrCreateSSLCerts)();
|
|
@@ -42,7 +68,7 @@ class PropagationServer {
|
|
|
42
68
|
*/
|
|
43
69
|
async initializeWallet() {
|
|
44
70
|
this.wallet = await blockchain_1.Wallet.load("default");
|
|
45
|
-
this.publicKey = await this.wallet.getPublicSyntheticKey().toString("hex");
|
|
71
|
+
this.publicKey = (await this.wallet.getPublicSyntheticKey()).toString("hex");
|
|
46
72
|
}
|
|
47
73
|
/**
|
|
48
74
|
* Create an Axios HTTPS Agent with self-signed certificate allowance.
|
|
@@ -51,14 +77,11 @@ class PropagationServer {
|
|
|
51
77
|
return new https_1.default.Agent({
|
|
52
78
|
cert: fs_1.default.readFileSync(this.certPath),
|
|
53
79
|
key: fs_1.default.readFileSync(this.keyPath),
|
|
54
|
-
rejectUnauthorized: false,
|
|
80
|
+
rejectUnauthorized: false,
|
|
55
81
|
});
|
|
56
82
|
}
|
|
57
83
|
/**
|
|
58
84
|
* Check if the store and optional root hash exist by making a HEAD request.
|
|
59
|
-
*
|
|
60
|
-
* @param {string} [rootHash] - Optional root hash to check for existence.
|
|
61
|
-
* @returns {Promise<{ storeExists: boolean, rootHashExists: boolean }>} - An object indicating if the store and root hash exist.
|
|
62
85
|
*/
|
|
63
86
|
async checkStoreExists(rootHash) {
|
|
64
87
|
const spinner = (0, nanospinner_1.createSpinner)(`Checking if store ${this.storeId} exists...`).start();
|
|
@@ -94,9 +117,6 @@ class PropagationServer {
|
|
|
94
117
|
}
|
|
95
118
|
/**
|
|
96
119
|
* Start an upload session by sending a POST request with the rootHash.dat file.
|
|
97
|
-
*
|
|
98
|
-
* @param {string} rootHash - The root hash used to name the .dat file.
|
|
99
|
-
* @param {string} datFilePath - The full path to the rootHash.dat file.
|
|
100
120
|
*/
|
|
101
121
|
async startUploadSession(rootHash) {
|
|
102
122
|
const spinner = (0, nanospinner_1.createSpinner)(`Starting upload session for store ${this.storeId}...`).start();
|
|
@@ -138,7 +158,6 @@ class PropagationServer {
|
|
|
138
158
|
}
|
|
139
159
|
/**
|
|
140
160
|
* Request a nonce for a file by sending a HEAD request to the server.
|
|
141
|
-
* Checks if the file already exists based on the 'x-file-exists' header.
|
|
142
161
|
*/
|
|
143
162
|
async getFileNonce(filename) {
|
|
144
163
|
try {
|
|
@@ -160,7 +179,7 @@ class PropagationServer {
|
|
|
160
179
|
}
|
|
161
180
|
/**
|
|
162
181
|
* Upload a file to the server by sending a PUT request.
|
|
163
|
-
* Logs progress using cli-progress
|
|
182
|
+
* Logs progress using a local cli-progress bar.
|
|
164
183
|
*/
|
|
165
184
|
async uploadFile(label, dataPath) {
|
|
166
185
|
const filePath = path_1.default.join(config_1.STORE_PATH, this.storeId, dataPath);
|
|
@@ -172,48 +191,70 @@ class PropagationServer {
|
|
|
172
191
|
const wallet = await blockchain_1.Wallet.load("default");
|
|
173
192
|
const keyOwnershipSig = await wallet.createKeyOwnershipSignature(nonce);
|
|
174
193
|
const publicKey = await wallet.getPublicSyntheticKey();
|
|
175
|
-
|
|
176
|
-
formData.append("file", fs_1.default.createReadStream(filePath));
|
|
194
|
+
// Get the file size
|
|
177
195
|
const fileSize = fs_1.default.statSync(filePath).size;
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
196
|
+
let progressBar;
|
|
197
|
+
try {
|
|
198
|
+
// Create a new progress bar for the file
|
|
199
|
+
progressBar = new cli_progress_1.default.SingleBar({
|
|
200
|
+
format: `${(0, colorette_1.blue)('[{bar}]')} | ${(0, colorette_1.yellow)('{filename}')} | {percentage}% | {value}/{total} bytes`,
|
|
201
|
+
hideCursor: true,
|
|
202
|
+
barsize: 30,
|
|
203
|
+
align: "left",
|
|
204
|
+
autopadding: true,
|
|
205
|
+
noTTYOutput: false,
|
|
206
|
+
stopOnComplete: true,
|
|
207
|
+
clearOnComplete: false,
|
|
208
|
+
}, cli_progress_1.default.Presets.legacy);
|
|
209
|
+
progressBar.start(fileSize, 0, {
|
|
210
|
+
filename: formatFilename(path_1.default.basename(label)),
|
|
211
|
+
});
|
|
212
|
+
// Create a progress stream
|
|
213
|
+
const progressStream = (0, progress_stream_1.default)({
|
|
214
|
+
length: fileSize,
|
|
215
|
+
time: 500, // Adjust as needed
|
|
216
|
+
});
|
|
217
|
+
progressStream.on("progress", (progress) => {
|
|
218
|
+
progressBar.update(progress.transferred);
|
|
219
|
+
});
|
|
220
|
+
// Create a read stream and pipe it through the progress stream
|
|
221
|
+
const fileReadStream = fs_1.default
|
|
222
|
+
.createReadStream(filePath)
|
|
223
|
+
.pipe(progressStream);
|
|
224
|
+
// Use form-data to construct the request body
|
|
225
|
+
const formData = new form_data_1.default();
|
|
226
|
+
formData.append("file", fileReadStream);
|
|
227
|
+
const headers = {
|
|
228
|
+
...formData.getHeaders(),
|
|
187
229
|
"x-nonce": nonce,
|
|
188
230
|
"x-public-key": publicKey.toString("hex"),
|
|
189
231
|
"x-key-ownership-sig": keyOwnershipSig,
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
progressBar.update(uploadedBytes, { percentage });
|
|
198
|
-
},
|
|
199
|
-
};
|
|
200
|
-
try {
|
|
232
|
+
};
|
|
233
|
+
const config = {
|
|
234
|
+
headers: headers,
|
|
235
|
+
httpsAgent: this.createHttpsAgent(),
|
|
236
|
+
maxContentLength: Infinity,
|
|
237
|
+
maxBodyLength: Infinity,
|
|
238
|
+
};
|
|
201
239
|
const url = `https://${this.ipAddress}:${PropagationServer.port}/upload/${this.storeId}/${this.sessionId}/${dataPath}`;
|
|
202
240
|
const response = await axios_1.default.put(url, formData, config);
|
|
203
|
-
//
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
241
|
+
// Wait for the progress stream to finish
|
|
242
|
+
await new Promise((resolve, reject) => {
|
|
243
|
+
progressStream.on("end", resolve);
|
|
244
|
+
progressStream.on("error", reject);
|
|
245
|
+
});
|
|
207
246
|
}
|
|
208
247
|
catch (error) {
|
|
209
|
-
console.error((0, colorette_1.red)(`✖ Error uploading file ${label}:`), error.message);
|
|
210
|
-
progressBar.stop(); // Stop the progress bar in case of error
|
|
211
248
|
throw error;
|
|
212
249
|
}
|
|
250
|
+
finally {
|
|
251
|
+
if (progressBar) {
|
|
252
|
+
progressBar.stop();
|
|
253
|
+
}
|
|
254
|
+
}
|
|
213
255
|
}
|
|
214
256
|
/**
|
|
215
257
|
* Commit the upload session by sending a POST request to the server.
|
|
216
|
-
* This finalizes the upload and moves files from the temporary session directory to the permanent location.
|
|
217
258
|
*/
|
|
218
259
|
async commitUploadSession() {
|
|
219
260
|
const spinner = (0, nanospinner_1.createSpinner)(`Committing upload session for store ${this.storeId}...`).start();
|
|
@@ -242,10 +283,6 @@ class PropagationServer {
|
|
|
242
283
|
}
|
|
243
284
|
/**
|
|
244
285
|
* Static function to handle the entire upload process for multiple files based on rootHash.
|
|
245
|
-
* @param {string} storeId - The ID of the DataStore.
|
|
246
|
-
* @param {string} rootHash - The root hash used to derive the file set.
|
|
247
|
-
* @param {string} publicKey - The public key of the user.
|
|
248
|
-
* @param {string} ipAddress - The IP address of the server.
|
|
249
286
|
*/
|
|
250
287
|
static async uploadStore(storeId, rootHash, ipAddress) {
|
|
251
288
|
const propagationServer = new PropagationServer(ipAddress, storeId);
|
|
@@ -268,67 +305,92 @@ class PropagationServer {
|
|
|
268
305
|
await propagationServer.startUploadSession(rootHash);
|
|
269
306
|
const dataStore = blockchain_1.DataStore.from(storeId);
|
|
270
307
|
const files = await dataStore.getFileSetForRootHash(rootHash);
|
|
271
|
-
//
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
308
|
+
// Prepare upload tasks
|
|
309
|
+
const uploadTasks = files.map((file) => ({
|
|
310
|
+
label: file.name,
|
|
311
|
+
dataPath: file.path,
|
|
312
|
+
}));
|
|
313
|
+
// Limit the number of concurrent uploads
|
|
314
|
+
const concurrencyLimit = 3; // Adjust this number as needed
|
|
315
|
+
// Import asyncPool from your utilities
|
|
316
|
+
const { asyncPool } = await Promise.resolve().then(() => __importStar(require("../utils/asyncPool")));
|
|
317
|
+
await asyncPool(concurrencyLimit, uploadTasks, async (task) => {
|
|
318
|
+
await propagationServer.uploadFile(task.label, task.dataPath);
|
|
319
|
+
});
|
|
275
320
|
// Commit the session after all files have been uploaded
|
|
276
321
|
await propagationServer.commitUploadSession();
|
|
277
322
|
console.log((0, colorette_1.green)(`✔ All files have been uploaded to DataStore ${storeId}.`));
|
|
278
323
|
}
|
|
279
324
|
/**
|
|
280
325
|
* Fetch a file from the server by sending a GET request and return its content in memory.
|
|
281
|
-
* Logs progress using cli-progress.
|
|
282
|
-
* @param {string} dataPath - The data path of the file to download.
|
|
283
|
-
* @returns {Promise<Buffer>} - The file content in memory as a Buffer.
|
|
326
|
+
* Logs progress using a local cli-progress bar.
|
|
284
327
|
*/
|
|
285
328
|
async fetchFile(dataPath) {
|
|
329
|
+
const url = `https://${this.ipAddress}:${PropagationServer.port}/fetch/${this.storeId}/${dataPath}`;
|
|
286
330
|
const config = {
|
|
287
|
-
responseType: "
|
|
331
|
+
responseType: "stream",
|
|
288
332
|
httpsAgent: this.createHttpsAgent(),
|
|
289
|
-
onDownloadProgress: (progressEvent) => {
|
|
290
|
-
const totalLength = progressEvent.total || 0;
|
|
291
|
-
const downloadedBytes = progressEvent.loaded;
|
|
292
|
-
// Update progress bar
|
|
293
|
-
const progressBar = PropagationServer.multiBar.create(totalLength, 0, {
|
|
294
|
-
dataPath: (0, colorette_1.yellow)(dataPath),
|
|
295
|
-
percentage: 0,
|
|
296
|
-
});
|
|
297
|
-
progressBar.update(downloadedBytes, {
|
|
298
|
-
percentage: Math.round((downloadedBytes / totalLength) * 100),
|
|
299
|
-
});
|
|
300
|
-
if (downloadedBytes === totalLength) {
|
|
301
|
-
progressBar.update(totalLength, { percentage: 100 });
|
|
302
|
-
progressBar.stop();
|
|
303
|
-
console.log((0, colorette_1.green)(`✔ File ${dataPath} fetched successfully.`));
|
|
304
|
-
}
|
|
305
|
-
},
|
|
306
333
|
};
|
|
307
|
-
|
|
334
|
+
let progressBar;
|
|
308
335
|
try {
|
|
309
336
|
const response = await axios_1.default.get(url, config);
|
|
310
|
-
|
|
311
|
-
|
|
337
|
+
const totalLengthHeader = response.headers["content-length"];
|
|
338
|
+
const totalLength = totalLengthHeader
|
|
339
|
+
? parseInt(totalLengthHeader, 10)
|
|
340
|
+
: null;
|
|
341
|
+
if (!totalLength) {
|
|
342
|
+
throw new Error("Content-Length header is missing");
|
|
343
|
+
}
|
|
344
|
+
// Create a new progress bar for the file
|
|
345
|
+
progressBar = new cli_progress_1.default.SingleBar({
|
|
346
|
+
format: `${(0, colorette_1.blue)('[{bar}]')} | ${(0, colorette_1.yellow)('{filename}')} | {percentage}% | {value}/{total} bytes`,
|
|
347
|
+
hideCursor: true,
|
|
348
|
+
barsize: 30,
|
|
349
|
+
align: "left",
|
|
350
|
+
autopadding: true,
|
|
351
|
+
noTTYOutput: false,
|
|
352
|
+
stopOnComplete: true,
|
|
353
|
+
clearOnComplete: false,
|
|
354
|
+
}, cli_progress_1.default.Presets.legacy);
|
|
355
|
+
progressBar.start(totalLength, 0, {
|
|
356
|
+
filename: formatFilename(dataPath),
|
|
357
|
+
});
|
|
358
|
+
let dataBuffers = [];
|
|
359
|
+
const progressStream = (0, progress_stream_1.default)({
|
|
360
|
+
length: totalLength,
|
|
361
|
+
time: 500, // Adjust as needed
|
|
362
|
+
});
|
|
363
|
+
progressStream.on("progress", (progress) => {
|
|
364
|
+
progressBar.update(progress.transferred);
|
|
365
|
+
});
|
|
366
|
+
response.data.pipe(progressStream);
|
|
367
|
+
progressStream.on("data", (chunk) => {
|
|
368
|
+
dataBuffers.push(chunk);
|
|
369
|
+
});
|
|
370
|
+
// Wait for the progress stream to finish
|
|
371
|
+
await new Promise((resolve, reject) => {
|
|
372
|
+
progressStream.on("end", resolve);
|
|
373
|
+
progressStream.on("error", reject);
|
|
374
|
+
});
|
|
375
|
+
return Buffer.concat(dataBuffers);
|
|
312
376
|
}
|
|
313
377
|
catch (error) {
|
|
314
|
-
console.error((0, colorette_1.red)(`✖ Error fetching file ${dataPath}:`), error);
|
|
315
378
|
throw error;
|
|
316
379
|
}
|
|
380
|
+
finally {
|
|
381
|
+
if (progressBar) {
|
|
382
|
+
progressBar.stop();
|
|
383
|
+
}
|
|
384
|
+
}
|
|
317
385
|
}
|
|
318
386
|
/**
|
|
319
387
|
* Get details of a file, including whether it exists and its size.
|
|
320
|
-
* Makes a HEAD request to the server and checks the response headers.
|
|
321
|
-
*
|
|
322
|
-
* @param {string} dataPath - The path of the file within the DataStore.
|
|
323
|
-
* @param {string} rootHash - The root hash associated with the DataStore.
|
|
324
|
-
* @returns {Promise<{ exists: boolean; size: number }>} - An object containing file existence and size information.
|
|
325
388
|
*/
|
|
326
389
|
async getFileDetails(dataPath, rootHash) {
|
|
327
390
|
try {
|
|
328
391
|
const config = {
|
|
329
392
|
httpsAgent: this.createHttpsAgent(),
|
|
330
393
|
};
|
|
331
|
-
// Construct the URL for the HEAD request to check file details
|
|
332
394
|
const url = `https://${this.ipAddress}:${PropagationServer.port}/store/${this.storeId}/${rootHash}/${dataPath}`;
|
|
333
395
|
const response = await axios_1.default.head(url, config);
|
|
334
396
|
// Check the headers for file existence and size
|
|
@@ -336,7 +398,7 @@ class PropagationServer {
|
|
|
336
398
|
const fileSize = parseInt(response.headers["x-file-size"], 10);
|
|
337
399
|
return {
|
|
338
400
|
exists: fileExists,
|
|
339
|
-
size: fileExists ? fileSize : 0,
|
|
401
|
+
size: fileExists ? fileSize : 0,
|
|
340
402
|
};
|
|
341
403
|
}
|
|
342
404
|
catch (error) {
|
|
@@ -346,63 +408,73 @@ class PropagationServer {
|
|
|
346
408
|
}
|
|
347
409
|
/**
|
|
348
410
|
* Download a file from the server by sending a GET request.
|
|
349
|
-
* Logs progress using cli-progress.
|
|
350
|
-
* @param {string} dataPath - The data path of the file to download.
|
|
411
|
+
* Logs progress using a local cli-progress bar.
|
|
351
412
|
*/
|
|
352
|
-
async downloadFile(dataPath) {
|
|
353
|
-
const config = {
|
|
354
|
-
responseType: "stream", // Make sure the response is streamed
|
|
355
|
-
httpsAgent: this.createHttpsAgent(),
|
|
356
|
-
};
|
|
413
|
+
async downloadFile(label, dataPath) {
|
|
357
414
|
const url = `https://${this.ipAddress}:${PropagationServer.port}/fetch/${this.storeId}/${dataPath}`;
|
|
358
|
-
const downloadPath = path_1.default.join(config_1.STORE_PATH, this.storeId, dataPath);
|
|
415
|
+
const downloadPath = path_1.default.join(config_1.STORE_PATH, this.storeId, dataPath);
|
|
359
416
|
// Ensure that the directory for the file exists
|
|
360
417
|
fs_1.default.mkdirSync(path_1.default.dirname(downloadPath), { recursive: true });
|
|
361
|
-
const
|
|
418
|
+
const config = {
|
|
419
|
+
responseType: "stream",
|
|
420
|
+
httpsAgent: this.createHttpsAgent(),
|
|
421
|
+
};
|
|
422
|
+
let progressBar;
|
|
362
423
|
try {
|
|
363
424
|
const response = await axios_1.default.get(url, config);
|
|
364
|
-
const
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
425
|
+
const totalLengthHeader = response.headers["content-length"];
|
|
426
|
+
const totalLength = totalLengthHeader
|
|
427
|
+
? parseInt(totalLengthHeader, 10)
|
|
428
|
+
: null;
|
|
429
|
+
if (!totalLength) {
|
|
430
|
+
throw new Error("Content-Length header is missing");
|
|
431
|
+
}
|
|
432
|
+
// Create a new progress bar for the file
|
|
433
|
+
progressBar = new cli_progress_1.default.SingleBar({
|
|
434
|
+
format: `${(0, colorette_1.blue)('[{bar}]')} | ${(0, colorette_1.yellow)('{filename}')} | {percentage}% | {value}/{total} bytes`,
|
|
435
|
+
hideCursor: true,
|
|
436
|
+
barsize: 30,
|
|
437
|
+
align: "left",
|
|
438
|
+
autopadding: true,
|
|
439
|
+
noTTYOutput: false,
|
|
440
|
+
stopOnComplete: true,
|
|
441
|
+
clearOnComplete: false,
|
|
442
|
+
}, cli_progress_1.default.Presets.legacy);
|
|
443
|
+
progressBar.start(totalLength, 0, {
|
|
444
|
+
filename: formatFilename(label),
|
|
370
445
|
});
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
progressBar.update(downloadedBytes, {
|
|
376
|
-
percentage: Math.round((downloadedBytes / totalLength) * 100),
|
|
377
|
-
});
|
|
446
|
+
const fileWriteStream = fs_1.default.createWriteStream(downloadPath);
|
|
447
|
+
const progressStream = (0, progress_stream_1.default)({
|
|
448
|
+
length: totalLength,
|
|
449
|
+
time: 500, // Adjust as needed
|
|
378
450
|
});
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
return new Promise((resolve, reject) => {
|
|
382
|
-
fileWriteStream.on("finish", () => {
|
|
383
|
-
progressBar.update(totalLength, { percentage: 100 });
|
|
384
|
-
progressBar.stop();
|
|
385
|
-
console.log((0, colorette_1.green)(`
|
|
386
|
-
File ${dataPath} downloaded successfully to ${downloadPath}.`));
|
|
387
|
-
resolve();
|
|
388
|
-
});
|
|
389
|
-
fileWriteStream.on("error", (error) => {
|
|
390
|
-
progressBar.stop();
|
|
391
|
-
console.error((0, colorette_1.red)(`✖ Error downloading file ${dataPath}:`), error);
|
|
392
|
-
reject(error);
|
|
393
|
-
});
|
|
451
|
+
progressStream.on("progress", (progress) => {
|
|
452
|
+
progressBar.update(progress.transferred);
|
|
394
453
|
});
|
|
454
|
+
response.data.pipe(progressStream).pipe(fileWriteStream);
|
|
455
|
+
// Wait for both the file write stream and the progress stream to finish
|
|
456
|
+
await Promise.all([
|
|
457
|
+
new Promise((resolve, reject) => {
|
|
458
|
+
fileWriteStream.on("finish", resolve);
|
|
459
|
+
fileWriteStream.on("error", reject);
|
|
460
|
+
}),
|
|
461
|
+
new Promise((resolve, reject) => {
|
|
462
|
+
progressStream.on("end", resolve);
|
|
463
|
+
progressStream.on("error", reject);
|
|
464
|
+
}),
|
|
465
|
+
]);
|
|
395
466
|
}
|
|
396
467
|
catch (error) {
|
|
397
|
-
console.error((0, colorette_1.red)(`✖ Error downloading file ${dataPath}:`), error);
|
|
398
468
|
throw error;
|
|
399
469
|
}
|
|
470
|
+
finally {
|
|
471
|
+
if (progressBar) {
|
|
472
|
+
progressBar.stop();
|
|
473
|
+
}
|
|
474
|
+
}
|
|
400
475
|
}
|
|
401
476
|
/**
|
|
402
477
|
* Static function to handle downloading multiple files from a DataStore based on file paths.
|
|
403
|
-
* @param {string} storeId - The ID of the DataStore.
|
|
404
|
-
* @param {string[]} dataPaths - The list of data paths to download.
|
|
405
|
-
* @param {string} ipAddress - The IP address of the server.
|
|
406
478
|
*/
|
|
407
479
|
static async downloadStore(storeId, rootHash, ipAddress) {
|
|
408
480
|
const propagationServer = new PropagationServer(ipAddress, storeId);
|
|
@@ -413,13 +485,25 @@ class PropagationServer {
|
|
|
413
485
|
if (!storeExists || !rootHashExists) {
|
|
414
486
|
throw new Error(`Store ${storeId} does not exist.`);
|
|
415
487
|
}
|
|
416
|
-
|
|
488
|
+
// Fetch the rootHash.dat file
|
|
417
489
|
const datFileContent = await propagationServer.fetchFile(`${rootHash}.dat`);
|
|
418
490
|
const root = JSON.parse(datFileContent.toString());
|
|
491
|
+
// Prepare download tasks
|
|
492
|
+
const downloadTasks = [];
|
|
419
493
|
for (const [fileKey, fileData] of Object.entries(root.files)) {
|
|
420
|
-
const dataPath = (0, hashUtils_1.getFilePathFromSha256)(
|
|
421
|
-
|
|
494
|
+
const dataPath = (0, hashUtils_1.getFilePathFromSha256)(fileData.sha256, "data");
|
|
495
|
+
const label = Buffer.from(fileKey, "hex").toString("utf-8");
|
|
496
|
+
downloadTasks.push({ label, dataPath });
|
|
422
497
|
}
|
|
498
|
+
// Limit the number of concurrent downloads
|
|
499
|
+
const concurrencyLimit = 5; // Adjust this number as needed
|
|
500
|
+
// Import asyncPool from your utilities
|
|
501
|
+
const { asyncPool } = await Promise.resolve().then(() => __importStar(require("../utils/asyncPool")));
|
|
502
|
+
await asyncPool(concurrencyLimit, downloadTasks, async (task) => {
|
|
503
|
+
await propagationServer.downloadFile(task.label, task.dataPath);
|
|
504
|
+
});
|
|
505
|
+
// Save the rootHash.dat file
|
|
506
|
+
fs_1.default.writeFileSync(path_1.default.join(config_1.STORE_PATH, storeId, `${rootHash}.dat`), datFileContent);
|
|
423
507
|
const dataStore = blockchain_1.DataStore.from(storeId);
|
|
424
508
|
await dataStore.generateManifestFile();
|
|
425
509
|
console.log((0, colorette_1.green)(`✔ All files have been downloaded to ${storeId}.`));
|
|
@@ -427,29 +511,3 @@ class PropagationServer {
|
|
|
427
511
|
}
|
|
428
512
|
exports.PropagationServer = PropagationServer;
|
|
429
513
|
PropagationServer.port = 4159; // Static port used for all requests
|
|
430
|
-
// Adjust cliProgress settings to align output properly and handle potential undefined values
|
|
431
|
-
// MultiBar for handling multiple progress bars with green progress and margin between bars
|
|
432
|
-
PropagationServer.multiBar = new cli_progress_1.default.MultiBar({
|
|
433
|
-
clearOnComplete: false,
|
|
434
|
-
hideCursor: true,
|
|
435
|
-
format: (options, params, payload) => {
|
|
436
|
-
// Bar length and padding settings
|
|
437
|
-
const barCompleteChar = (0, colorette_1.green)(options.barCompleteChar || "="); // Green bar for completed portion
|
|
438
|
-
const barIncompleteChar = options.barIncompleteChar || "-"; // Default incomplete character
|
|
439
|
-
const barSize = options.barsize || 40; // Default size of the bar
|
|
440
|
-
// Calculate the bar progress
|
|
441
|
-
const progressBar = `${barCompleteChar.repeat(Math.round(params.progress * barSize))}${barIncompleteChar.repeat(barSize - Math.round(params.progress * barSize))}`;
|
|
442
|
-
// Calculate the percentage manually
|
|
443
|
-
const percentage = Math.round((params.value / params.total) * 100);
|
|
444
|
-
// Format the filename to a fixed length
|
|
445
|
-
const formattedFilename = formatFilename(payload.filename, 30); // Trim to max 30 chars
|
|
446
|
-
// Padding the filename, percentage, and size
|
|
447
|
-
const percentageStr = `${percentage}%`.padEnd(4); // Ensure percentage is always 7 characters wide
|
|
448
|
-
const size = `${params.value}/${params.total} bytes`.padEnd(20); // Ensure size is always 20 characters wide
|
|
449
|
-
// Return the complete formatted progress bar with padding
|
|
450
|
-
return `${progressBar} | ${formattedFilename.padEnd(35)} | ${percentageStr} | ${size}`;
|
|
451
|
-
},
|
|
452
|
-
stopOnComplete: true,
|
|
453
|
-
barsize: 40,
|
|
454
|
-
align: "left",
|
|
455
|
-
}, cli_progress_1.default.Presets.shades_classic);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataStore.d.ts","sourceRoot":"","sources":["../../src/blockchain/DataStore.ts"],"names":[],"mappings":"AAEA,OAAO,EAOL,SAAS,IAAI,eAAe,EAE5B,iBAAiB,EAIlB,MAAM,8BAA8B,CAAC;AAWtC,OAAO,EAAE,eAAe,EAAW,MAAM,UAAU,CAAC;AAGpD,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAYjD,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,IAAI,CAAoB;gBAEpB,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,wBAAwB;IAiB/D,IAAW,OAAO,IAAI,MAAM,CAE3B;IAED,IAAW,IAAI,IAAI,iBAAiB,CAEnC;IAEM,QAAQ,IAAI,MAAM;IAIlB,QAAQ,IAAI,MAAM;IAIlB,SAAS,IAAI,MAAM;WAMN,cAAc,IAAI,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;WAOtD,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS;WAK1C,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS;WAiBtD,MAAM,CACxB,MAAM,GAAE,qBAA0B,GACjC,OAAO,CAAC,SAAS,CAAC;mBAyCA,IAAI;IA4FzB;;;OAGG;IACU,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAK5C;;;OAGG;WACiB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IAIxD;;;;OAIG;mBACkB,mBAAmB;WAqB1B,YAAY,IAAI,SAAS,EAAE;IAW5B,aAAa,IAAI,OAAO,CAAC;QACpC,WAAW,EAAE,eAAe,CAAC;QAC7B,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IAyGW,iBAAiB,IAAI,OAAO,CAAC;QACxC,eAAe,EAAE,MAAM,CAAC;QACxB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;YA0BY,iBAAiB;IAYlB,cAAc,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAwC5C,oBAAoB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAexD,WAAW,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAKzC,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAM5B,uBAAuB,CAClC,kBAAkB,CAAC,EAAE,MAAM,GAC1B,OAAO,CAAC,OAAO,CAAC;IAkBN,cAAc,CACzB,QAAQ,EAAE,iBAAiB,GAC1B,OAAO,CAAC,eAAe,CAAC;IA+C3B;;;;;OAKG;IACU,qBAAqB,CAChC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"DataStore.d.ts","sourceRoot":"","sources":["../../src/blockchain/DataStore.ts"],"names":[],"mappings":"AAEA,OAAO,EAOL,SAAS,IAAI,eAAe,EAE5B,iBAAiB,EAIlB,MAAM,8BAA8B,CAAC;AAWtC,OAAO,EAAE,eAAe,EAAW,MAAM,UAAU,CAAC;AAGpD,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAYjD,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,IAAI,CAAoB;gBAEpB,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,wBAAwB;IAiB/D,IAAW,OAAO,IAAI,MAAM,CAE3B;IAED,IAAW,IAAI,IAAI,iBAAiB,CAEnC;IAEM,QAAQ,IAAI,MAAM;IAIlB,QAAQ,IAAI,MAAM;IAIlB,SAAS,IAAI,MAAM;WAMN,cAAc,IAAI,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;WAOtD,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS;WAK1C,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS;WAiBtD,MAAM,CACxB,MAAM,GAAE,qBAA0B,GACjC,OAAO,CAAC,SAAS,CAAC;mBAyCA,IAAI;IA4FzB;;;OAGG;IACU,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAK5C;;;OAGG;WACiB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IAIxD;;;;OAIG;mBACkB,mBAAmB;WAqB1B,YAAY,IAAI,SAAS,EAAE;IAW5B,aAAa,IAAI,OAAO,CAAC;QACpC,WAAW,EAAE,eAAe,CAAC;QAC7B,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IAyGW,iBAAiB,IAAI,OAAO,CAAC;QACxC,eAAe,EAAE,MAAM,CAAC;QACxB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;YA0BY,iBAAiB;IAYlB,cAAc,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAwC5C,oBAAoB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAexD,WAAW,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAKzC,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAM5B,uBAAuB,CAClC,kBAAkB,CAAC,EAAE,MAAM,GAC1B,OAAO,CAAC,OAAO,CAAC;IAkBN,cAAc,CACzB,QAAQ,EAAE,iBAAiB,GAC1B,OAAO,CAAC,eAAe,CAAC;IA+C3B;;;;;OAKG;IACU,qBAAqB,CAChC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CA2C7C"}
|
|
@@ -374,13 +374,8 @@ class DataStore {
|
|
|
374
374
|
async getFileSetForRootHash(rootHash) {
|
|
375
375
|
const datFilePath = path_1.default.join(config_1.STORE_PATH, this.storeId, `${rootHash}.dat`);
|
|
376
376
|
const datFileContent = JSON.parse(fs_1.default.readFileSync(datFilePath, "utf-8"));
|
|
377
|
-
const heightDatFilePath = path_1.default.join(config_1.STORE_PATH, this.storeId, "height.json");
|
|
378
377
|
// Use a Set to ensure uniqueness
|
|
379
378
|
const filesInvolved = new Set();
|
|
380
|
-
filesInvolved.add({
|
|
381
|
-
name: "height.json",
|
|
382
|
-
path: "height.json",
|
|
383
|
-
});
|
|
384
379
|
// Iterate over each file and perform an integrity check
|
|
385
380
|
for (const [fileKey, fileData] of Object.entries(datFileContent.files)) {
|
|
386
381
|
const filePath = (0, hashUtils_1.getFilePathFromSha256)(datFileContent.files[fileKey].sha256, "data");
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Processes items in sequential batches with a concurrency limit.
|
|
3
|
+
* @param {number} limit - The maximum number of concurrent executions per batch.
|
|
4
|
+
* @param {Array<T>} items - The array of items to process.
|
|
5
|
+
* @param {(item: T) => Promise<R>} iteratorFn - The async function to apply to each item.
|
|
6
|
+
* @returns {Promise<Array<R>>} - A promise that resolves when all items have been processed.
|
|
7
|
+
*/
|
|
8
|
+
export declare function asyncPool<T, R>(limit: number, items: T[], iteratorFn: (item: T) => Promise<R>): Promise<R[]>;
|
|
9
|
+
//# sourceMappingURL=asyncPool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asyncPool.d.ts","sourceRoot":"","sources":["../../src/utils/asyncPool.ts"],"names":[],"mappings":"AACA;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAAE,CAAC,EAChC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,CAAC,EAAE,EACV,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAClC,OAAO,CAAC,CAAC,EAAE,CAAC,CAgBd"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.asyncPool = asyncPool;
|
|
4
|
+
/**
|
|
5
|
+
* Processes items in sequential batches with a concurrency limit.
|
|
6
|
+
* @param {number} limit - The maximum number of concurrent executions per batch.
|
|
7
|
+
* @param {Array<T>} items - The array of items to process.
|
|
8
|
+
* @param {(item: T) => Promise<R>} iteratorFn - The async function to apply to each item.
|
|
9
|
+
* @returns {Promise<Array<R>>} - A promise that resolves when all items have been processed.
|
|
10
|
+
*/
|
|
11
|
+
async function asyncPool(limit, items, iteratorFn) {
|
|
12
|
+
const ret = [];
|
|
13
|
+
for (let i = 0; i < items.length; i += limit) {
|
|
14
|
+
const batchItems = items.slice(i, i + limit);
|
|
15
|
+
const batchPromises = batchItems.map((item) => iteratorFn(item));
|
|
16
|
+
// Wait for the current batch to complete before starting the next one
|
|
17
|
+
const batchResults = await Promise.all(batchPromises);
|
|
18
|
+
ret.push(...batchResults);
|
|
19
|
+
// Optional: add a cooldown between batches
|
|
20
|
+
// await new Promise((resolve) => setTimeout(resolve, 500));
|
|
21
|
+
}
|
|
22
|
+
return ret;
|
|
23
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dignetwork/dig-sdk",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.72",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"nanospinner": "^1.1.0",
|
|
47
47
|
"nconf": "^0.12.1",
|
|
48
48
|
"node-cache": "^5.1.2",
|
|
49
|
-
"
|
|
49
|
+
"progress-stream": "^2.0.0",
|
|
50
50
|
"superagent": "^10.0.0",
|
|
51
51
|
"unzipper": "^0.12.3"
|
|
52
52
|
},
|
|
@@ -61,6 +61,7 @@
|
|
|
61
61
|
"@types/mocha": "^10.0.7",
|
|
62
62
|
"@types/nconf": "^0.10.7",
|
|
63
63
|
"@types/node": "^22.1.0",
|
|
64
|
+
"@types/progress-stream": "^2.0.5",
|
|
64
65
|
"@types/superagent": "^8.1.8",
|
|
65
66
|
"@types/unzipper": "^0.10.10",
|
|
66
67
|
"chai": "^5.1.1",
|