fix: version the complete HiCAD asset graph
This commit is contained in:
parent
beb6ff4f04
commit
08d8a1d4af
@ -1,7 +1,7 @@
|
||||
# Include inside the authenticated HiCAD HTTPS server block.
|
||||
# Replace __AI_CAD_WS_PROXY_SECRET__ during deployment and chmod the rendered file 600.
|
||||
|
||||
location ^~ /vendor/zoo-modeling-app/assets/ {
|
||||
location ^~ /vendor/zoo-modeling-app/assets {
|
||||
root /var/www/ai-chatbot/public;
|
||||
try_files $uri =404;
|
||||
gzip_static on;
|
||||
|
||||
@ -1,44 +1,77 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { createHash } from "node:crypto";
|
||||
import { readFileSync, writeFileSync } from "node:fs";
|
||||
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;
|
||||
/(\b(?:src|href)=")(\.\/assets\/([^"?]+\.(?:css|js)))(?:\?v=[^"]+)?(")/g;
|
||||
|
||||
export function cacheBustZooModelingAppAssets(outputDir) {
|
||||
export function cacheBustZooModelingAppAssets(
|
||||
outputDir,
|
||||
{ retainOriginalAssets = false } = {}
|
||||
) {
|
||||
const indexPath = path.join(outputDir, "index.html");
|
||||
const source = readFileSync(indexPath, "utf8");
|
||||
let versionedAssetCount = 0;
|
||||
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, suffix) => {
|
||||
const assetPath = path.join(outputDir, assetReference.slice(2));
|
||||
const version = createHash("sha256")
|
||||
.update(readFileSync(assetPath))
|
||||
.digest("hex")
|
||||
.slice(0, 12);
|
||||
versionedAssetCount += 1;
|
||||
return `${prefix}${assetReference}?v=${version}${suffix}`;
|
||||
}
|
||||
(_match, prefix, _assetReference, assetPath, suffix) =>
|
||||
`${prefix}./${versionedAssetsName}/${assetPath}${suffix}`
|
||||
);
|
||||
|
||||
if (versionedAssetCount === 0) {
|
||||
throw new Error(`No versioned HiCAD assets found in ${indexPath}`);
|
||||
}
|
||||
|
||||
writeFileSync(indexPath, versionedSource);
|
||||
return versionedAssetCount;
|
||||
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[2] || "public/vendor/zoo-modeling-app"
|
||||
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}`
|
||||
);
|
||||
const assetCount = cacheBustZooModelingAppAssets(outputDir);
|
||||
console.log(`Versioned ${assetCount} HiCAD entry assets in ${outputDir}`);
|
||||
}
|
||||
|
||||
@ -301,8 +301,7 @@ function ensureWasm() {
|
||||
copyFileSync(wasmBinary, path.join(sourceDir, "public/kcl_wasm_lib_bg.wasm"));
|
||||
}
|
||||
|
||||
function precompressVersionedAssets() {
|
||||
const assetsDir = path.join(outputDir, "assets");
|
||||
function precompressVersionedAssets(assetsDir) {
|
||||
for (const entry of readdirSync(assetsDir, { withFileTypes: true })) {
|
||||
if (!entry.isFile() || !/\.(?:css|js)$/.test(entry.name)) {
|
||||
continue;
|
||||
@ -339,12 +338,12 @@ async function main() {
|
||||
if (!existsSync(path.join(buildDir, "index.html"))) {
|
||||
throw new Error("Zoo Design Studio build did not produce index.html");
|
||||
}
|
||||
precompressVersionedAssets(path.join(buildDir, "assets"));
|
||||
cacheBustZooModelingAppAssets(buildDir);
|
||||
|
||||
rmSync(outputDir, { force: true, recursive: true });
|
||||
mkdirSync(path.dirname(outputDir), { recursive: true });
|
||||
await cp(buildDir, outputDir, { recursive: true });
|
||||
precompressVersionedAssets();
|
||||
|
||||
const license = path.join(sourceDir, "LICENSE");
|
||||
if (existsSync(license)) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user