fix(agent-bridge): strip real implementation from production Metro bundles - #412
Open
V3RON wants to merge 2 commits into
Open
fix(agent-bridge): strip real implementation from production Metro bundles#412V3RON wants to merge 2 commits into
V3RON wants to merge 2 commits into
Conversation
…ndles @rozenite/agent-bridge required @rozenite/plugin-bridge unconditionally, so its RPC protocol code (error classes, ROZENITE_RPC_MESSAGE_TYPE, etc.) always ended up in production/release bundles, unlike every other devtools plugin. All other plugins gate their real implementation behind a react-native.ts entry point that only require()s it when NODE_ENV !== 'production', letting Metro's minifier dead-code-eliminate the require and drop the whole real-implementation chunk (and its plugin-bridge dependency) from release builds. This applies the same react-native.ts + isDev-gated require() pattern to agent-bridge, using @rozenite/vite-plugin's react-native build target to produce the same NODE_ENV-gated require()/chunk-split output as the other plugins. Since agent-bridge has no devtools panel, its own vite config only builds that one target, with a separate vitest.config.ts so tests don't go through the panel-oriented Vite plugin branches. agent-bridge is no longer part of the root/playground TS project reference graph (it now builds through vite instead of tsc emit, like the other plugins) and drops its own project reference to @rozenite/agent-bridge (already resolved via normal package exports). Verified by bundling apps/playground (which installs all plugins, including agent-bridge) via `expo export --platform ios`: all @rozenite/*-plugin identifiers and plugin-bridge's RPC/error identifiers (RozeniteProtocolError, MissingRozeniteForWebError, RozeniteHandlerError, ROZENITE_RPC_MESSAGE_TYPE) are now absent from the release bundle.
Several plugin tsconfig.json files hand-mapped `@rozenite/agent-shared` (and, in a few cases, plugin-bridge/agent-bridge/ui) to sibling source files via "paths". This bypasses the real pnpm workspace symlink and each package's own conditional `exports` map, and had gone stale: two of them (feature-flags-plugin, storage-plugin) still pointed at `agent-bridge/src/index.ts`, which no longer exists now that agent-bridge builds through react-native.ts instead of a plain src/index.ts entry. Replaced these with `"customConditions": ["development"]`, so resolution goes through the normal node_modules symlink + package.json exports conditions (falling through to the "development" condition where a package declares one, e.g. agent-shared, and to "types"/dist otherwise) — the same mechanism already used by packages extending tsconfig.base.json. Verified with a fresh `pnpm build:all`, `pnpm typecheck:all` (63/63), and `turbo run test` (54/54).
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
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.
Summary
@rozenite/agent-bridgerequired@rozenite/plugin-bridgeunconditionally at its module top level. Unlike every other devtools plugin, it had noreact-native.tsentry point gating its real implementation behindNODE_ENV !== 'production', so its RPC/protocol code (error classes,ROZENITE_RPC_MESSAGE_TYPE, etc.) always ended up in production/release Metro bundles for any app using an in-app agent tool.This applies the same shim pattern used by the other 14 plugins:
react-native.tsat the package root, exportinguseRozenitePluginAgentTool/useRozeniteInAppAgentToolasletbindings,require()d from./src/react-native/useRozeniteAgentToolonly whenNODE_ENV !== 'production', and no-ops otherwise.src/react-native/useRozeniteAgentTool.ts.@rozenite/vite-plugin'sreact-nativetarget (requirePlugin+rozeniteReactNativePlugin), which splits the gatedrequire()into its own chunk so Metro's minifier can drop it — and its@rozenite/plugin-bridgedependency — entirely from release builds. Since agent-bridge has no devtools panel, itsvite.config.tsonly builds that one target; a separatevitest.config.tskeeps tests off the panel-oriented plugin branches.package.jsonmain/module/types/exports to point atdist/react-native/index.*, matching the other plugins, so consumers get correct type hints foruseRozenitePluginAgentTool/useRozeniteInAppAgentToolresolved straight from the published.d.ts(verified end-to-end below).tscemit, like the other plugins), and 6 sibling plugins drop their now-unnecessary TS project reference to it — they already resolve its types via normal packageexports.Follow-up cleanup: several plugin
tsconfig.jsonfiles hand-mapped@rozenite/agent-shared(and, in a few cases,plugin-bridge/agent-bridge/ui) to sibling source files via"paths", bypassing the real pnpm workspace symlink and each package's own conditionalexportsmap. Two of them (feature-flags-plugin,storage-plugin) had gone stale, still pointing atagent-bridge/src/index.ts, which no longer exists now that agent-bridge builds throughreact-native.ts. Replaced all of these with"customConditions": ["development"], so resolution goes through the normal node_modules symlink + package.json exports conditions instead (falling through to each package's"development"condition where it declares one, e.g.agent-shared, and to"types"/dist otherwise).Test plan
pnpm build:all— all 32 packages build successfullypnpm typecheck:all— all 63 typecheck tasks passturbo run test— all 54 test tasks pass (agent-bridge's own 6 tests included)apps/playground(installs all 14 plugins + agent-bridge) viaexpo export --platform ios(production/release mode) and grepped the output bundle:@rozenite/*-pluginpackage identifiers: 0 occurrences (unchanged, already correct)plugin-bridgeRPC/error identifiers (RozeniteProtocolError,MissingRozeniteForWebError,RozeniteHandlerError,ROZENITE_RPC_MESSAGE_TYPE): now 0 occurrences (previously present via agent-bridge's unconditional import)apps/playground, confirmedrequire.resolve('@rozenite/agent-bridge/package.json')and thetypes/exportsmap resolve through the real workspace symlink todist/react-native/index.d.ts, and that a deliberate type error (auseRozeniteInAppAgentTool()call missing the requiredtoolfield) is correctly caught bytsc(TS2345: Property 'tool' is missing...), proving real (non-any) type hints flow through to consumers.