astro
Version:
Astro is a modern site builder with web best practices, performance, and DX front-of-mind.
33 lines (32 loc) • 1.3 kB
JavaScript
import { encodeHexLowerCase } from "@oslojs/encoding";
import { getConfigHashInput } from "./input.js";
export { getConfigHashInput } from "./input.js";
/**
* Serialize a value with object keys sorted recursively, so that a change in key
* order does not change the result. Array order is preserved because it is
* meaningful (e.g. `i18n.locales`, `redirects`). Function and `undefined` values
* are dropped by `JSON.stringify`, which is what lets us hand whole config
* objects (like `markdown` or `image`) to {@link getConfigHashInput} and let
* their non-serializable pockets fall away.
*/
function stableStringify(value) {
return JSON.stringify(value, (_key, val) => {
if (val && typeof val === "object" && !Array.isArray(val)) {
return Object.keys(val).sort().reduce((acc, key) => {
acc[key] = val[key];
return acc;
}, {});
}
return val;
});
}
/**
* Produce a sha256 over the output-affecting subset of the resolved config (see
* {@link getConfigHashInput}). A mismatch invalidates the whole incremental
* build cache.
*/
export async function computeConfigHash(config) {
const input = stableStringify(getConfigHashInput(config));
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(input));
return encodeHexLowerCase(new Uint8Array(digest));
}