FN-6106: block plugin view re-exports from server entries
Add an ESLint guard to keep plugin dashboard views out of server entrypoints. - add a custom fusion/no-plugin-view-reexport ESLint rule for plugin src/index.ts files - flag relative re-exports of *-view entrypoints so CSS-bearing dashboard modules stay out of Node-loaded plugin entries - document the server-entry export constraint in the plugin authoring guide Files changed: docs/PLUGIN_AUTHORING.md | 1 + eslint.config.mjs | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) Fusion-Task-Id: FN-6106 Fusion-Task-Lineage: 6bbfa073-e7fd-42a9-a332-c638b81cd55f
This commit is contained in:
@@ -763,6 +763,7 @@ The host then renders plugin views via `PluginDashboardViewHost` using the compo
|
||||
Bundled workspace plugin pattern:
|
||||
- Keep plugin package under `plugins/` (for example `plugins/fusion-plugin-roadmap`)
|
||||
- Export backend/plugin entry from `src/index.ts` and keep dashboard view exports in the plugin package (for example `./dashboard-view`)
|
||||
- Do not re-export dashboard view entrypoints (including `dashboard-view`, `manage-view`, or other `-view` modules) from `src/index.ts`; the `fusion/no-plugin-view-reexport` ESLint guard catches violations because server-side plugin entries must not transitively load CSS
|
||||
- Register the lazy dashboard component in host code (currently `packages/dashboard/app/plugins/registerBundledPluginViews.ts`)
|
||||
- CLI bundling inlines backend plugin code from workspace packages; dashboard view modules are imported by the dashboard build via the host registry
|
||||
|
||||
|
||||
@@ -69,6 +69,36 @@ const detachedSpawnGuard = {
|
||||
},
|
||||
};
|
||||
|
||||
const noPluginViewReexport = {
|
||||
meta: {
|
||||
type: "problem",
|
||||
docs: {
|
||||
description: "ban dashboard view re-exports from plugin server entry points",
|
||||
},
|
||||
schema: [],
|
||||
},
|
||||
create(context) {
|
||||
function isViewEntrypointReexportSource(value) {
|
||||
return typeof value === "string"
|
||||
&& value.startsWith(".")
|
||||
&& /(?:^|\/)[^/]*-view(?:\.(?:js|tsx))?$/.test(value);
|
||||
}
|
||||
|
||||
return {
|
||||
ExportNamedDeclaration(node) {
|
||||
if (!isViewEntrypointReexportSource(node.source?.value)) {
|
||||
return;
|
||||
}
|
||||
context.report({
|
||||
node: node.source,
|
||||
message:
|
||||
"Plugin server entry (src/index.ts) must not re-export dashboard view components. Use a dedicated subpath export (e.g. './dashboard-view') instead — see docs/PLUGIN_AUTHORING.md.",
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* ESLint Flat Config for Fusion Workspace
|
||||
*
|
||||
@@ -339,6 +369,23 @@ export default tseslint.config(
|
||||
},
|
||||
},
|
||||
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
// PLUGIN SERVER ENTRYPOINTS — keep dashboard views out of Node-loaded entries
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
{
|
||||
files: ["plugins/**/src/index.ts", "plugins/examples/**/src/index.ts"],
|
||||
plugins: {
|
||||
fusion: {
|
||||
rules: {
|
||||
"no-plugin-view-reexport": noPluginViewReexport,
|
||||
},
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
"fusion/no-plugin-view-reexport": "error",
|
||||
},
|
||||
},
|
||||
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
// AGENT SKILL TEMPLATES — template code with underscore prefix support
|
||||
// (agent prompt templates use _prefixed placeholders intentionally)
|
||||
|
||||
Reference in New Issue
Block a user