npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@flightlog/react-native

v0.1.0-rc.1

Published

React Native native crash capture for Flightlog

Readme

@flightlog/react-native

React Native/Expo adapter around @flightlog/sdk. It adds device/app/JavaScript-engine metadata, AppState and React Native global error capture, a React error boundary, and persisted iOS/Android native crash delivery.

Requirements

  • Expo native development build or bare React Native app with Expo Modules autolinking.
  • A Flightlog HTTP endpoint reachable from the simulator/device.
  • Native app rebuild after installing this package or changing its Swift/Kotlin code.

Expo Go is not supported. It does not contain the Flightlog native module. Metro reload/Fast Refresh cannot install or update native code.

Install and link native code

bun add @flightlog/react-native
bun add --dev @flightlog/cli

The adapter declares @flightlog/sdk and @flightlog/contracts as exact runtime dependencies, so application projects do not need to add them separately. The optional CLI dependency runs the host server and Studio; it is not bundled into the mobile application package. Start it with bunx @flightlog/cli studio or a project script.

For guided setup, run bunx @flightlog/cli init from the app root. It detects Expo/React Native, previews package/script/file changes, asks for confirmation, and generates a starter module. It intentionally does not rewrite the native app entrypoint; import the generated module once and rebuild the development build as instructed.

For Expo, install into an app that uses development builds, run bunx expo prebuild when the project owns generated native directories, then rebuild with the project's normal bunx expo run:ios / bunx expo run:android or EAS development-build flow. Expo Modules autolinking reads expo-module.config.json; do not manually add the Swift/Kotlin module. Re-run prebuild/rebuild after changing package or native versions. Managed apps that never generate/build native projects and Expo Go cannot use crash capture.

For bare React Native, Expo Modules must already be installed and configured. Run CocoaPods installation through the repository's established native workflow after dependency installation, verify FlightlogReactNative.podspec is discovered on iOS, and verify the Android package/provider is manifest-merged. This package does not support legacy manual linking. Keep platform deployment targets compatible with the versions declared by the podspec and Gradle configuration.

Endpoint selection

| Target | Typical SDK endpoint | Server mode | | --- | --- | --- | | iOS Simulator | http://localhost:4319 | Default loopback usually works. | | Android emulator | http://10.0.2.2:4319 | Android Studio's standard emulator maps this to the host; verify with your emulator/network setup. | | Physical iOS/Android device | http://<development-machine-LAN-IP>:4319 | Explicit dev --lan; ingest token required. |

localhost on a physical device means the device itself. Use the development machine's reachable private IPv4 address, keep phone/computer on the same trusted network, account for firewall/VPN/client-isolation rules, and do not expose Flightlog to the internet. Android cleartext HTTP or iOS local-network/transport policy can require app-native configuration depending on the target's platform settings.

For physical devices, start the host CLI in explicit LAN mode:

bunx @flightlog/cli dev --lan

The process prints generated ingest and admin capabilities. Put only the ingest token in the app. Keep the admin token in trusted Studio/API/MCP clients. Generated process tokens are not persisted for later shell commands; export explicit FLIGHTLOG_INGEST_TOKEN and FLIGHTLOG_ADMIN_TOKEN first when deterministic reuse is needed.

Initialization

import {
  Flightlog,
  FlightlogErrorBoundary,
  FlightlogReactNative,
} from "@flightlog/react-native";

FlightlogReactNative.init({
  app: "my-app",
  endpoint: "http://reachable-host:4319",
  token: process.env.EXPO_PUBLIC_FLIGHTLOG_INGEST_TOKEN,
  captureConsole: true,
  captureWarnings: true,
  captureNetwork: true,
  onDiagnostic: (diagnostic) => console.warn("Flightlog diagnostic", diagnostic),
});

export function Root() {
  return (
    <FlightlogErrorBoundary
      context={{ feature: "root" }}
      fallback={(error, reset) => <ErrorView error={error} onRetry={reset} />}
    >
      <App />
    </FlightlogErrorBoundary>
  );
}

Flightlog.breadcrumb("Checkout opened");
Flightlog.navigation("Checkout/Payment");
Flightlog.event("state", "Cart updated", { itemCount: 3 });
Flightlog.setContext({
  user: { id: "local-user-7" },
  tags: { buildChannel: "development" },
});
Flightlog.error(error, { action: "submit-payment" });

Environment variables prefixed EXPO_PUBLIC_ are bundled into the app and are not secrets. The ingest capability is intentionally write-only but should still be scoped to a trusted development session. Never bundle the admin capability.

The adapter forces runtime to react-native, derives platform/device/OS/app/JS-engine metadata, disables the runtime-neutral global handler in favor of the React Native handler, and enables AppState/global/native-crash captures by default. Console and network capture remain opt-in.

Set stable release and environment values in initialization, use navigation() from the navigation container's route-change callback, and update context at authentication/feature boundaries. AppState foreground/background breadcrumbs and global JavaScript errors are installed by default. Network capture observes global fetch, not every native networking library. An error boundary catches render/lifecycle errors below it; it does not replace global JavaScript or native crash handlers. Place the boundary above navigation and feature providers whose failures it should catch, while keeping initialization outside the component render cycle.

Initialization removes JavaScript/AppState handlers installed by the prior adapter initialization. Native handler installation is process-idempotent. Call the SDK's await Flightlog.cleanup() at a controlled shutdown when practical; FlightlogReactNative.cleanup() only removes adapter captures and does not replace SDK flush cleanup.

Native crash delivery

Supported native handlers synchronously persist into a durable FIFO of up to eight canonical NativeCrashPayload artifacts before chaining to the previous fatal handler. Legacy single-payload storage is migrated. The queue preserves older undelivered crashes when full (the newest crash is not enqueued), records stable ID/occurrence/attempt metadata, and marks repeated fingerprints/crash loops when safely derivable. This bounds normal queue storage without allowing a crash during upload or initialization to replace the original.

During each healthy initialization, the module persists the normalized endpoint, write-only ingest capability, app/session identity, and transport-safe context/session metadata. Tokens are used only in the Authorization header and are never returned by diagnostics or logged. getPendingNativeCrashReports() enumerates the FIFO and getNativeCrashDiagnostics() non-throwingly reports pending count, queue limit, and last delivery state/status without configuration or token values. The singular getter/clear APIs remain compatible and operate on the oldest item.

On later process starts, native code attempts the oldest artifact with a three-second connect/read timeout and retains it unless a 2xx batch response names its stable event ID in accepted or duplicate. It then continues FIFO draining. It retries at safe process startup, foreground, native configuration, and JS initialization. The JS fallback also enumerates the FIFO, submits the same event ID through the SDK, and clears by ID only after an accounted successful flush; native/JS races are therefore idempotent at the server and cannot clear a different report.

Exact startup guarantee: iOS registers an Expo ExpoAppDelegateSubscriber; Expo invokes its didFinishLaunching hook during native application launch before React bundle execution, where migration/handler installation and an asynchronous delivery attempt are started. Android manifest-merges a non-exported ContentProvider; its onCreate runs during application startup before the React host/bundle and starts delivery. The first-ever install cannot deliver before JavaScript has supplied and durably persisted endpoint/ingest/session configuration. Network scheduling and completion before React executes are not guaranteed; durable retry is. Native source or Expo autolinking changes require rebuilding the development build.

The iOS POSIX signal handler performs only pre-opened journal write/fsync plus default-handler restore/re-raise; it never performs networking, uses Foundation, creates UUIDs, or captures a stack in signal context. The journal is converted into canonical stable-ID queue entries at the next healthy startup. Objective-C exceptions and Android uncaught Java/Kotlin exceptions synchronously commit their artifacts before chaining.

Crash handling is best-effort. Debuggers, development overlays, hard kills, OS termination, and some native signals can intercept/bypass in-process handlers. Android 11+ additionally consults ApplicationExitInfo for supported crash/native-crash/ANR history. Test fatal behavior in a release-like development build without debugger attachment.

testNativeCrash() is destructive by design and should only be exposed in controlled development UI.

Diagnostics and test-crash flow

  1. Start the server at the endpoint appropriate for the target and initialize the adapter once.
  2. Check Flightlog.getSessionId(), FlightlogReactNativeModule.getNativeCrashDiagnostics(), and onDiagnostic output. Diagnostics intentionally omit tokens and endpoint configuration.
  3. Send a normal breadcrumb/error, call await Flightlog.flush(), and confirm the session appears in Studio before testing a crash.
  4. In a release-like development build with no debugger attached, invoke testNativeCrash() from an explicitly development-only action. The process must terminate.
  5. Relaunch the app normally. Do not clear app data or reinstall. Confirm the durable report is accepted/duplicated, the pending count drains, and the prior session contains the crash.
  6. Repeat the repository's iOS Simulator, Android emulator, and physical-device matrix and record evidence in docs/RELEASE_VALIDATION.md.

If a report remains pending, keep the app alive/foregrounded for the bounded attempt, verify endpoint reachability and ingest token, inspect native platform logs and diagnostics, and relaunch once more. A first-install crash cannot upload because no durable configuration exists yet. A debugger, force-stop, hard kill, low-level fatal signal, development redbox, OS resource termination, or uninstall may bypass capture or prevent a retry. Never use the destructive test in production UI.

Privacy

SDK key/header redaction is enabled by default, but native exception messages, stacks, device/app metadata, route/context, and explicitly supplied data can still identify people or reveal application state. Do not attach secrets, request bodies, credentials, payment data, or unnecessary personal information. Add application-specific redaction rules, use opaque local identifiers, inspect actual payloads during integration, and retain data only as long as needed. EXPO_PUBLIC_ values are public application configuration; only the write-only ingest capability belongs there, never the admin capability.

What automation proves

Repository tests prove JavaScript FIFO validation/drain, stable SDK IDs, failure retention, concurrent guards, flush/clear policy, capture lifecycle, and type integration. Native queue/migration/startup hook code is checked in but still requires native build and process-death testing. Automation does not prove native autolinking, OS handler behavior, simulator/device networking, or process-death delivery on either platform.

Run and record the example app matrix in the release validation record before making native platform claims.