import { readFileSync } from "node:fs";
import { createServer } from "node:http";
import { isAbsolute, join, resolve } from "node:path";
import { chromium } from "@playwright/test";
function option(name) {
const index = process.argv.indexOf(name);
return index >= 0 ? process.argv[index + 1] : undefined;
}
function defaultConfigPath() {
if (!process.env.LOCALAPPDATA || !isAbsolute(process.env.LOCALAPPDATA)) {
throw new Error("local_app_data_unavailable");
}
return join(process.env.LOCALAPPDATA, "Dada", "P0A", "config", "instance.json");
}
const manifestPath = resolve(option("--manifest") ?? "config/runtime-assets-manifest.json");
const configPath = resolve(option("--config") ?? process.env.DADA_INSTANCE_CONFIG_PATH ?? defaultConfigPath());
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
const configuration = JSON.parse(readFileSync(configPath, "utf8"));
if (typeof configuration.asset_root !== "string" || !isAbsolute(configuration.asset_root)) {
throw new Error("asset_root_configuration_invalid");
}
const fontEntries = manifest.entries
.filter((entry) => entry.assetId.startsWith("TEXT-FONT-") && entry.mimeType.startsWith("font/"))
.toSorted((left, right) => left.assetId.localeCompare(right.assetId));
const uniqueEntries = [...new Map(fontEntries.map((entry) => [entry.sha256, entry])).values()];
const fontPaths = new Map(
uniqueEntries.map((entry) => [
`/${encodeURIComponent(entry.assetId)}`,
{ mimeType: entry.mimeType, path: join(configuration.asset_root, entry.relativePath) },
]),
);
const server = createServer((request, response) => {
const font = fontPaths.get(request.url ?? "");
if (!font) {
response.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
response.end("
Dada browser font validation");
return;
}
const bytes = readFileSync(font.path);
response.writeHead(200, { "Content-Length": bytes.length, "Content-Type": font.mimeType });
response.end(bytes);
});
await new Promise((resolveReady) => server.listen(0, "127.0.0.1", resolveReady));
const address = server.address();
if (!address || typeof address === "string") throw new Error("browser_font_probe_server_unavailable");
const origin = `http://127.0.0.1:${address.port}`;
const browser = await chromium.launch({ channel: option("--channel") ?? "msedge", headless: true });
const failures = [];
try {
let page = await browser.newPage();
await page.goto(origin);
for (let index = 0; index < uniqueEntries.length; index += 1) {
if (index > 0 && index % 25 === 0) {
await page.close();
page = await browser.newPage();
await page.goto(origin);
}
const entry = uniqueEntries[index];
const result = await page.evaluate(async ({ family, url }) => {
try {
const response = await fetch(url);
if (!response.ok) return `http_${response.status}`;
await new FontFace(family, await response.arrayBuffer()).load();
return "loaded";
} catch (error) {
return error instanceof Error ? `${error.name}: ${error.message}` : String(error);
}
}, { family: `DadaFontProbe${index}`, url: `${origin}/${encodeURIComponent(entry.assetId)}` });
if (result !== "loaded") failures.push({ asset_id: entry.assetId, error: result });
}
} finally {
await browser.close();
await new Promise((resolveClosed) => server.close(resolveClosed));
}
const result = {
checked_entries: fontEntries.length,
failed_fonts: failures,
status: failures.length === 0 ? "passed" : "failed",
unique_fonts: uniqueEntries.length,
};
process.stdout.write(`${JSON.stringify(result)}\n`);
if (failures.length > 0) process.exitCode = 1;