'use strict'; const fs = require('fs'); const path = require('path'); const hasha = require('hasha'); const makeDir = require('make-dir'); const writeFileAtomic = require('write-file-atomic'); const packageHash = require('package-hash'); let ownHash = ''; function getOwnHash() { ownHash = packageHash.sync(path.join(__dirname, 'package.json')); return ownHash; } function wrap(opts) { if (!(opts.factory || opts.transform) || (opts.factory && opts.transform)) { throw new Error('Specify factory or transform but not both'); } if (typeof opts.cacheDir !== 'string' && !opts.disableCache) { throw new Error('cacheDir must be a string'); } let transformFn = opts.transform; const {factory, cacheDir, shouldTransform, disableCache, hashData, onHash} = opts; const cacheDirCreated = opts.createCacheDir === false; let created = transformFn && cacheDirCreated; const ext = opts.ext || ''; const salt = opts.salt || ''; const encoding = opts.encoding === 'buffer' ? undefined : opts.encoding || 'utf8'; function transform(input, metadata, hash) { if (!created) { if (!cacheDirCreated && !disableCache) { makeDir.sync(cacheDir); } if (!transformFn) { transformFn = factory(cacheDir); } created = true; } return transformFn(input, metadata, hash); } return function (input, metadata) { if (shouldTransform && !shouldTransform(input, metadata)) { return input; } if (disableCache) { return transform(input, metadata); } let data = [ownHash || getOwnHash(), input]; if (salt) { data.push(salt); } if (hashData) { data = data.concat(hashData(input, metadata)); } const hash = hasha(data, {algorithm: 'sha256'}); const cachedPath = path.join(cacheDir, hash + ext); if (onHash) { onHash(input, metadata, hash); } try { return fs.readFileSync(cachedPath, encoding); } catch (error) { const result = transform(input, metadata, hash); writeFileAtomic.sync(cachedPath, result, {encoding}); return result; } }; } module.exports = wrap;