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.
|
# Include inside the authenticated HiCAD HTTPS server block.
|
||||||
# Replace __AI_CAD_WS_PROXY_SECRET__ during deployment and chmod the rendered file 600.
|
# 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;
|
root /var/www/ai-chatbot/public;
|
||||||
try_files $uri =404;
|
try_files $uri =404;
|
||||||
gzip_static on;
|
gzip_static on;
|
||||||
|
|||||||
@ -1,44 +1,77 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
import { createHash } from "node:crypto";
|
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 path from "node:path";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
const assetReferencePattern =
|
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 indexPath = path.join(outputDir, "index.html");
|
||||||
const source = readFileSync(indexPath, "utf8");
|
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(
|
const versionedSource = source.replace(
|
||||||
assetReferencePattern,
|
assetReferencePattern,
|
||||||
(_match, prefix, assetReference, suffix) => {
|
(_match, prefix, _assetReference, assetPath, suffix) =>
|
||||||
const assetPath = path.join(outputDir, assetReference.slice(2));
|
`${prefix}./${versionedAssetsName}/${assetPath}${suffix}`
|
||||||
const version = createHash("sha256")
|
|
||||||
.update(readFileSync(assetPath))
|
|
||||||
.digest("hex")
|
|
||||||
.slice(0, 12);
|
|
||||||
versionedAssetCount += 1;
|
|
||||||
return `${prefix}${assetReference}?v=${version}${suffix}`;
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (versionedAssetCount === 0) {
|
|
||||||
throw new Error(`No versioned HiCAD assets found in ${indexPath}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
writeFileSync(indexPath, versionedSource);
|
writeFileSync(indexPath, versionedSource);
|
||||||
return versionedAssetCount;
|
return { assetCount: assetReferences.length, version };
|
||||||
}
|
}
|
||||||
|
|
||||||
const invokedPath = process.argv[1] ? path.resolve(process.argv[1]) : "";
|
const invokedPath = process.argv[1] ? path.resolve(process.argv[1]) : "";
|
||||||
if (invokedPath === fileURLToPath(import.meta.url)) {
|
if (invokedPath === fileURLToPath(import.meta.url)) {
|
||||||
const outputDir = path.resolve(
|
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"));
|
copyFileSync(wasmBinary, path.join(sourceDir, "public/kcl_wasm_lib_bg.wasm"));
|
||||||
}
|
}
|
||||||
|
|
||||||
function precompressVersionedAssets() {
|
function precompressVersionedAssets(assetsDir) {
|
||||||
const assetsDir = path.join(outputDir, "assets");
|
|
||||||
for (const entry of readdirSync(assetsDir, { withFileTypes: true })) {
|
for (const entry of readdirSync(assetsDir, { withFileTypes: true })) {
|
||||||
if (!entry.isFile() || !/\.(?:css|js)$/.test(entry.name)) {
|
if (!entry.isFile() || !/\.(?:css|js)$/.test(entry.name)) {
|
||||||
continue;
|
continue;
|
||||||
@ -339,12 +338,12 @@ async function main() {
|
|||||||
if (!existsSync(path.join(buildDir, "index.html"))) {
|
if (!existsSync(path.join(buildDir, "index.html"))) {
|
||||||
throw new Error("Zoo Design Studio build did not produce index.html");
|
throw new Error("Zoo Design Studio build did not produce index.html");
|
||||||
}
|
}
|
||||||
|
precompressVersionedAssets(path.join(buildDir, "assets"));
|
||||||
cacheBustZooModelingAppAssets(buildDir);
|
cacheBustZooModelingAppAssets(buildDir);
|
||||||
|
|
||||||
rmSync(outputDir, { force: true, recursive: true });
|
rmSync(outputDir, { force: true, recursive: true });
|
||||||
mkdirSync(path.dirname(outputDir), { recursive: true });
|
mkdirSync(path.dirname(outputDir), { recursive: true });
|
||||||
await cp(buildDir, outputDir, { recursive: true });
|
await cp(buildDir, outputDir, { recursive: true });
|
||||||
precompressVersionedAssets();
|
|
||||||
|
|
||||||
const license = path.join(sourceDir, "LICENSE");
|
const license = path.join(sourceDir, "LICENSE");
|
||||||
if (existsSync(license)) {
|
if (existsSync(license)) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user