@ocfl/ocfl
Version:
Oxford Common File Layout (OCFL) JS library
140 lines (126 loc) • 3.03 kB
JavaScript
//@ts-check
//const hasha = require("hasha");
const crypto = require("crypto");
const fs = require("fs");
const stream = require("stream/promises");
//const worker = require('node:worker_threads');
const { Enum } = require('./enum.js');
const { Transform } = require('stream');
/**
*/
class CONTENT extends Enum {
static sha256 = new this('sha256');
static sha512 = new this('sha512');
};
class FIXITY extends Enum {
static sha256 = new this('sha256');
static sha512 = new this('sha512');
static md5 = new this('md5');
static sha1 = new this('sha1');
static blake2b512 = new this('blake2b-512');
};
/**
* A pass through stream that pass data as it is and calculate the digest as data pass through.
*/
class HashThrough extends Transform {
constructor(hash, streamOptions) {
super(streamOptions);
this.hash = hash;
}
_transform(chunk, encoding, cb) {
try {
this.hash.update(chunk, encoding);
cb(null, chunk);
} catch (err) {
cb(err)
}
}
digest(encoding) {
return this.hash.digest(encoding || 'hex');
}
}
/**
* @type { Object.<string, function():crypto.Hash>}
*/
let algorithms = {};
for (let algo of FIXITY) {
algorithms[algo.value] = function () { return crypto.createHash(algo.name); }
}
/**
*
* @param {string} algorithm
*/
function createStream(algorithm) {
const hash = algorithms[algorithm || 'sha512']();
//hash.setEncoding('hex');
return hash;
}
/**
*
* @param {string} [algorithm]
* @param {object} [options]
*/
function createStreamThrough(algorithm = 'sha512', options) {
const hash = algorithms[algorithm]();
//hash.setEncoding('hex');
return new HashThrough(hash, options);
}
/**
*
* @param {string} algorithm
* @param {Buffer | string | Array<Buffer | string>} input
* @return {string}
*/
function digestSync(algorithm, input) {
const hash = algorithms[algorithm || 'sha512']();
let inputs = Array.isArray(input) ? input : [input];
for (let chunk of inputs) {
hash.update(chunk);
}
return hash.digest('hex');
}
/**
*
* @param {string} algorithm
* @param {Buffer | string | Array<Buffer | string>} input
*/
async function digestAsync(algorithm, input) {
return digestSync(algorithm, input);
}
/**
*
* @param {string} algorithm
* @param {NodeJS.ReadableStream} input
*/
async function digestFromStream(algorithm, input) {
let hash = algorithms[algorithm]();
await stream.pipeline(input, hash);
return hash.digest('hex');
}
/**
*
* @param {string} algorithm
* @param {string} filePath
*/
async function digestFromFile(algorithm, filePath) {
return await digestFromStream(algorithm, fs.createReadStream(filePath));
}
const OcflDigest = {
CONTENT,
FIXITY,
algorithms,
createStream, createStreamThrough,
digestAsync, digestSync,
digestFromStream, digestFromFile
};
module.exports = {
OcflDigest
// DIGEST,
// DIGEST_FIXITY,
// digestSync,
// digestAsync,
// digestFromStream,
// digestFromFile,
// digestStream,
// HashThrough
};