@typed/content-hash
Version:
Content hash a directory of HTML/JS/CSS files and other static assets
90 lines • 4.61 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.rewriteDependencies = void 0;
const tslib_1 = require("tslib");
const Env_1 = require("@typed/fp/Env");
const FxEnv_1 = require("@typed/fp/FxEnv");
const base64url_1 = (0, tslib_1.__importDefault)(require("base64url"));
const crypto_1 = require("crypto");
const function_1 = require("fp-ts/function");
const Option_1 = require("fp-ts/Option");
const path_1 = require("path");
const logging_1 = require("../application/services/logging");
const applyOrigin_1 = require("./applyOrigin");
const ensureRelative_1 = require("./ensureRelative");
const hashes_1 = require("./hashes");
const getHashedPath_1 = require("./hashes/getHashedPath");
const rewriteDocumentContents_1 = require("./rewriteDocumentContents");
const sha512Hash_1 = require("./sha512Hash");
const dtsRegex = new RegExp(`.d.ts$`);
const rewriteDependencies = (documents) => (0, FxEnv_1.Do)(function* (_) {
const env = yield* _((0, Env_1.ask)());
const computedHashes = computeContentHashes(documents, env.documentRegistry, env.hashLength);
let documentRegistry = env.documentRegistry;
for (const document of documents) {
const { filePath } = document;
yield* _((0, logging_1.debug)(`Rewriting dependencies ${filePath}...`));
const hasComputedHash = computedHashes.has(filePath);
const updatedDocument = hasComputedHash
? { ...document, contentHash: (0, Option_1.some)({ type: 'hash', hash: computedHashes.get(filePath) }) }
: document;
documentRegistry = yield* _((0, function_1.pipe)((0, rewriteDocumentContents_1.rewriteDocumentContents)(updatedDocument, rewriteDocumentDependencies(updatedDocument, computedHashes, env), env.sourceMaps, hasComputedHash), (0, Env_1.useSome)({ documentRegistry })));
}
return documentRegistry;
});
exports.rewriteDependencies = rewriteDependencies;
const rewriteDocumentDependencies = (document, computedHashes, env) => (ms) => {
for (const dep of document.dependencies) {
const depDoc = env.documentRegistry.get(dep.filePath);
if (depDoc) {
ms.overwrite(dep.position.start, dep.position.end, determineReplacementPath({ document, depDoc, dep, computedHashes, ...env }));
}
}
};
function determineReplacementPath({ document, depDoc, documentRegistry, hashLength, directory, dep, baseUrl, computedHashes, }) {
const hashedPath = computedHashes.has(depDoc.filePath)
? (0, hashes_1.replaceHash)(depDoc.filePath, depDoc.fileExtension, computedHashes.get(depDoc.filePath).slice(0, hashLength))
: (0, getHashedPath_1.getHashedPath)(depDoc, documentRegistry, hashLength);
const relativePath = (0, ensureRelative_1.ensureRelative)(path_1.posix.relative(path_1.posix.dirname(document.filePath), hashedPath));
const absolutePath = ensureAbsolute(path_1.posix.relative(directory, hashedPath));
const pathToUse = baseUrl
? (0, applyOrigin_1.applyOrigin)(directory, hashedPath, baseUrl)
: dep.specifier.startsWith('/')
? absolutePath
: relativePath;
const replacementPath = dtsRegex.test(pathToUse) ? pathToUse.replace(dtsRegex, '') : pathToUse;
return replacementPath;
}
function ensureAbsolute(path) {
if (path[0] !== '/') {
return '/' + path;
}
return path;
}
function computeContentHashes(documents, registry, hashLength) {
const computedHashes = new Map();
if (documents.length < 2) {
return computedHashes;
}
for (const document of documents) {
if ((0, Option_1.isSome)(document.contentHash) && document.contentHash.value.type == 'hash') {
computedHashes.set(document.filePath, computeContentHash(document, registry, hashLength));
}
}
return computedHashes;
}
function computeContentHash(document, registry, hashLength) {
const getHash = (d) => (0, function_1.pipe)((0, hashes_1.getContentHash)(d, registry, hashLength), (0, Option_1.getOrElse)(() => (0, sha512Hash_1.sha512Hash)(d.contents)));
const computed = (0, crypto_1.createHash)('sha512');
computed.update(getHash(document));
const dependenciesForHashing = new Set(document.dependencies);
for (const dep of dependenciesForHashing) {
const depDoc = registry.get(dep.filePath);
if (depDoc) {
computed.update(getHash(depDoc));
depDoc.dependencies.forEach((d) => dependenciesForHashing.add(d));
}
}
return base64url_1.default.fromBase64(computed.digest('base64'));
}
//# sourceMappingURL=rewriteDependencies.js.map