Keep the SDK root out of the frontend bundle - #3
Merged
Merged
Conversation
The plugin installed in the server image but its frontend bundle would not build: frontend bundle build failed: contract.ts:1:34: ERROR: Could not resolve "@get-bb/plugin-sdk" app.tsx imported two constants from contract.ts, which imports defineRpcContract from the SDK root. That put the SDK in the app bundle's graph, and the server builds that bundle against a production install where the SDK — a devDependency — has been pruned. Only @get-bb/plugin-sdk/app is shimmed for the frontend; the root never is. Every local check passed because a dev install has the SDK on disk. Move the two runtime values the frontend needs into shared.ts, which imports nothing, and leave app.tsx's contract.ts import type-only so it erases. The zod enum is now built from shared.ts's list, so the stages keep one definition. Verified by pruning dev dependencies and building: dist/app.meta.json carries neither the SDK nor zod. bundle.test.ts encodes the rule — no runtime import of the SDK root, zod, or contract.ts from the frontend graph — and fails when the original bug is put back. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The plugin reached the server image but its frontend bundle would not build, so the install failed and it never appeared in the plugin list:
app.tsximported two constants (BRIEFS_CHANGED_CHANNEL,BRIEF_STAGES) fromcontract.ts, which importsdefineRpcContractfrom the SDK root. That put the SDK into the app bundle's dependency graph — and the server builds that bundle against a production install where the SDK, a devDependency, has been pruned. Only@get-bb/plugin-sdk/appis shimmed for the frontend; the root never is.Every local check passed because a dev install has the SDK on disk. That is the whole trap.
Fix
shared.tsholds the runtime values the frontend needs and imports nothing at all.app.tsxtakes those from there, and itscontract.tsimport is now type-only so it erases completely.contract.tsbuilds its zod enum fromshared.ts's list, so the stages keep one definition rather than two that can drift.Verified the way the image does it — prune dev dependencies, then build:
and
dist/app.meta.jsoncarries neither the SDK nor zod. (Keeping zod out shrinks the bundle too; it is not shimmed and would otherwise be bundled fromnode_modules.)Regression guard
bundle.test.tsencodes the invariant: no runtime import of the SDK root, zod, orcontract.tsanywhere in the frontend graph, plusshared.tsimporting nothing. I checked it earns its keep by reintroducing the original bug — it fails — and it caught one bug in itself along the way (the word "import" inside a comment anchoring a runaway match).This is the third independent thing standing between a
bb.appplugin and this image, afterNODE_PATHand plugin-directory ownership. The first two were image problems; this one was mine.🤖 Generated with Claude Code