feat(FN-3717): gate bootstrap on openclaw bridge asset
Stabilizes the OpenClaw bundle by hardening the asset copy logic and gating the bootstrap flow on the openclaw bridge asset being present, with regression tests covering the new bundle-output helpers and a patch changeset for `@runfusion/fusion`. Fusion-Task-Id: FN-3717
This commit is contained in:
60
packages/cli/src/__tests__/bundle-output-helpers.test.ts
Normal file
60
packages/cli/src/__tests__/bundle-output-helpers.test.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const state = {
|
||||
existingPaths: new Set<string>(),
|
||||
indexHtml: "",
|
||||
};
|
||||
|
||||
vi.mock("node:fs", () => ({
|
||||
existsSync: (path: string) => state.existingPaths.has(path),
|
||||
readFileSync: () => state.indexHtml,
|
||||
execFileSync: vi.fn(),
|
||||
execSync: vi.fn(),
|
||||
}));
|
||||
|
||||
import {
|
||||
bundlePath,
|
||||
clientIndexPath,
|
||||
dashboardClientStubMarker,
|
||||
hasBuiltDashboardAssets,
|
||||
openclawMcpSchemaServerPath,
|
||||
} from "./bundle-output-helpers";
|
||||
|
||||
const cursorPluginManifestPath = bundlePath.replace(
|
||||
"dist/bin.js",
|
||||
"dist/plugins/fusion-plugin-cursor-runtime/manifest.json",
|
||||
);
|
||||
|
||||
describe("hasBuiltDashboardAssets", () => {
|
||||
beforeEach(() => {
|
||||
state.existingPaths.clear();
|
||||
state.indexHtml = "<html><body><script src=\"assets/app.js\"></script></body></html>";
|
||||
});
|
||||
|
||||
it("returns false when openclaw mcp-schema-server.cjs is missing", () => {
|
||||
state.existingPaths.add(bundlePath);
|
||||
state.existingPaths.add(clientIndexPath);
|
||||
state.existingPaths.add(cursorPluginManifestPath);
|
||||
|
||||
expect(hasBuiltDashboardAssets()).toBe(false);
|
||||
});
|
||||
|
||||
it("returns true when all required assets exist and dashboard stub marker is absent", () => {
|
||||
state.existingPaths.add(bundlePath);
|
||||
state.existingPaths.add(clientIndexPath);
|
||||
state.existingPaths.add(cursorPluginManifestPath);
|
||||
state.existingPaths.add(openclawMcpSchemaServerPath);
|
||||
|
||||
expect(hasBuiltDashboardAssets()).toBe(true);
|
||||
});
|
||||
|
||||
it("returns false when dashboard client index contains stub marker", () => {
|
||||
state.existingPaths.add(bundlePath);
|
||||
state.existingPaths.add(clientIndexPath);
|
||||
state.existingPaths.add(cursorPluginManifestPath);
|
||||
state.existingPaths.add(openclawMcpSchemaServerPath);
|
||||
state.indexHtml = dashboardClientStubMarker;
|
||||
|
||||
expect(hasBuiltDashboardAssets()).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -7,6 +7,13 @@ export const workspaceRoot = join(cliRoot, "..", "..");
|
||||
export const bundlePath = join(cliRoot, "dist", "bin.js");
|
||||
export const clientIndexPath = join(cliRoot, "dist", "client", "index.html");
|
||||
const cursorPluginManifestPath = join(cliRoot, "dist", "plugins", "fusion-plugin-cursor-runtime", "manifest.json");
|
||||
export const openclawMcpSchemaServerPath = join(
|
||||
cliRoot,
|
||||
"dist",
|
||||
"plugins",
|
||||
"fusion-plugin-openclaw-runtime",
|
||||
"mcp-schema-server.cjs",
|
||||
);
|
||||
|
||||
export const dashboardClientStubMarker = "Dashboard assets not built";
|
||||
|
||||
@@ -28,8 +35,13 @@ function runBuildCommand(command: string, cwd: string) {
|
||||
});
|
||||
}
|
||||
|
||||
function hasBuiltDashboardAssets(): boolean {
|
||||
if (!existsSync(bundlePath) || !existsSync(clientIndexPath) || !existsSync(cursorPluginManifestPath)) {
|
||||
export function hasBuiltDashboardAssets(): boolean {
|
||||
if (
|
||||
!existsSync(bundlePath) ||
|
||||
!existsSync(clientIndexPath) ||
|
||||
!existsSync(cursorPluginManifestPath) ||
|
||||
!existsSync(openclawMcpSchemaServerPath)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user