Track the 1.x SDK, and stop hijacking npm installs from Metro - #43
Merged
Conversation
Metro resolver: the redirect added in #42 fired unconditionally, so the package resolved to ../../sdk-react-native/src for ANYONE with a sibling checkout — silently running unreleased local code instead of the pinned version — and resolved to a non-existent path for anyone without one. Caught while verifying the example against the published SDK: it kept reporting unreleased behaviour. Now gated on the node_modules entry actually being a symlink, which is exactly what distinguishes `pnpm add link:` from an install. Verified both ways round: npm install emits app://Wallet (1.0.0), a link emits app://com.formo.analytics.demo/Wallet. Dependency: ^0.1.6 -> ^1.0.0. The caret meant 0.1.6 could never pick up 1.x, so the example was two majors behind. App identity now comes from app.json via expo-constants instead of a hardcoded copy. config/formo.ts claimed version 1.1.0 while app.json said 1.0.0 — and these reach Formo as `app_version` and as the mobile `origin`, so the drift meant every event reported a version the app never had. The test asserted the literal 1.1.0, which is how it went unnoticed; it now asserts the two agree. Kept the explicit app config rather than relying on auto-detection: in Expo Go the native modules report EXPO GO's bundle id and version, and on React Native Web nothing resolves a bundle id at all. README: screen() takes (name, category?, properties?) — the example passed an object where the category string goes, which would have sent [object Object]. 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.
Follow-up to #42. Found while checking whether this example needs updating for the mobile analytics work — and it turned up a bug I introduced in #42.
The Metro bug (the important one)
The resolver redirect added in #42 fires unconditionally:
So the package resolves to
../../sdk-react-native/srcfor anyone with a sibling checkout, silently running unreleased local code instead of the pinned npm version — and resolves to a non-existent path for anyone without one. CI didn't catch it because thewith-react-nativejob lints and tests but never bundles.I hit it directly: after pinning the dependency back to the published
1.0.0, the app kept emittingDeep Link Openedand the newapp://<bundle>/<screen>URL — neither of which exists in 1.0.0. I nearly reported that as "verified against the published SDK".Now gated on the
node_modulesentry actually being a symlink, which is precisely what distinguishespnpm add link:from an install. Verified both directions:page_urlemittedpnpm install(npm 1.0.0)app://Walletpnpm add link:../../sdk-react-nativeapp://com.formo.analytics.demo/WalletDependency:
^0.1.6→^1.0.0The caret on a
0.xversion can never resolve to1.x, so the example was pinned two majors behind and none of the 1.0 behaviour was being demonstrated.App identity comes from
app.jsonnowconfig/formo.tshardcodedversion: "1.1.0"whileapp.jsonsaid1.0.0. These reach Formo asapp_versionand as the mobileorigin, so the drift meant every event reported a version the app never had — indefinitely, and invisibly.Now read from
app.jsonthroughexpo-constants(already a dependency). The existing test asserted the literal"1.1.0", which is exactly how the drift went unnoticed; it now asserts the two agree, plus that the iOS bundle identifier and Android package match (the SDK sends onebundleIdfor both, so a mismatch would make one app report two origins).The explicit
appconfig is deliberately kept rather than relying on auto-detection: in Expo Go the native modules report Expo Go's own bundle id and version, and on React Native Web nothing resolves a bundle id at all.README
screen()takes(name, category?, properties?). The example passed an object where thecategorystring goes, which would have sent[object Object]as the category.Verification
14 tests pass (was 13), typecheck clean, and
expo start --webbundles and runs in both install modes.Not included
Demos of the new lifecycle APIs (
pushNotification*, crash tracking,Application Foregrounded) — they aren't in a published release yet. Worth a follow-up once the SDK ships them.Also still open:
expo prebuildfails outright becausetar@7is hoisted where Expo 52 expects tar v6's API, so no one can build a dev client from this example. Separate issue.🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.