FN-6111: alias bundled plugin views to source entries
Keep bundled plugin dashboard views loading from source so Compound Engineering no longer falls back to the unavailable placeholder. - switch bundled dependency graph, roadmap, and compound engineering dashboard view loaders to static literal imports - add vitest aliases for dependency graph and compound engineering dashboard view source entrypoints and cover the alias contract with regression tests - document the missing-alias failure mode and the static-import requirement for bundled dashboard views Files changed: .../bundled-plugin-vite-alias-missing.md | 20 +++++++++++--------- .../__tests__/registerBundledPluginViews.test.tsx | 10 +++++++-- .../app/plugins/registerBundledPluginViews.ts | 19 +++++------------- .../runtime-plugin-alias-regression.test.ts | 21 ++++++++++++++------ packages/dashboard/vitest.config.ts | 8 ++++++++ 5 files changed, 49 insertions(+), 29 deletions(-) Fusion-Task-Id: FN-6111 Fusion-Task-Lineage: a41b893c-4c14-4a2d-b0c9-47e1dbd0e1ef
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
||||
} from "../registerBundledPluginViews";
|
||||
|
||||
const MockDependencyGraphDashboardView = () => createElement("div", { "data-testid": "dep-graph-view" });
|
||||
const MockCompoundEngineeringDashboardView = () => createElement("div", { "data-testid": "ce-view" });
|
||||
const MockRoadmapDashboardView = () => createElement("div", { "data-testid": "roadmap-view" });
|
||||
const MockCliPrintingPressWizardView = () => createElement("div", { "data-testid": "cli-printing-press-view" });
|
||||
const MockCliPrintingPressManageView = () => createElement("div", { "data-testid": "cli-printing-press-manage-view" });
|
||||
@@ -15,6 +16,10 @@ vi.mock("@fusion-plugin-examples/dependency-graph/dashboard-view", () => ({
|
||||
DependencyGraphDashboardView: (...args: unknown[]) => MockDependencyGraphDashboardView(...args),
|
||||
}));
|
||||
|
||||
vi.mock("@fusion-plugin-examples/compound-engineering/dashboard-view", () => ({
|
||||
CompoundEngineeringDashboardView: (...args: unknown[]) => MockCompoundEngineeringDashboardView(...args),
|
||||
}));
|
||||
|
||||
vi.mock("@fusion-plugin-examples/fusion-plugin-roadmap/dashboard-view", () => ({
|
||||
RoadmapDashboardView: (...args: unknown[]) => MockRoadmapDashboardView(...args),
|
||||
}));
|
||||
@@ -36,13 +41,15 @@ describe("registerBundledPluginViews", () => {
|
||||
__test_resetBundledPluginViewRegistration();
|
||||
});
|
||||
|
||||
it("registers dependency graph, roadmap, and cli printing press bundled views", () => {
|
||||
it("registers dependency graph, compound engineering, roadmap, and cli printing press bundled views", () => {
|
||||
registerBundledPluginViews();
|
||||
|
||||
// This registration is independent of engine-side plugin load success; the
|
||||
// dashboard can still render the Graph view while the plugin install row is errored.
|
||||
expect(isPluginViewRegistered("fusion-plugin-dependency-graph", "graph")).toBe(true);
|
||||
expect(getPluginViewComponent("fusion-plugin-dependency-graph", "graph")).toBeTruthy();
|
||||
expect(isPluginViewRegistered("fusion-plugin-compound-engineering", "compound-engineering")).toBe(true);
|
||||
expect(getPluginViewComponent("fusion-plugin-compound-engineering", "compound-engineering")).toBeTruthy();
|
||||
expect(getPluginViewComponent("fusion-plugin-roadmap", "roadmaps")).toBeTruthy();
|
||||
expect(getPluginViewComponent("fusion-plugin-cli-printing-press", "wizard")).toBeTruthy();
|
||||
expect(getPluginViewComponent("fusion-plugin-cli-printing-press", "manage")).toBeTruthy();
|
||||
@@ -62,6 +69,7 @@ describe("registerBundledPluginViews", () => {
|
||||
registerBundledPluginViews();
|
||||
|
||||
expect(isPluginViewRegistered("fusion-plugin-dependency-graph", "graph")).toBe(true);
|
||||
expect(isPluginViewRegistered("fusion-plugin-compound-engineering", "compound-engineering")).toBe(true);
|
||||
expect(isPluginViewRegistered("fusion-plugin-roadmap", "roadmaps")).toBe(true);
|
||||
expect(isPluginViewRegistered("fusion-plugin-cli-printing-press", "wizard")).toBe(true);
|
||||
expect(isPluginViewRegistered("fusion-plugin-cli-printing-press", "manage")).toBe(true);
|
||||
|
||||
@@ -38,24 +38,15 @@ async function loadRoadmapView(): Promise<{ default: PluginViewComponent }> {
|
||||
}
|
||||
|
||||
async function loadCompoundEngineeringView(): Promise<{ default: PluginViewComponent }> {
|
||||
// @vite-ignore + moduleId variable so tsc does NOT statically resolve/compile
|
||||
// the plugin's source here. The plugin must not depend on @fusion/dashboard
|
||||
// (workspace-acyclicity invariant), so its type-only dashboard import only
|
||||
// resolves in the plugin's own build; a literal import would make the
|
||||
// dashboard typecheck the plugin file and fail to resolve that import.
|
||||
const moduleId = "@fusion-plugin-examples/compound-engineering/dashboard-view";
|
||||
const exportName = "CompoundEngineeringDashboardView";
|
||||
try {
|
||||
const mod = await import(/* @vite-ignore */ moduleId) as unknown as Record<string, ComponentType<{ context?: PluginDashboardViewContext }>>;
|
||||
const component = mod[exportName];
|
||||
if (!component) {
|
||||
console.warn(`[plugin-views] Missing export ${exportName} from ${moduleId}`);
|
||||
return { default: createMissingPluginView(moduleId, exportName) };
|
||||
}
|
||||
return { default: component as PluginViewComponent };
|
||||
} catch {
|
||||
const mod = await import("@fusion-plugin-examples/compound-engineering/dashboard-view") as unknown as Record<string, ComponentType<{ context?: PluginDashboardViewContext }>>;
|
||||
const component = mod[exportName];
|
||||
if (!component) {
|
||||
console.warn(`[plugin-views] Missing export ${exportName} from ${moduleId}`);
|
||||
return { default: createMissingPluginView(moduleId, exportName) };
|
||||
}
|
||||
return { default: component as PluginViewComponent };
|
||||
}
|
||||
|
||||
async function loadCliPrintingPressWizardView(): Promise<{ default: PluginViewComponent }> {
|
||||
|
||||
@@ -23,11 +23,10 @@ describe("FN-3298 regression: dashboard vitest runtime plugins resolve from sour
|
||||
expect(config).not.toContain('fusion-plugin-paperclip-runtime/dist/index.js');
|
||||
});
|
||||
|
||||
// FN-3888 regression: bundled dependency-graph dashboard view must not depend
|
||||
// on plugins/fusion-plugin-dependency-graph/dist/, which goes stale when the
|
||||
// plugin source is edited without a manual rebuild and surfaces in the UI as
|
||||
// "Bundled plugin view unavailable: @fusion-plugin-examples/dependency-graph/dashboard-view".
|
||||
it("aliases dependency-graph plugin imports to src in vite and vitest configs", () => {
|
||||
// FN-3888/FN-6111 regression: bundled dashboard views must not depend on
|
||||
// plugins/*/dist/, which goes stale when plugin source is edited without a
|
||||
// manual rebuild and surfaces in the UI as "Bundled plugin view unavailable".
|
||||
it("aliases bundled dashboard view plugin imports to src in vite and vitest configs", () => {
|
||||
const testDir = dirname(fileURLToPath(import.meta.url));
|
||||
const dashboardDir = join(testDir, "..", "..");
|
||||
|
||||
@@ -41,6 +40,18 @@ describe("FN-3298 regression: dashboard vitest runtime plugins resolve from sour
|
||||
'"../../plugins/fusion-plugin-dependency-graph/src/dashboard-view.tsx"',
|
||||
);
|
||||
expect(config).not.toContain("fusion-plugin-dependency-graph/dist/");
|
||||
expect(
|
||||
config,
|
||||
`${configFile} must alias the compound-engineering dashboard-view to src`,
|
||||
).toContain('"@fusion-plugin-examples/compound-engineering/dashboard-view": resolve(');
|
||||
expect(config).toContain(
|
||||
'"../../plugins/fusion-plugin-compound-engineering/src/dashboard-view.tsx"',
|
||||
);
|
||||
expect(config).toContain('"@fusion-plugin-examples/compound-engineering": resolve(');
|
||||
expect(config).toContain(
|
||||
'"../../plugins/fusion-plugin-compound-engineering/src/index.ts"',
|
||||
);
|
||||
expect(config).not.toContain("fusion-plugin-compound-engineering/dist/");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -302,6 +302,14 @@ export default defineConfig({
|
||||
__dirname,
|
||||
"../../plugins/fusion-plugin-dependency-graph/src/index.ts",
|
||||
),
|
||||
"@fusion-plugin-examples/compound-engineering/dashboard-view": resolve(
|
||||
__dirname,
|
||||
"../../plugins/fusion-plugin-compound-engineering/src/dashboard-view.tsx",
|
||||
),
|
||||
"@fusion-plugin-examples/compound-engineering": resolve(
|
||||
__dirname,
|
||||
"../../plugins/fusion-plugin-compound-engineering/src/index.ts",
|
||||
),
|
||||
},
|
||||
},
|
||||
test: {
|
||||
|
||||
Reference in New Issue
Block a user