Skip to content

Declare every runtime-shimmed package for types in plugin scaffolds - #2227

Open
SawyerHood wants to merge 1 commit into
mainfrom
fix/2072-shim-type-deps
Open

Declare every runtime-shimmed package for types in plugin scaffolds#2227
SawyerHood wants to merge 1 commit into
mainfrom
fix/2072-shim-type-deps

Conversation

@SawyerHood

Copy link
Copy Markdown
Collaborator

What was wrong

bb plugin build resolves sonner, vaul, @pierre/diffs, the ten portal radix families and the host-resident clsx/tailwind-merge/class-variance-authority through an esbuild shim plus a generated export manifest, so the bundle never reads them from node_modules. A plugin's tsc has no such shim: it resolves those imports through ordinary node resolution, and nothing supplied declarations for them. The scaffold only declared the four shimmed packages its starter components happened to import (@radix-ui/react-dialog, clsx, tailwind-merge, class-variance-authority), so the documented import { toast } from "sonner" — and 12 other shimmed specifiers — failed with TS2307: Cannot find module 'sonner' in a fresh bb plugin new --app, even though bb plugin build succeeded. The shim list was also hand-copied in three places (the builder, the export-manifest generator, and the scaffold generator), and the scaffold's copy had already drifted (@pierre/diffs missing). Issue #2072; investigation report: https://get-bb.github.io/reports/issues/2072.html.

What changed

  • packages/plugin-build/src/runtime-shims.mjs (+ .d.mts): the single shim table. Plain ESM so the two generator scripts that run under bare node before any TypeScript is compiled can read it by file path (@bb/templates cannot depend on @bb/plugin-build without a workspace cycle). Exports RUNTIME_SLOT_BY_SPECIFIER, RUNTIME_SHIM_NPM_SPECIFIERS (what the export manifest introspects) and SHIMMED_TYPE_PACKAGES (the npm packages a plugin must declare for types: every shimmed package except React, whose types are @types/react*). build-plugin-app.ts, generate-runtime-export-manifest.mjs and generate-plugin-scaffold.mjs all read it; the hand-copied RUNTIME_MODULE_IDS and SHIMMED_SPECIFIERS lists are gone. turbo.json adds the file to both generate tasks' inputs.
  • packages/templates/scripts/generate-plugin-scaffold.mjs: the generated module now emits PLUGIN_SHIMMED_TYPE_DEPENDENCIES (renamed from PLUGIN_STARTER_TYPE_DEPENDENCIES) covering every shimmed package, versions mirrored from apps/app/package.json via the existing versionedDeps(). scaffoldPlugin writes all of them into an app scaffold's devDependencies.
  • bb plugin types (setPluginSdkPin in packages/templates/src/plugin-scaffold.ts): alongside the SDK pin it brings the shimmed packages' type-only devDependencies to the host's versions — repinning a drifted range, moving a copy out of dependencies, and (for bb.app plugins) adding any that are missing. --check reports each one and exits 1. bb plugin migrate is unchanged (its plan stays the SDK layout switch). The CLI prints one line per repinned package.
  • Docs: the bb-plugin-authoring skill (manifest rules, bb plugin types, the "import freely" list), the bb-cli skill, the in-CLI plugin guide (packages/templates/src/templates/bb-guide-plugins.md: command reference and the shim paragraph) and the scaffold README now say shimmed packages need a devDependencies entry for types at the host's version and never belong in dependencies.

No wire changes; HOST_DAEMON_PROTOCOL_VERSION untouched. No new plugin API members.

How you verified

  • New packages/templates/test/plugin-scaffold-shim-types.test.ts: scaffolds an app plugin, links exactly the packages its package.json declares into node_modules (no network), adds import { toast } from "sonner" to app.tsx plus a file importing every shimmed specifier (including @pierre/diffs/react), and runs the scaffold's own tsc. Against the previous generator it fails with Cannot find module 'sonner' / '@pierre/diffs/react' / ...; it passes with this change.
  • New guard in apps/cli/src/__tests__/plugin-scaffold-dependencies.test.ts: the app scaffold's devDependenciesSHIMMED_TYPE_PACKAGES, and none of them is in dependencies — derived from the build's own table, so adding a slot without declaring its types fails the test.
  • New setPluginSdkPin cases in packages/templates/test/plugin-migrate-layout.test.ts: an app plugin with a drifted sonner range, vaul in dependencies and the rest missing ends up with every shimmed package in devDependencies at the host's version and is idempotent afterwards; a headless plugin only has the shimmed packages it already declares repinned.
  • pnpm exec turbo run test --filter=@bb/plugin-build --filter=@bb/templates --filter=@bb/cli (all green), apps/server plugin-install.test.ts (uses the scaffold; green), and pnpm exec turbo run build typecheck for the whole repo (88/88).
  • Live, with this worktree's CLI build (BB_CLI_REEXEC=1 so the installed bb does not take over, isolated BB_DATA_DIR): bb plugin new toasty --apppackage.json lists all 16 shimmed packages in devDependencies; adding import { toast } from "sonner"; toast.success("hi") to app.tsxnpx tsc --noEmit exit 0; bb plugin types --check exit 0; after npm pkg set devDependencies.sonner="^0.1.0", --check prints Set "sonner" to ^1.7.4 in devDependencies — the version this bb shims at runtime and exits 1; bb plugin types prints sonner: ^0.1.0 → ^1.7.4 in devDependencies.; bb plugin build still succeeds.

Fixes #2072

AGENT GENERATED: by Claude Opus 5

`bb plugin build` swaps sonner, vaul, @pierre/diffs, the portal radix
families and the host-resident clsx/tailwind-merge/cva for runtime shims,
but a plugin's tsc resolves those imports through node_modules, and the
scaffold only declared the four packages its starter components happened
to import. The documented `import { toast } from "sonner"` therefore
failed to typecheck in a fresh `bb plugin new --app` (#2072).

- Move the shim table into packages/plugin-build/src/runtime-shims.mjs,
  plain ESM read by the builder, the export-manifest generator and the
  plugin-scaffold generator, so the three hand-copied lists cannot drift.
- Scaffold every shimmed npm package as a type-only devDependency at the
  host's version (PLUGIN_SHIMMED_TYPE_DEPENDENCIES, mirrored from
  apps/app/package.json).
- `bb plugin types` repins those devDependencies alongside the SDK pin
  (adding missing ones for app plugins, moving any out of dependencies)
  and `--check` reports the drift.
- Document the rule in the plugin-authoring skill, the plugin guide, the
  bb-cli skill and the scaffold README; guard it with a CLI test
  (scaffold devDependencies ⊇ shim list) and a templates test that runs
  the scaffold's tsc over every shimmed specifier.

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Plugin frontends cannot typecheck imports of BB-shimmed packages (sonner, vaul, most radix families)

1 participant