Skip to content

Delete core code the native app never runs - #189

Merged
arun279 merged 2 commits into
feat/expo-nativefrom
chore/core-dead-code
Oct 22, 2026
Merged

arun279 merged 2 commits into
feat/expo-nativefrom
chore/core-dead-code

Conversation

@arun279

@arun279 arun279 commented Oct 22, 2026 •

Copy link
Copy Markdown
Owner

Part of the retroactive cleanup of #24: the "Core dead code left from the web app" set from the 2026-10-21 cleanup audit, re-checked against current feat/expo-native (7f796a4) before deleting anything.

Re-verification

All five items still exist and are still unused by production code. I checked each with git grep over packages/, scripts/ and .maestro. knip doesn't flag any of them, because it counts the core tests as entry points, and knip --production lists dozens of core exports the app does use (for example parseHistorySearch), so neither result settles anything here. The grep does. Nothing was already gone. Nothing had gained a caller.

Item Status on 7f796a4
Redirect OAuth flow Dead. _layout.tsx still passes redirect: () => {}, a no-op redirectHandoff and native: true, and nothing reads native.
browser flag and unreadable-response Dead. _layout.tsx still passes browser: false, and client.ts is still the kind's only producer.
parseLibrarySearch, LibrarySearch Dead. Only its own test imported it.
routeMovieUnmark, MovieUnmarkRoute Dead. useMovieActions.ts uses resolveMovieUnmark and the durable queue's pending ops.
performance.d.ts Dead. Nothing reads rnStartupTiming.

The audit's overlap with #159 no longer applies, because #159 merged.

Deleted, and what covers the behaviour that stays

  • Redirect OAuth flow. Deleted: connectWithRedirect, completeRedirect, the redirect, redirectHandoff and native deps and state, buildAuthorizeUrl, exchangeCodeForToken, the RedirectHandoff port, and siteBaseUrl with TRAKT_SITE_BASE, which only buildAuthorizeUrl used. redirectUri stays, because Trakt's refresh grant needs it.
    • Device sign-in stays covered by the device-code tests in create-auth-store.test.ts. "connects as soon as Trakt approves, while the Keychain is still saving the token" covers the Keychain race that the deleted redirect test also covered.
    • Refresh and revoke stay covered in auth-oauth.test.ts.
    • The mock Trakt test that exchanged an authorization code to get a token for its refresh and revoke checks now gets the token from a device grant.
  • browser and unreadable-response. Deleted from TraktClient, boot.ts, create-runtime.ts, sync-contract.ts and diagnostics.ts. A rejected fetch is now always network, and an abort is still timeout. Covered by trakt-client.test.ts's "maps a fetch reject (no response) to network" and "rejects a held read as a typed timeout after the request timeout". sync-contract.test.ts keeps the server-failure copy check.
  • parseLibrarySearch. Pure dead code.
  • routeMovieUnmark. Its replacement is covered by movie-detail.test.tsx's "cancels a deferred mark after remount without reading live plays" and "does not send an item removal while a mark is in flight".
  • performance.d.ts. Pure dead code.

Parallel mechanisms left alone

The mock's web PKCE authorize page, its authorization-code grant, and the CORS block stay. The audit marks them as waiting on #157, #161 and #164, and those closed without merging, so that decision is still open. "redirects the authorize page back to the app with the caller's state intact" stays. Nothing here touches the Trakt fakes, the menus or the privacy policy copies.

Persisted cache

The witness is reseeded, not bumped: the buster stays at 435347de5bc1, so shipping users keep their cache.

  • shouldDehydrateQuery persists the library, movie-library, watchlist, users, history, calendar and genres heads, plus show/info for library shows. It persists any query that has data. TanStack copies the whole query state, so a failed refetch's error can be stored too. restorableCache clears the error on restored error-status queries, and the app reads failures only through readFailureOf's instanceof TraktReadError, which a restored plain object never passes. The app never produced unreadable-response anyway, since it always passed browser: false.
  • I ran a TypeScript check on the base: a type-level walk over the queryFn data of every persisted query factory. It found none of AuthState, AuthDeps, RedirectHandoff, TraktFailure or its unreadable-response member, TraktClientConfig, LibrarySearch or MovieUnmarkRoute. Two controls ran in the same check: a library entry nested in that data, and each deleted type planted into it. The walk found every one.

Footprint

Product-Growth: none. Product code in packages/core/src, packages/native/src and packages/native/app shrinks by 136 lines (6 added, 142 deleted), and tests by 208 lines (11 added, 219 deleted).
Binary-Size: the Hermes bundles shrink 4,975 B on iOS (5,448,542 to 5,443,567) and 5,027 B on Android (5,480,582 to 5,475,555). I measured both with expo export and scripts/measure-sizes.sh, the way the check job does, on 7f796a4 and on this branch.

pnpm check passes on Node 22.23.4.

Leftovers from the web app, each confirmed unused by production code on
current feat/expo-native:

- The redirect OAuth flow: connectWithRedirect, completeRedirect, the
  redirect, redirectHandoff and native deps and state, buildAuthorizeUrl,
  exchangeCodeForToken, the Trakt site base they alone used, and the
  RedirectHandoff port. The app signs in only by device code and passed
  no-op stubs for all of these.
- The TraktClient browser flag and the unreadable-response failure kind
  it alone produced. The app always passed browser: false.
- parseLibrarySearch and LibrarySearch.
- routeMovieUnmark and MovieUnmarkRoute, replaced by the durable queue
  lookup in useMovieActions.
- performance.d.ts, whose rnStartupTiming nothing reads.

The mock Trakt test that exchanged an authorization code to get a token
for its refresh and revoke checks now gets the token from a device
grant. The data tree changed, so the persisted-cache buster is bumped.
None of the deleted types is reachable from the data of a persisted
query, so no persisted shape changed and shipping users keep their
cache. The buster stays at 435347de5bc1; only the witness moves.
@github-actions

Copy link
Copy Markdown

Pull request footprint

measurement base to head
Product code lines in core/src, native/src, native/app, and native/modules -125
Test lines in test, packages/*/{test,__tests__,e2e}, and .maestro -189
CI and tooling lines in .github and scripts +0
Product comment lines identified by a comment prefix -2

User-delivered artifact sizes

measurement base head delta
Expo iOS JavaScript bundle, raw file 5.45 MB 5.44 MB -4.7 kB
Expo Android JavaScript bundle, raw file 5.48 MB 5.48 MB -4.7 kB
Firebase tester APK, arm64-v8a and all densities 41.16 MB 41.16 MB -4.1 kB
Play download estimate, XXXHDPI arm64-v8a English Android 15 19.83 MB 19.83 MB -1.8 kB

Most complex product function

measurement base head
Cyclomatic complexity, oxlint complexity 10 10
Cognitive complexity, Biome noExcessiveCognitiveComplexity 15 15

@arun279 arun279 left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Media review on 87c2030: pr-media compared all 106 screens against base d104d36 and found none changed. That is expected for deleting dead code. The persisted cache is reseeded rather than bumped, so shipping users keep their cache; the type-level evidence is in the PR body.

@arun279
arun279 merged commit dfad4ee into feat/expo-native Oct 22, 2026
24 checks passed
@arun279
arun279 deleted the chore/core-dead-code branch October 22, 2026 20:23
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.

1 participant