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

@gamitolab/bridgekit

v0.3.0-alpha.4

Published

Typed bidirectional bridge between React Native and native (Android/iOS)

Readme

@gamitolab/bridgekit

Typed, bidirectional communication between React Native and native code via a Marker API. One TypeScript contract definition drives JS types, runtime metadata, and generated Kotlin/Swift.

Built on Nitro Modules for the native transport.

Platform support

| Platform | Status | Transport | | -------- | ------ | --------- | | Android | ✅ Supported | Nitro (Kotlin runtime) | | iOS | ✅ Supported | Nitro (Swift runtime) | | Web | ✅ Supported | In-memory loopback (no native code) |

Alpha. The wire protocol is locked and the Android/iOS runtimes are at parity, but the public API may still change before 1.0.

Installation

# while in alpha, install the @alpha tag
pnpm add @gamitolab/bridgekit@alpha react-native-nitro-modules

# codegen CLI (dev dependency)
pnpm add -D @gamitolab/bridgekit-cli@alpha

BridgeKit is a Nitro module. After installing:

  • iOS — cd ios && pod install
  • Android — autolinking handles it; no manual steps.

Peer dependencies: react, react-native (>= 0.86), react-native-nitro-modules (^0.37). The host app pins RN and Nitro; this package does not. Dev builds in this repo use React Native 0.86.3 and react-native-nitro-modules 0.37.1.

Brownfield

The public module is pure Swift (import BridgeKit). Nitro/C++ lives in BridgeKitNitro and is what autolinking installs. A packaged RN host never imports Nitro and never puts provide() inside the RN framework.

BRIDGEKIT_HOST_PROVIDES_RUNTIME=1 is a build mode: the host already links public BridgeKit (Swift package / xcframework), so CocoaPods must not inject a second copy into the RN target. In that mode BridgeKitNitro also skips BKTransportWeakStubs.m (stubs in the same image as Nitro swallow provide()) and the RN target must link with -Wl,-undefined,dynamic_lookup so BKTransport* stay unbound until the host image loads.

  1. pnpm add @gamitolab/bridgekit@alpha react-native-nitro-modules
  2. Generate host contracts: bridgekit generate --platform swift --out-dir ios/HostApp/Generated
  3. Package RN: pnpm package:ios (set BRIDGEKIT_HOST_PROVIDES_RUNTIME=1 in the RN Podfile)
  4. In the host Xcode project, add the remote package. No local path. URL https://github.com/gamitolab/bridgekit.git, exact tag 0.3.0-alpha.4, product BridgeKit, package bridgekit:
.package(url: "https://github.com/gamitolab/bridgekit.git", exact: "0.3.0-alpha.4")
.product(name: "BridgeKit", package: "bridgekit")

Then:

import BridgeKit

func application(...) -> Bool {
  BridgekitDemoInitializer.configure() // your provide()s, generated contracts
  ReactNativeBrownfield.shared.startReactNative(...)
  return true
}

No Podfile in the host. No NSClassFromString. Integrated brownfield (pods in the same app target) autolinks Nitro and injects public BridgeKit in-process.

Entry points

| Import | Contents | | ------ | -------- | | @gamitolab/bridgekit | Runtime + React hooks + contract layer (everything) | | @gamitolab/bridgekit/contract | Contract layer only — zero side effects, safe in Node/Jest/web | | @gamitolab/bridgekit/react | React hooks (useBridge, useBridgeState, …) | | @gamitolab/bridgekit/test | Testing helpers (createTestBridge, mockBridge) |


Quick Start — Marker API

1. Define a contract (TypeScript, single source of truth)

// connect-host.contract.ts — provided by NATIVE, consumed by JS
import { defineContract, Async, Void, Stream, State } from '@gamitolab/bridgekit/contract';

export const ConnectHost = defineContract('connect.host', {
  methods: {
    isLoggedIn: Async<boolean>(),
    installEsim: Async<{ url: string; iccId: string }, 'success' | 'cancelled' | 'error'>(),
    showLogin: Void(),
  },
  streams: {
    otpCodes: Stream<string>(),
  },
  state: {
    connectivity: State<{ online: boolean }>({ online: false }),
  },
});

Marker reference:

  • Async<Result>() / Async<Params, Result>() — async request/response
  • Sync<Result>() / Sync<Params, Result>() — sync read (native-provided only)
  • Void() / Void<Params>() — fire-and-forget
  • Stream<Value>() / Stream<Value, Params>() — typed observable flow
  • State<Value>(initial) — observable bidirectional state

2. Generate native bindings

The codegen lives in @gamitolab/bridgekit-cli. Emit Kotlin and/or Swift from the same contract:

# Android (Kotlin) — default platform
bridgekit generate \
  --contracts 'src/**/*.contract.ts' \
  --out-dir android/src/main/java/com/myapp/bridgekit/generated

# iOS (Swift)
bridgekit generate --platform swift \
  --contracts 'src/**/*.contract.ts' \
  --out-dir ios/MyApp/bridgekit/generated

This produces typed interfaces, data classes, codecs, and a contract object per platform.

3. Provide from native (Kotlin)

class ConnectHostProvider : ConnectHost {
  override suspend fun isLoggedIn(): Boolean = session.isLoggedIn()
  override suspend fun installEsim(params: InstallEsimParams): InstallEsimResult = /* ... */
  override fun showLogin() { /* ... */ }
  override fun otpCodes(): Flow<String> = smsRetriever.codes()
  override val connectivity = MutableStateFlow(Connectivity(online = true))
}

BridgeKit.default.provide(ConnectHostContract) { ConnectHostProvider() }

4. Consume from React Native

import { useBridge, useBridgeState } from '@gamitolab/bridgekit/react';
import { ConnectHost } from './connect-host.contract';

function LoginButton() {
  const connect = useBridge(ConnectHost);
  const { value, status } = useBridgeState(ConnectHost, 'connectivity');

  return (
    <Button
      title={value?.online ? 'Connected' : 'Offline'}
      onPress={() => connect.showLogin()}
    />
  );
}

5. Provide from React Native (JS → native direction)

import { useProvideBridge } from '@gamitolab/bridgekit/react';
import { LiaFeature } from './lia-feature.contract';

function LiaProvider({ children }) {
  useProvideBridge(LiaFeature, {
    getUnreadCount: () => store.unread,
  });
  return children;
}
val lia = bridgeKit.consume(LiaFeatureContract)
val count = lia.getUnreadCount()

ContractHook (React integration)

ContractHook is the React-first way to consume a contract. It returns a derived consumer that re-renders automatically when any subscribed state changes.

import { defineContract, Async, State } from '@gamitolab/bridgekit/contract';

const UserContract = defineContract('user.contract', {
  methods: {
    getProfile: Async<{ userId: string }, { name: string; email: string }>(),
  },
  state: {
    loginStatus: State<'idle' | 'active' | 'error'>('idle'),
  },
});

// In a React component:
const user = UserContract.hook();
// user.loginStatus.value — reactive, re-renders on change
// user.loginStatus.status — 'provided' | 'unprovided' | 'stale'
// user.getProfile({ userId }) — returns Promise<{ name, email }>

Scoping

Use BridgeScopeProvider to isolate contracts to a feature or instance:

import { BridgeScopeProvider } from '@gamitolab/bridgekit/react';

// Feature scope — multiple instances of the same feature do not cross-talk
<BridgeScopeProvider feature="checkout" instance={cartId}>
  <CheckoutFlow />
</BridgeScopeProvider>

Auto-discovery (native feature modules)

class ConnectBridgeModule : BridgeKitModule {
  override fun register(bridgekit: BridgeKit, host: BridgeKitHost) {
    bridgekit.provide(ConnectHostContract) { ConnectHostProvider(host.locate()) }
  }
}
// Register via META-INF/services/com.bridgekit.discovery.BridgeKitModule

Testing

import { createTestBridge } from '@gamitolab/bridgekit/test';

const { bridgekit } = createTestBridge();
await bridgekit.provide(ConnectHost, { isLoggedIn: async () => true });
const proxy = bridgekit.bridge(ConnectHost);
expect(await proxy.isLoggedIn()).toBe(true);
val fake = object : ConnectHost { /* ... */ }
val bridgekit = BridgeKit(testTransport)

Diagnostics

BridgeKit.default.dump() returns live state:

const state = BridgeKit.default.dump();
// state.bindings    — registered providers per contract+scope
// state.mirrors     — observable state mirrors per contract+scope
// state.openStreams  — current count of open stream subscriptions
// state.streamDrops  — cumulative items dropped by bounded consumer queues
// state.counters     — { calls, errors, firesDropped }
// state.epoch        — current connection generation

On Android: BridgeKit.default.dump() logs to Logcat under the BridgeKit tag.


License

MIT © malopezr7