ai-chatbot/scripts/cache-bust-zoo-modeling-app-assets.mjs

78 lines
2.5 KiB
JavaScript

#!/usr/bin/env node
import { createHash } from "node:crypto";
import {
cpSync,
existsSync,
readFileSync,
renameSync,
rmSync,
writeFileSync,
} from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
const assetReferencePattern =
/(\b(?:src|href)=")(\.\/assets\/([^"?]+\.(?:css|js)))(?:\?v=[^"]+)?(")/g;
export function cacheBustZooModelingAppAssets(
outputDir,
{ retainOriginalAssets = false } = {}
) {
const indexPath = path.join(outputDir, "index.html");
const source = readFileSync(indexPath, "utf8");
const assetReferences = [...source.matchAll(assetReferencePattern)];
if (assetReferences.length === 0) {
const currentVersion = source.match(/\.\/assets-([a-f0-9]{12})\//)?.[1];
if (currentVersion) {
return { assetCount: 0, version: currentVersion };
}
throw new Error(`No HiCAD entry assets found in ${indexPath}`);
}
const assetsDir = path.join(outputDir, "assets");
const contentHash = createHash("sha256");
for (const reference of assetReferences.sort((a, b) =>
a[3].localeCompare(b[3])
)) {
contentHash.update(reference[3]);
contentHash.update(readFileSync(path.join(assetsDir, reference[3])));
}
const version = contentHash.digest("hex").slice(0, 12);
const versionedAssetsName = `assets-${version}`;
const versionedAssetsDir = path.join(outputDir, versionedAssetsName);
rmSync(versionedAssetsDir, { force: true, recursive: true });
if (retainOriginalAssets) {
cpSync(assetsDir, versionedAssetsDir, { recursive: true });
} else {
renameSync(assetsDir, versionedAssetsDir);
}
const versionedSource = source.replace(
assetReferencePattern,
(_match, prefix, _assetReference, assetPath, suffix) =>
`${prefix}./${versionedAssetsName}/${assetPath}${suffix}`
);
writeFileSync(indexPath, versionedSource);
return { assetCount: assetReferences.length, version };
}
const invokedPath = process.argv[1] ? path.resolve(process.argv[1]) : "";
if (invokedPath === fileURLToPath(import.meta.url)) {
const outputDir = path.resolve(
process.argv.slice(2).find((argument) => !argument.startsWith("--")) ||
"public/vendor/zoo-modeling-app"
);
if (!existsSync(outputDir)) {
throw new Error(`HiCAD output directory does not exist: ${outputDir}`);
}
const { assetCount, version } = cacheBustZooModelingAppAssets(outputDir, {
retainOriginalAssets: process.argv.includes("--retain-original"),
});
console.log(
`Versioned ${assetCount} HiCAD entry assets as assets-${version} in ${outputDir}`
);
}