Files
workinf_Blender_Wasm/tools/web/check-web-engine-command-registry.mjs
mes123456 e9bfef0c5a
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled
feat(web): complete Blender route runtime execution
2026-09-07 00:12:32 +08:00

46 lines
4.3 KiB
JavaScript

import assert from "node:assert/strict";
import fs from "node:fs";
const protocol = fs.readFileSync(new URL("../../web/protocol/web-engine.ts", import.meta.url), "utf8");
const registry = fs.readFileSync(new URL("../../web/protocol/web-engine-capabilities.ts", import.meta.url), "utf8");
const app = fs.readFileSync(new URL("../../web/app/src/app/App.tsx", import.meta.url), "utf8");
const catalog = JSON.parse(fs.readFileSync(new URL("../../web/app/src/capabilities/blender-feature-route-catalog.json", import.meta.url), "utf8"));
const commandUnion = protocol.split("export type WebEngineEditCommand =", 2)[1]?.split("/** JSON values", 1)[0] ?? "";
const commands = new Set([...commandUnion.matchAll(/type:\s*"([A-Za-z0-9]+)"/gu)].map((match) => match[1]));
commands.add("moveNLAStrip");
const registered = new Set([...registry.matchAll(/^ ([A-Za-z0-9]+): \{/gmu)].map((match) => match[1]));
registered.delete("listBlenderOperators");
registered.delete("invokeBlenderOperator");
const missing = [...commands].filter((command) => !registered.has(command)).sort();
const stale = [...registered].filter((command) => !commands.has(command)).sort();
assert.deepEqual(missing, [], `WebEngine edit commands missing capabilities: ${missing.join(",")}`);
assert.deepEqual(stale, [], `WebEngine capabilities without edit commands: ${stale.join(",")}`);
const normalizeCommandIdentifier = (identifier) => String(identifier ?? "").replace(/^(?:web[-_]?command|command):/iu, "");
const webMainEntries = catalog.entries.filter((entry) => entry.route === "WEB_MAIN" && entry.kind === "web-command");
const missingWebMainRoutes = webMainEntries.map((entry) => normalizeCommandIdentifier(entry.identifier)).filter((identifier) => identifier && !registered.has(identifier));
const serverEntries = catalog.entries.filter((entry) => entry.route === "SERVER_NATIVE");
const missingServerRoutes = serverEntries.filter((entry) => entry.httpRoute !== "/api/server-operator-job").map((entry) => entry.identifier);
const browserEntries = catalog.entries.filter((entry) => entry.route === "BROWSER_EQUIVALENT");
const browserGroups = new Set(Object.keys(catalog.browserActionGroups ?? {}));
const missingBrowserGroups = browserEntries.filter((entry) => !browserGroups.has(entry.browserActionGroup)).map((entry) => entry.identifier);
const browserCommands = [...new Set(browserEntries.map((entry) => catalog.browserActionGroups?.[entry.browserActionGroup]?.command).filter(Boolean))];
const missingBrowserCommands = browserCommands.filter((command) => !app.includes(`id: "${command}"`));
const browserActionableEntries = browserEntries.filter((entry) => {
const command = catalog.browserActionGroups?.[entry.browserActionGroup]?.command;
return browserGroups.has(entry.browserActionGroup) && Boolean(command) && app.includes(`id: "${command}"`);
});
const runtimeAudit = {
schemaVersion: 1,
command: "featureRouteRuntimeAudit",
status: missingWebMainRoutes.length || missingServerRoutes.length || missingBrowserGroups.length ? "FAILED" : "PASS",
webMain: { entries: webMainEntries.length, registered: webMainEntries.length - missingWebMainRoutes.length, missing: missingWebMainRoutes },
serverNative: { entries: serverEntries.length, httpRoute: "/api/server-operator-job", missing: missingServerRoutes },
browserEquivalent: { entries: browserEntries.length, actionable: browserActionableEntries.length, groups: [...browserGroups].sort(), missing: missingBrowserGroups, missingCommands: missingBrowserCommands },
behavioralEvidence: { separate: true, status: catalog.behavioralEvidence?.status, verifiedUnits: catalog.behavioralEvidence?.verifiedUnits, unverifiedUnits: catalog.behavioralEvidence?.unverifiedUnits },
};
assert.deepEqual(missingWebMainRoutes, [], `WEB_MAIN commands missing capabilities: ${missingWebMainRoutes.join(",")}`);
assert.deepEqual(missingServerRoutes, [], `SERVER_NATIVE entries missing HTTP route: ${missingServerRoutes.join(",")}`);
assert.deepEqual(missingBrowserGroups, [], `BROWSER_EQUIVALENT entries missing browser action group: ${missingBrowserGroups.join(",")}`);
assert.deepEqual(missingBrowserCommands, [], `BROWSER_EQUIVALENT browser action adapters missing from App: ${missingBrowserCommands.join(",")}`);
process.stdout.write(`web-engine-command-registry-ok commands=${commands.size} featureRouteRuntimeAudit=${JSON.stringify(runtimeAudit)}\n`);