Contributions
31 PRs merged across 10 upstream repos. Plus a public patches repo with 88 drop-in fixes for Bun, npm, and pnpm. I find the bug, file the upstream PR, and drop the patch into the repo so my projects, and anyone else hitting the same bug, can ship without waiting for the merge to land. When the fix lands in a release, I bump the dep and delete the patch. Every merged PR listed here shipped as a patch first.
Merged PRs
- expo/expo (10 PRs):
- #45403
getPackageByNamedid apackages/<name>/package.jsonlookup, which misses for scoped packages whose dir name differs from the package name (@expo/uilives atpackages/expo-ui/,@expo/app-integrityatpackages/expo-app-integrity/). On a miss,Workspace.getInfoAsyncrecorded emptyworkspacePeerDependenciesfor those packages, soupdateWorkspaceProjectsnever rewroteworkspace:*to the canary version, and the published canary tarballs shippedpeerDependencies.expo: "workspace:*".bun add @expo/ui@canaryerrored withWorkspace dependency "expo" not foundandnpm install @expo/ui@canaryerrored withEUNSUPPORTEDPROTOCOL. Fix keeps the existing path-based fast path and falls back to scanningcachedPackagesbynamefield when the path lookup misses. Same root cause as #44412, different call site - #44652
scrollPositionandidmodifiers (iOS 17+) binding aScrollView’s leading target to JS viauseNativeStateand the worklet.valuewrite path. Readingstate.valuereturns the id of the leading target; writing scrolls to the matching view. The optionalonChangecallback fires on the JS thread when the leading target changes.id(string)marks views as scroll targets and works onScrollView,LazyVStack, andLazyHStack. Built on the worklet infrastructure from #44214 and #44215. Deferred from #43955 per @intergalacticspacehighway - #44548
textContentTypemodifier wrapping SwiftUI’stextContentType(_:)with all 45UITextContentTypevalues. Wires@expo/uiTextFieldandSecureFieldinto iOS keychain autofill for passwords, emails, addresses, credit cards, and OTP codes. Before this,@expo/uitext fields could not participate in iOS autofill at all. Includes#availableguards for the iOS 17+ values (creditCardExpiration,birthdate, etc.) and iOS 17.4+ values (cellularEID,cellularIMEI) - #44547
textInputAutocapitalizationmodifier (iOS 15+) with all fourTextInputAutocapitalizationmodes:never,words,sentences,characters. Before this, the only way to disable auto-capitalization on@expo/uiTextFieldwas forcingkeyboardType="ascii-capable", which changed the keyboard layout entirely. Username and email fields can now behave correctly without that workaround - #43958
PersistentFileLog.readEntriesrace condition where reads bypassed theserialQueuethat guards every write. Caused flakyUpdatesLogReaderTests.PurgeOldLogsfailures inexpo-updatesCI when a read executed before a queued write flushed to disk and returnedentries1.count == 1instead of2. Fix wrapsreadEntriesinserialQueue.syncso reads wait for pending writes. No deadlock risk because all callers are external to the queue - #43955
scrollTargetBehaviorandscrollTargetLayoutmodifiers (iOS 17+) for paging and view-aligned scroll snapping in@expo/uiScrollView. Brings SwiftUI’s snap-paging API to React Native through@expo/uimodifier composition with#availableguards for iOS 17, tvOS 17, and macOS 14 - #43923
defaultScrollAnchorForRolemodifier (iOS 18+) wrapping the two-parameterdefaultScrollAnchor(_:for:)overload. Lets you set independent scroll anchors perScrollAnchorRole(initialOffset,sizeChanges,alignment), so a chat view can anchor to bottom globally but start at top via a per-role override. Also addednullsupport to match Apple’sUnitPoint?signature and the missing@platform macos 14.0+JSDoc to the single-arg version from #43914 - #43914
defaultScrollAnchormodifier (iOS 17+) for controlling where aScrollVieworListstarts. Removes the need forscaleEffect(y: -1)flips, reversed data arrays, and inverted scroll indicator hacks that chat UIs used to need. Reuses the existingUnitPointOptionsenum and falls back to a no-op on iOS < 17 - #43228 per-axis
scaleEffectaccepting{ x, y }in addition tonumber. Backwards-compatible:scaleEffect(0.5)still normalizes to{ x: 0.5, y: 0.5 }in the TS layer before hitting native - #43158
ClipShapeModifierandMaskModifierwere silently renderingRectanglefor any shape other thancircleorroundedRectanglebecause they used a rawStringfield instead of theShapeTypeenum from #40748. Every other shape modifier (BackgroundModifier,ContainerShapeModifier,ContentShapeModifier,GlassEffectModifier) already usedShapeType. Switched both to exhaustiveShapeTypeswitching with nodefaultfallthrough, addedroundedCornerStyleandcornerSizefields, and unblockedcapsuleandellipseinclipShape()andmask()
- #45403
- get-convex/better-auth (5 PRs):
- #218 four bugs causing stale auth state and incorrect
isAuthenticatedvalues. (1)getCookie()parsed cookies from JSON, which turnedexpiresinto a string. Comparingstring < new Date()coerced the Date to a number and the string toNaN, andNaN < anythingis alwaysfalse, so expired cookies were never filtered out. (2) Cookies persisted after/get-sessionreturnednull, so combined with bug 1, stale credentials shipped indefinitely. (3) Sign-out stored"{}"inlocalCacheNameandJSON.parse("{}")returns truthy{}, breakingif (sessionData)checks. Fix stores"null"soJSON.parse("null")returnsnull. (4)isAuthenticatedwassession !== null, which returnedtruefor{}(from bug 3) andundefinedduring loading edges. Fix usesBoolean(session?.session) - #245 widened the
better-authpeer dep from exact1.4.9to>=1.4.9 <1.5.0after verifying every import path is stable across 1.4.9 through 1.4.18. Explicitly excludes 1.5.0, which movedcreateAuthEndpointandcreateAuthMiddlewarefrombetter-auth/pluginstobetter-auth/api, removed thebetter-auth/adapters/testexport path, and deletedrunAdapterTestentirely - #267 concurrent
fetchAccessTokendedup withuseRef. On page load,sessionIdtransitions fromundefinedto a value, which creates a newfetchAccessTokenreference and triggersConvexProviderWithAuthto callsetAuth()again while the first request is still in-flight. React 18 StrictMode doubles this in dev. Each/convex/tokencall hits the DB for session middleware and runs JWT signing, so N concurrent calls meant N redundant round-trips with only one result used. Fix stores the in-flight promise in auseRefso concurrent callers share it, withforceRefreshToken: truebypassing the guard and.finally()clearing the ref after resolution. Closes #219, likely reduces the action count reported in #186 - #278 removed the dead
react-dompeer dep declaration. Zero imports ofreact-dom,ReactDOM,createRoot,hydrateRoot,flushSync, orcreatePortalacross all 32 files insrc/. None of the exports (/react,/nextjs,/react-start) touch it. The declaration was generating peer dep warnings inbunandpnpmprojects that don’t usereact-dom - #323 migrated
@convex-dev/better-authtobetter-auth1.6.7+, fixing five runtime breaks across the 1.6.x line in one rebase.Where.modefolding (1.6.0):CleanedWhere = Required<Where>forced the new field onto every adapter call, soadapterWhereValidatorand per-table validators threwArgumentValidationErroron bump. Fix acceptsmodein validators, case-foldseq/ne/in/not_in/contains/starts_with/ends_withinfilterByWhere, and excludes insensitive clauses fromfindIndexandpaginatefast-paths since Convex indexes are byte-compared.shouldReturnResponseflip (1.6.0, commit8304f65):to-auth-endpoints.tsdefaults to aResponsewhen context carries aRequest, so internal endpoint calls from cross-domain hooks returned aResponseinstead of a parsed object, JWT cookies got the literal string"undefined", andsetSessionCookiecrashed. Fix passesasResponse: falseat all 7 internal call sites with regression tests that pre-set the flags totrueso dropping the override fails the assertion.twoFactor.verified(1.6.2, #8711): new schema column the Convex validator rejected.parseSetCookieHeader: deleted the 34-line local copy incross-domain/client.tsthat split on", "and shatteredExpires=Wed, 21 Oct 2015 07:28:00 GMTinto four garbage cookies, re-exported frombetter-auth/cookies../instrumentation(1.6.6, #9111): peer floor raised to 1.6.7 where #9281 routes the dynamicimport("@opentelemetry/api")to a noop onbrowserandedgeconditions, fixing Convex V8 isolate’s synchronous bare-specifier rejection. Shipped in@convex-dev/better-auth@0.12.0
- #218 four bugs causing stale auth state and incorrect
- shadcn-ui/ui (5 PRs):
- #10396 added the TanStack Start dark mode guide to the official shadcn docs, the fifth framework-specific guide after Next.js, Vite, Astro, and Remix. The canonical pattern was scattered across Discord threads and three stale PRs with different tradeoffs: #7173 (cookies, no system mode), #7490 (cookies, conditional
ScriptOnce), and #9096 (wrappedtanstack-theme-kitas a runtime dep). Pattern:ScriptOncefrom@tanstack/react-routerfor the pre-hydration inline script, a React context for post-hydration state,suppressHydrationWarningon<html>,document.documentElement.style.colorSchemeso native UI respects the theme, and aprefers-color-schemelistener for system mode. In review, @shadcn refactored the inline script string into agetThemeScript(storageKey, defaultTheme)function so custom provider props reach the pre-hydration pass, extracted the class-swap into anapplyThemehelper, and added amountedgate so the inline script’s work isn’t overwritten on first mount - #10369
notFoundComponenton the Start root route in thestart-appandstart-monorepotemplates. Silences the TanStack Router warning that fires on first load from phantom requests hitting/favicon.icoand Chrome DevTools’/.well-known/appspecific/com.chrome.devtools.jsonwhen neithernotFoundComponentnordefaultNotFoundComponentis configured. JSX shape matches the existing 404ErrorBoundarypattern fromtemplates/react-router-appandtemplates/react-router-monorepo(samecontainer mx-auto p-4 pt-16wrapper, same “404” heading and “The requested page could not be found.” copy) so the ten-template suite stays consistent - #10337 fixed
llms.txt404s and backfilled missing routes so LLM crawlers can index the full docs site - #9484 raw
<ComponentsList />tag leaking into copy-to-markdown output on component pages - #9331 registered the
@ramonclaudio-coderabbitshadcn registry in the official open source directory after #8892 asked for it. Adds entries toapps/v4/public/r/registries.jsonandapps/v4/registry/directory.jsonso the registry is discoverable through the shadcn CLI. The registry itself ships a framework-agnostic CodeRabbit API client, pluggable storage adapters (LocalStorage, Convex, Supabase, PostgreSQL, MySQL), and React components for generating developer activity reports
- #10396 added the TanStack Start dark mode guide to the official shadcn docs, the fifth framework-specific guide after Next.js, Vite, Astro, and Remix. The canonical pattern was scattered across Discord threads and three stale PRs with different tradeoffs: #7173 (cookies, no system mode), #7490 (cookies, conditional
- better-auth/better-auth (3 PRs):
- #9281 serve a noop
./instrumentationvia conditional exports forbrowserand edge runtimes, matching the shape./async_hooksalready uses. The dynamicimport("@opentelemetry/api")inpackages/core/src/instrumentation/api.tsthrew synchronously on runtimes like Convex’s V8 isolate (bare specifiers rejected at resolve time viadeno_core::resolve_import), so the.catch()ingetOpenTelemetryAPInever ran and everywithSpancall throughto-auth-endpoints.tsandwith-hooks.tssurfaced an uncaught error. The breaking pattern landed in#9111and shipped in v1.6.6.@opentelemetry/apiitself ships a noop proxy when no SDK is registered, so this is about dynamic-import-probe portability, not OTel runtime support. Unblocks the 1.6 migration for@convex-dev/better-authconsumers - #9087 add
/change-passwordand/revoke-other-sessionsto theatomListenersmatcher so$sessionSignalfires after session-rotating endpoints. Without this, callers likeuseSession()kept returning stale session data after password changes because the client never re-fetched. Companion to get-convex/better-auth#329 which invalidates the Convex adapter’s cached JWT on the same events - #9072 incorrect
operationIdin the password reset callback endpoint, plusforgettoforgotcleanup across demo apps and tests
- #9281 serve a noop
- withastro/compiler-rs (2 PRs):
- #25 real fix for the
@astrojs/compiler-rsGLIBC_2.35issue. #22 added-xto the linux-gnu builds hoping zigbuild would pin glibc, but zigbuild without an explicit suffix falls back to zig’s per-arch baseline (GLIBC_2.35on x86_64,GLIBC_2.30on aarch64 for zig 0.15), so the shipped 0.1.7 binary still couldn’t load on Vercel (glibc 2.34), Amazon Linux 2023, AWS Lambda, RHEL/CentOS 7, or Debian 10. Switched both gnu targets to--use-napi-cross, which downloads@napi-rs/cross-toolchainwith a sysroot pinned to glibc 2.17. Matches the pattern used byoxc,@swc/core,@napi-rs/canvas,lightningcss, and the official@napi-rs/package-template. Verified on a fork CI run plus a Vercel preview deploy withexperimental.rustCompiler: true, bothobjdump -TshowingGLIBC_2.16max on x64 andGLIBC_2.17on arm64. Shipped in@astrojs/compiler-rs@0.1.8 - #22 first-attempt glibc compat fix, added
-xtox86_64-unknown-linux-gnu. Turned out to be insufficient, superseded by #25
- #25 real fix for the
- napi-rs/napi-rs (1 PR): #3189 cross-compile regression in the v3 CLI rewrite. When
--cross-compile/-xwas passed for a linux or darwin target,pickBinary()incli/src/api/build.tsskippedcargo-zigbuildif host platform, arch, and abi matched target, logged a warning, then silently fell through tocargo build. The whole point of--cross-compileon a native build is to pin a lower glibc via zig’s linker. Without it, buildingx86_64-unknown-linux-gnuonubuntu-latest(glibc 2.39) produced binaries incompatible with glibc < 2.35 systems like Amazon Linux 2023 (glibc 2.34) and Vercel’s build container. v2 had this fix in #1432 (resolving #1430) but it wasn’t carried over during the v3 rewrite in #1492. Fix removes the platform-match conditions in theelsebranch ofpickBinary()so--cross-compilealways usescargo-zigbuildfor non-Windows targets - oven-sh/bun (1 PR): #21855 added the
decompressproperty to theBunFetchRequestInitinterface with JSDoc documentation. The option already worked at runtime in Bun’sfetch(), but TypeScript users had to@ts-ignoreit on every call to disable response decompression. Now it’s a first-class typed option, no escape hatch required - fuma-nama/fumadocs (2 PRs):
- #2092 fixed the TanStack Start template in
create-fumadocs-app. Wired thevite-reactplugin with the requiredcustomViteReactPlugin: trueflag, configured a customNotFoundcomponent for TanStack Router, and bumped deps to current versions. Resolved four issues at once: TanStack Startvite-reactplugin warning, missing custom 404 component warning, module resolution errors during client-side navigation, and React hydration errors caused byuseMemonull references that flashed errors mid-route-change - #2095 prettier formatting fix that unblocked the changesets release PR #2093 for
create-fumadocs-app@15.7.0. The release PR was stuck on a formatting check, so I ran the formatter and shipped the diff so the release could go out
- #2092 fixed the TanStack Start template in
- rorkai/App-Store-Connect-CLI (1 PR): #784 Mac App Store screenshot support for the
ascCLI. New--provider macosgrabs the frontmost window of a running macOS app by bundle ID usingscreencapture -l <windowID>, where the window ID comes from a Swift one-liner piped toswift -viaCGWindowListCopyWindowInfo, without cgo or extra binaries. New--device macrenders to the 2880x1800APP_DESKTOPcanvas without a device bezel, with optional title, subtitle, and background color overlays. Also fixedASC_TIMEOUTbeing silently ignored forscreenshots captureandscreenshots frame, both now useContextWithTimeout - TanStack/db (1 PR): #17 corrected the stale README link to the example todo app, repointing it at
examples/react/todo. Tiny fix, but it was the first thing I clicked when I landed on the repo and it 404’d. Was PR #17 in the repo, early days
Patches
Open (PRs still awaiting upstream merge):
@expo/ui56.0.0-canary-20260506-03817f5:Alertcomponent wrapping SwiftUI’s iOS 15.alert(_:isPresented:actions:message:), withAlert.Trigger,Alert.Actions, and optionalAlert.Messageslots. MirrorsConfirmationDialog’s shape soisPresentedbindings andButtonactions compose the same way. expo/expo#45700@convex-dev/better-auth0.12.2: wrapfetchAccessTokeninnew Promise(executor)souseConvexAuth().isAuthenticatedflips after sign-in on Hermes V1. Expo SDK 56 canary dropped@babel/plugin-transform-async-to-generatorfrom the Hermes V1 preset (#45345), exposing a bridge race the transform’s extra tick was hiding. The explicitnew Promiserestores that one-tick delay, so back-to-back auth state changes no longer race the websocket reconnect. get-convex/better-auth#368shadcn4.7.0: strip C0 control characters (0x00-0x1F) and DEL (0x7F) frompromptstext input values. Cmd+Delete on macOS sends Ctrl+U (NAK) whichpromptsinserts as a literal byte, creating directories like\x15my-app. shadcn-ui/ui#10364better-auth1.6.9: preserve the current session on/change-passwordwhenrevokeOtherSessionsis set. Without this, the rotating endpoint’s bulk-delete loop also wipes the row that was just minted for the active caller, so the response sets a session cookie pointing at a row that no longer exists and the next request 401s. better-auth/better-auth#9345@hugeicons/react1.1.6:core-free-iconssubpath type shim so TypeScript stops complaining about the bundled icon set undernode16,nodenext, andbundlerresolution without forcing a paid tier. Also stops Vite dev from pre-bundling the 6.2 MB barrel for the 33 KB you actually use. hugeicons/react#5bun1.3.13: two PRs. oven-sh/bun#27085 fixesincludePrereleasesemantics in peer dep semver validation. oven-sh/bun#27086 fixes invalid YAML in theupdate-root-certsworkflowlabelsfield
Dropped (PR merged, patch no longer needed):
expocanary-20260506-964f25d: #45403better-auth1.6.2->1.6.5: #9087@expo/ui56.0.0-canary-20260212-4f61309->56.0.0-canary-20260305-5163746: #43158, #43228@expo/ui56.0.0-canary-20260212-4f61309->56.0.0-canary-20260401-5e87ef7: #43914, #43923@expo/ui56.0.0-canary-20260212-4f61309->56.0.0-canary-20260409-6fc2991: #43955, #44547, #44548expo-modules-core56.0.0-canary-20260212-4f61309->56.0.0-canary-20260402-87c5ce2: #43958@convex-dev/better-auth0.10.10->0.10.11: #218, #245@convex-dev/better-auth0.10.11->0.10.12: #267@convex-dev/better-auth0.10.12->0.10.13: #278@convex-dev/better-auth0.11.5->0.12.0: #323bun1.2.20->1.2.21: #21855create-fumadocs-app15.6.4->15.6.5: #2092, #2095convex1.31.3->1.31.4(not my PR):WebSocketManageraddEventListenerguard, patched while reporting (baafbf5)jose6.0.3->6.0.4:process.getBuiltinModuleremoved from webapi dist for Edge Runtime compat (panva/jose#752)@shopify/mini-oxygen4.0.0(not my PR, fix in next release): Shopify/hydrogen#3617 Environment API (Vite 6/7/8 backward compat) supersedes my rebase #3493, which picked up @thomasKn’s stalled #3417. Siblings@shopify/hydrogen2026.1.0,@shopify/hydrogen-react2026.1.0,@shopify/cli-hydrogen11.1.9dropped with it
Issues I filed upstream
- panva/jose#752
process.getBuiltinModulemisuse broke Edge Runtime and Next.js middleware. Traces convinced @panva the bug was real, fixed inv6.0.4 - shadcn-ui/ui#8892 registry directory submission for CodeRabbit. @shadcn asked me to send a PR, I shipped #9331 which auto-closed this issue on merge
- get-convex/better-auth#219 potential duplicate token requests during concurrent
fetchAccessTokencalls. Fixed by my own PR #267 - Shopify/hydrogen#3263 Vite 7 support in
@shopify/mini-oxygen. Closed by me after @frandiox shipped Vite Environment API in #3617, superseding my rebase #3493 - oven-sh/bun#29444
bun installwarns on valid prereleases in peer deps.includePrereleasenot applied to peer dep semver checks, so@tanstack/router-core@1.167.10-rc.0satisfying^1.167.0emits a spurious peer warning. Open and tracked by my PR oven-sh/bun#27085 - anthropics/claude-code#18075 feature request for an env var to set a custom Chromium browser path, open
- anthropics/claude-code#18181 manual update doesn’t fix the symlink when
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFICis set. @bcherny replied “Fix incoming” and closed it - anthropics/claude-code#20664
--fork-sessiondoesn’t inheritCLAUDE_CODE_TASK_LIST_IDfrom the parent session, auto-closed for inactivity - tobi/qmd#198
bun addblocksnode-llama-cpppostinstall (harmless warning, qmd still works). Closed by me as not a bug, upstream later addedpnpm.onlyBuiltDependenciesin cc32c995 - Textualize/textual#5980 emoji with variation selectors cause button layout misalignment in Ghostty. Closed after the discussion concluded the fix belongs in terminal emulators via DEC mode 2027, not in
textual - cursor/cursor#3182 unable to update spending limit or toggle usage-based pricing on the main dashboard. Fixed upstream