fix(deps): pin react-native to 0.85.3 via pnpm.overrides #232
No reviewers
Labels
No labels
area:auth
area:ci
area:db
area:infra
area:native
area:pwa
area:service
epic
feature
foundation
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
james/carol!232
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix-rn-dedupe"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Follow-up to PR #231. The
react+react-domoverrides shipped there pinned the bundle to 19.2.3, but Expo Go still reported the React-version mismatch. Investigation found a second react-native version in the workspace.Root cause
@carol/api-clientdeclares@react-native-community/netinfoandreact-nativeas optional peer deps with the wildcard*version range. When pnpm resolves api-client into the workspace, its peer resolver picks the latest matching for each peer —react-native@0.86.0for netinfo's peer, not the workspace-pinned0.85.3.Result: two
react-nativesub-graphs innode_modules/.pnpm/:Expo Go's renderer is built against
react-native@0.85.3exactly, so anything else in the bundle triggers the React-version-mismatch error at runtime. The earlier React-version overrides didn't help because the mismatch was downstream, in the RN sub-graph.Fix
Add
react-native: 0.85.3to rootpnpm.overrides. Forces every consumer — including api-client's optional peer-dep resolution — to the workspace's pinned version. The optional-peer declaration inapi-clientstays intact (it's still the correct intent).Verified
Test plan
pnpm install --frozen-lockfileclean.react-native@0.86references inpnpm-lock.yaml.pnpm -F @carol/client export:websucceeds; rebuilt bundle has only React 19.2.3.Forward compatibility
When Expo SDK 57 lands and bumps
react-nativeto the next major, bump the override here in the same PR (and the workspace pins inapps/client).📊 Test coverage
Patch coverage: no testable lines changed.
Overall (
app/,lib/,db/, excluding UI per ADR-0019):Soft thresholds per ADR-0019. Coverage is informational and does not block merge.
Trivy (container image)
Threshold:
high· Total findings: 121 · At/above threshold: 16.27.0, 7.28.0, 8.5.0`useMe()` runs under the (app)/_layout auth gate. The QueryClient defaults staleTime to 30s, so a pre-login 401 stays cached when the post-login navigation lands. The layout reads the stale error, redirects to /login, and the app bounces straight back to where it started — even though the bearer tokens are now in SecureStore. Invalidate `keys.auth.me` right before `router.replace("/notes")`. The layout's first read re-queries with the fresh Authorization header and sees the actual user.Carol's translation catalog at packages/i18n/messages/*.json uses ICU single-brace interpolation ({email}, {url}) — the same shape next-intl already consumes on the API side. i18next defaults to double-brace {{var}}, so every interpolated string rendered literal: "Signed in as {email}." instead of the email, "Connected to {url}." instead of the server URL. Override interpolation.prefix and .suffix to "{"/"}" so the same catalog works in both runtimes.SecureStore.getItemAsync hops to the native bridge on every call — ~5-15ms on Android. The bearer-header middleware fires per HTTP request, so a screen with four queries pays that four times on mount and again on each re-fetch. Caching the value in JS memory after the first read removes the per-request bridge hop without weakening storage durability — the token still lives in EncryptedSharedPreferences / Keychain. Cache is sentinel-undefined ("not loaded") vs null ("no token") vs string ("token present") so we don't confuse a fresh-mount with a known-empty state. setAccessToken updates the cache after writing through; clearTokens nulls it. The same hot path on web is a no-op (cookies cover auth on same-origin) so no behaviour change there.