From 281bb051611f62957dbe1d7fa3d4a261a8dd6a36 Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Mon, 13 Jul 2026 07:32:50 -0700 Subject: [PATCH] FN-7936: alias @fusion/core to a runtime shim in bundled plugin outputs Fix bundled example plugins (dependency-graph, grok-runtime, roadmap, acp-runtime, compound-engineering) crashing on enable with "Cannot find package '@fusion/core'" by aliasing the private import to a self-contained runtime shim during CLI bundling. - packages/cli/tsup.config.ts: drop @fusion/core from bundlePluginEntry's external list and alias it to the existing pluginSdkCoreRuntimeShim so bundled.js no longer references the private workspace package at runtime - packages/cli/src/__tests__/bundle-output.test.ts: add a regression test asserting every staged bundled plugin's bundled.js contains no bare @fusion/core import/reference - docs/PLUGIN_AUTHORING.md: document that bundled.js outputs must be self-contained and must not leak private @fusion/* workspace imports - .changeset/fn-7936-bundled-plugin-fusion-core-external.md: add a patch changeset for @runfusion/fusion describing the fix Files changed: .changeset/fn-7936-bundled-plugin-fusion-core-external.md | 7 +++++ docs/PLUGIN_AUTHORING.md | 3 +++ packages/cli/src/__tests__/bundle-output.test.ts | 30 ++++++++++++++++++++++ packages/cli/tsup.config.ts | 9 +++++-- 4 files changed, 47 insertions(+), 2 deletions(-) Fusion-Task-Id: FN-7936 Fusion-Task-Lineage: a8a391b2-9441-4a7c-92bc-f1675e1a8a0d Co-authored-by: Fusion (runfusion.ai) --- ...936-bundled-plugin-fusion-core-external.md | 7 +++++ docs/PLUGIN_AUTHORING.md | 3 ++ .../cli/src/__tests__/bundle-output.test.ts | 30 +++++++++++++++++++ packages/cli/tsup.config.ts | 9 ++++-- 4 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 .changeset/fn-7936-bundled-plugin-fusion-core-external.md diff --git a/.changeset/fn-7936-bundled-plugin-fusion-core-external.md b/.changeset/fn-7936-bundled-plugin-fusion-core-external.md new file mode 100644 index 0000000000..cb5c952caa --- /dev/null +++ b/.changeset/fn-7936-bundled-plugin-fusion-core-external.md @@ -0,0 +1,7 @@ +--- +"@runfusion/fusion": patch +--- + +summary: Fix bundled example plugins failing to enable with a missing @fusion/core package error. +category: fix +dev: Aliases bundlePluginEntry @fusion/core imports to pluginSdkCoreRuntimeShim for self-contained bundled.js outputs. diff --git a/docs/PLUGIN_AUTHORING.md b/docs/PLUGIN_AUTHORING.md index 4e2764d33b..060bb4dece 100644 --- a/docs/PLUGIN_AUTHORING.md +++ b/docs/PLUGIN_AUTHORING.md @@ -767,6 +767,9 @@ Bundled workspace plugin pattern: - 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 + +Bundled `bundled.js` outputs must be self-contained at runtime. Do not leave private workspace package imports such as `@fusion/core` in emitted bundled plugin code; `@fusion/plugin-sdk` core runtime re-exports are resolved through the CLI runtime shim during packaging. + ### Bundled plugin build-freshness guard diff --git a/packages/cli/src/__tests__/bundle-output.test.ts b/packages/cli/src/__tests__/bundle-output.test.ts index 092d810458..58ad6d3957 100644 --- a/packages/cli/src/__tests__/bundle-output.test.ts +++ b/packages/cli/src/__tests__/bundle-output.test.ts @@ -12,8 +12,16 @@ import { } from "./bundle-output-helpers"; import { resolveClaudeCliExtensionFromModuleUrl } from "../commands/claude-cli-extension"; import { resolveDroidCliExtensionFromModuleUrl } from "../commands/droid-cli-extension"; +import { RUNTIME_PLUGIN_IDS } from "../plugins/staged-bundled-plugin-ids"; const tsupConfigPath = join(cliRoot, "tsup.config.ts"); +const bundlePluginEntryPluginIds = [ + ...RUNTIME_PLUGIN_IDS, + "fusion-plugin-dependency-graph", + "fusion-plugin-roadmap", + "fusion-plugin-compound-engineering", + "fusion-plugin-linear-import", +] as const; describe("CLI bundle output", () => { beforeAll(() => { @@ -222,6 +230,28 @@ describe("CLI bundle output", () => { expect(stagedPkg.dependencies?.["@fusion/core"]).toBeUndefined(); }); + it("bundled plugin outputs do not import private @fusion/core at runtime", () => { + const inspectedPluginIds: string[] = []; + + for (const pluginId of bundlePluginEntryPluginIds) { + const bundledPath = join(cliRoot, "dist", "plugins", pluginId, "bundled.js"); + if (!existsSync(bundledPath)) { + continue; + } + + inspectedPluginIds.push(pluginId); + const bundled = readFileSync(bundledPath, "utf-8"); + expect(bundled, `${pluginId} should not keep a bare @fusion/core import`).not.toMatch( + /from\s+["']@fusion\/core["']/, + ); + expect(bundled, `${pluginId} should not mention the private @fusion/core package`).not.toContain( + '"@fusion/core"', + ); + } + + expect(inspectedPluginIds.length).toBeGreaterThan(0); + }); + it("dist/plugins/fusion-plugin-whatsapp-chat/ is staged with a valid manifest", () => { const stagedRoot = join(cliRoot, "dist", "plugins", "fusion-plugin-whatsapp-chat"); const manifestPath = join(stagedRoot, "manifest.json"); diff --git a/packages/cli/tsup.config.ts b/packages/cli/tsup.config.ts index d52d18aec2..de42ecb21d 100644 --- a/packages/cli/tsup.config.ts +++ b/packages/cli/tsup.config.ts @@ -42,6 +42,7 @@ const compoundEngineeringPluginSrc = join(__dirname, "..", "..", "plugins", "fus const compoundEngineeringPluginDest = join(__dirname, "dist", "plugins", "fusion-plugin-compound-engineering"); const linearImportPluginSrc = join(__dirname, "..", "..", "plugins", "fusion-plugin-linear-import"); const linearImportPluginDest = join(__dirname, "dist", "plugins", "fusion-plugin-linear-import"); +const pluginSdkCoreRuntimeShim = join(__dirname, "src", "plugin-sdk-core-runtime-shim.ts"); const dashboardClientStub = ` @@ -174,9 +175,14 @@ async function bundlePluginEntry({ pluginId, srcDir, destDir, withMcpAsset = fal platform: "node", target: "node22", outfile: join(destDir, "bundled.js"), - external: ["@fusion/core", "@fusion/engine"], + external: ["@fusion/engine"], alias: { "@fusion/plugin-sdk": join(__dirname, "..", "plugin-sdk", "src", "index.ts"), + /* + * FNXC:BundledPlugins 2026-07-13-00:00: + * FN-7936 / issue #2059 requires every published bundled.js to be self-contained. The plugin-sdk source re-exports WORKFLOW_EXTENSION_SCHEMA_VERSION, workflowExtensionRegistryId, and createBoardActionServices from private @fusion/core; resolve those runtime values to the shared shim here so npm-installed bundled plugins never crash with Cannot find package '@fusion/core'. + */ + "@fusion/core": pluginSdkCoreRuntimeShim, }, logLevel: "warning", }); @@ -274,7 +280,6 @@ function assertAllStagedBundledPluginsLoadable() { } const pluginSdkEntry = join(__dirname, "..", "plugin-sdk", "src", "index.ts"); -const pluginSdkCoreRuntimeShim = join(__dirname, "src", "plugin-sdk-core-runtime-shim.ts"); const cliBuildConfig = { entry: ["src/bin.ts", "src/extension.ts"],