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

@asyncify-hq/react-native

v0.1.0

Published

Native push registration for Asyncify — one hook that wires FCM device tokens, permissions and token rotation on Android and iOS

Readme

@asyncify-hq/react-native

Native push registration for Asyncify: one hook that wires a device's FCM token into your Asyncify subscriber, asks for the OS notification permission, follows token rotation, and surfaces foreground messages. Built on React Native Firebase — the OS is the push receiver, so there is no service worker to run.

Install

npm install @asyncify-hq/react-native

This package has required peers — install and configure them too:

npm install @react-native-firebase/app @react-native-firebase/messaging

Follow the React Native Firebase getting-started guide to add your google-services.json (Android) / APNs key (iOS) and the @react-native-firebase/app config plugin. react and react-native are peers you already have.

Usage

Your backend mints a short-lived, single-subscriber token with @asyncify-hq/node (API keys never reach the device):

// backend
const { token } = await asyncify.subscriberToken(user.id);
// app
import { usePushRegistration } from '@asyncify-hq/react-native';

function PushToggle({ token }: { token: string }) {
  const push = usePushRegistration({
    token,
    apiUrl: 'https://api.your-deployment.com',
    onForegroundMessage: (msg) => console.log('foreground push', msg),
  });

  if (!push.supported) return null;

  return (
    <Button
      title={push.enabled ? 'Disable push' : 'Enable push'}
      disabled={push.busy}
      onPress={push.enabled ? push.disable : push.enable}
    />
  );
}

enable() prompts for the notification permission, reads the FCM token, and registers the device. The hook also re-registers silently after a token rotation (the server upsert is idempotent), so you call enable() once.

The localhost warning

apiUrl is required and must be reachable from the phone. On a device, localhost / 127.0.0.1 is the phone itself — not your laptop. Point apiUrl at a LAN IP or a public tunnel (e.g. the cloudflare URL that asyncify dev prints), never localhost.

Hook API

const {
  supported,   // boolean — true on Android/iOS
  permission,  // 'granted' | 'denied' | 'prompt'
  enabled,     // boolean — true once the device is registered
  busy,        // boolean — an enable()/disable() is in flight
  error,       // string | null — last explicit-action error
  enable,      // () => Promise<void>
  disable,     // () => Promise<void>
} = usePushRegistration({ token, apiUrl, onForegroundMessage });

Background and quit-state notifications are displayed by the OS automatically; onForegroundMessage fires only while the app is open.

Tapping a notification

On native, the OS always launches the app when a notification is tapped — there is no browser-opens-directly path like web push. When the tapped message carries a clickUrl (set on the workflow's push step), the hook forwards it to the system browser automatically, covering both a background tap and a tap that cold-started the app. Pass openClickUrlOnTap: false to receive taps yourself via the React Native Firebase APIs instead — the URL also rides in the message data as clickUrl.

Sticky opt-out

disable() must survive an app relaunch — otherwise, since the OS notification permission is still granted, the hook would silently re-register a fresh token on the next launch and undo the user's opt-out. To make it stick, the hook persists an opt-out marker (asyncify:push:opted-out) via @react-native-async-storage/async-storage, which is an optional peer: disable() sets it, enable() clears it, and a launch that sees it skips the silent re-register. Install async-storage to get this behavior:

npm install @react-native-async-storage/async-storage

Without async-storage the hook still works, but a disable() only lasts until the next app launch (the marker can't be persisted). The marker stores an opt-out, so users who never call disable() keep the zero-config auto-register behavior with no storage library at all.

iOS note

The code is platform-neutral — the same hook drives Android and iOS. iOS additionally requires an APNs key uploaded in the Firebase console and a Mac build (Xcode / an Apple Developer account). This package has been verified live on Android only; iOS is wired but unverified.

MIT © Shubam Patil