-
Notifications
You must be signed in to change notification settings - Fork 0
/
MerkleFileProcessor.ts
75 lines (70 loc) · 2.78 KB
/
MerkleFileProcessor.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/**
* @module MerkleFileProcessor - utilities to find the Merkle Root of a file or directory
*
* @author Lucas Armstrong - Lucas@throneit.com - github.com/LucasArmstrong
*/
/**
* @import fs.readdirSync
* @import fs.statSync
* @import HashAlgorithm - Enum of hash algorithms
* @import MerkleHash - Hash utlities for MerkleTree
* @import MerkleTree - generates a MerkleTree from a list of data
*/
import { readdirSync, statSync } from 'fs';
import { HashAlgorithm, MerkleHash } from './MerkleHash';
import { MerkleTree } from './MerkleTree';
/**
* @class MerkleFileProcessor
*/
export class MerkleFileProcessor {
/**
* @method processFile - Generates a Merkle Root from a file buffer string
*
* @param filePath
* @returns {string}
*/
static async processFile(filePath: string, hashAlgorithm: HashAlgorithm = HashAlgorithm.sha256): Promise<string> {
try {
const fileHash: string = await MerkleHash.createHashFromFile(filePath, hashAlgorithm);
const merkleTree: MerkleTree = new MerkleTree([fileHash]);
// console.log(`Merkle root for ${filePath}: ${merkleTree.root}`);
return merkleTree.root;
} catch (error) {
console.log(`processFile error for file path '${filePath}': `, error);
return '';
}
}
/**
* @method processDirectory - Recursively searches directory for files to generate a Merkle Root
*
* @param directoryPath
* @returns {string}
*/
static async processDirectory(directoryPath: string, hashAlgorithm: HashAlgorithm = HashAlgorithm.sha256): Promise<string> {
try {
const fileHashRoots: string[] = [];
const files: string[] = readdirSync(directoryPath);
if (!files.length) {
return '';
}
for (let i = 0; i < files.length; i++) {
const file = files[i];
const stat = statSync(`${directoryPath}/${file}`);
if (stat?.isDirectory()) {
fileHashRoots.push(await MerkleFileProcessor.processDirectory(`${directoryPath}/${file}`, hashAlgorithm));
} else {
fileHashRoots.push(await MerkleFileProcessor.processFile(`${directoryPath}/${file}`, hashAlgorithm));
}
}
if (!fileHashRoots.length) {
return '';
}
const merkleTree: MerkleTree = new MerkleTree(fileHashRoots);
// console.log(`\nMerkle root for ${directoryPath}/: ${type} - ${merkleTree.root}`);
return merkleTree.root;
} catch (error) {
console.log(`Unable to scan directory: ${directoryPath}`, error);
throw new Error(`processDirectory Error: ${error}`);
}
}
}