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

@iron-stack/push

v1.0.0

Published

Declarative push notification framework with multi-provider support (APNs, FCM, Expo), socket-aware delivery, and built-in throttling and batching.

Readme

@iron-stack/push

Declarative push notification framework with multi-provider support (APNs, FCM, Expo), socket-aware delivery, and built-in throttling and batching.

Installation

npm install @iron-stack/push

Quick Start

1. Define push rules (shared)

import { definePushRules } from '@iron-stack/push';

const pushRules = definePushRules<{
  'message:new': MessageWithSender;
}>({
  'message:new': {
    shouldPush: (msg, recipient) => !recipient.isOnline,
    title: (msg) => msg.sender.displayName,
    body: (msg) => msg.content,
    deepLink: (msg) => `myapp://conversation/${msg.conversationId}`,
    collapseKey: (msg) => `conv:${msg.conversationId}`,
    threadId: (msg) => msg.conversationId,
    throttleMs: 2000,
    batchWindowMs: 3000,
    batchTitle: (events) => events[0].sender.displayName,
    batchBody: (_, count) => `${count} new messages`,
  },
});

2. Server -- send push notifications

import { PushService, createExpoProvider, createSocketTracker } from '@iron-stack/push/server';

const push = new PushService({
  registry: yourDeviceRegistry,
  onlineTracker: createSocketTracker(),
  rules: pushRules,
  providers: [createExpoProvider()],
});

// Trigger push for affected users
await push.notify('message:new', messageData, recipientUserIds);

3. Client -- configure push (type only)

import type { PushClientConfig } from '@iron-stack/push/client';

const pushConfig: PushClientConfig = {
  platform: 'ios',
  registerForToken: async () => { /* get push token from OS */ },
  requestPermission: async () => { /* request notification permission */ },
  sendTokenToServer: async (token) => { /* register token with server */ },
};

API Reference

@iron-stack/push (shared)

| Export | Description | |---|---| | definePushRules(rules) | Type-safe factory for declaring per-event push behavior | | PlatformSchema | Zod schema for platform enum (ios, android, web) | | PushTokenSchema | Zod schema for push token objects | | Platform | Type: "ios" \| "android" \| "web" | | PushToken | Type for stored device tokens | | NotificationPayload | Type for the notification content (title, body, data, badge, sound, etc.) | | PushResult | Type for send results per token | | PushRule | Type for a single push rule definition | | PushRules | Type for the complete rules map | | PushRecipient | Type for resolved recipient (userId, isOnline, tokens) | | PushProvider | Interface that push providers must implement | | DeviceRegistry | Interface for device token storage (register, remove, query, prune) | | OnlineTracker | Interface for checking user online status |

@iron-stack/push/server

| Export | Description | |---|---| | PushService | Main push engine -- socket-aware, declarative, multi-provider | | PushService.notify(event, data, recipientIds) | Trigger push for an event based on rules | | PushService.sendDirect(userId, payload) | Send a push directly, bypassing rules | | PushService.addProvider(provider) | Register an additional push provider | | PushService.pruneStaleTokens(days) | Remove tokens unused for N days | | PushService.flushAll() | Flush all pending batched notifications | | PushQueue | Queue with built-in throttling and batching | | createSocketTracker() | Creates an in-memory online tracker backed by Socket.IO | | createMemoryRegistry() | In-memory device registry for development and testing | | createAPNsProvider(config) | Apple Push Notification Service provider (HTTP/2) | | createFCMProvider(config) | Firebase Cloud Messaging v1 API provider | | createExpoProvider(config?) | Expo push notification provider | | PushServiceConfig | Configuration for PushService | | APNsConfig | Configuration for APNs provider | | FCMConfig | Configuration for FCM provider | | ExpoConfig | Configuration for Expo provider |

@iron-stack/push/client

| Export | Description | |---|---| | PushClientConfig | Interface for platform-agnostic client push configuration | | NotificationHandler | Interface with onForeground, onTap, onBackground callbacks | | PushPermissionStatus | Type: "granted" \| "denied" \| "undetermined" |

Configuration

PushServiceConfig

| Option | Type | Default | Description | |---|---|---|---| | registry | DeviceRegistry | required | Device token storage backend | | onlineTracker | OnlineTracker | undefined | Socket-based online status (skip pushes for online users) | | rules | PushRules | required | Declarative per-event push config | | providers | PushProvider[] | [] | Registered push providers (APNs, FCM, Expo) | | autoRemoveInvalidTokens | boolean | true | Auto-remove expired/invalid tokens | | verbose | boolean | true | Log push events to console |

PushRule Options

| Option | Type | Description | |---|---|---| | shouldPush | (event, recipient) => boolean | Skip push when returning false (e.g., user is online) | | title | string \| (event) => string | Notification title | | body | string \| (event) => string | Notification body | | data | (event) => Record<string, string> | Custom data payload | | deepLink | (event) => string | Deep link URL opened on tap | | collapseKey | (event) => string | Newer pushes with same key replace older ones | | threadId | (event) => string | Group notifications by thread | | imageUrl | (event) => string | Rich notification image | | priority | "normal" \| "high" | Push priority (default: "high") | | silent | boolean | Silent/background push | | throttleMs | number | Min ms between pushes per recipient + collapse key | | batchWindowMs | number | Combine events within this window into one push | | batchTitle | (events, count) => string | Title for batched notifications | | batchBody | (events, count) => string | Body for batched notifications |

Provider Configs

APNsConfig

| Option | Type | Default | Description | |---|---|---|---| | key | string | required | .p8 key file contents | | keyId | string | required | Key ID from Apple Developer portal | | teamId | string | required | Team ID from Apple Developer portal | | bundleId | string | required | App bundle identifier | | production | boolean | false | Use production APNs endpoint |

FCMConfig

| Option | Type | Description | |---|---|---| | projectId | string | Firebase project ID | | serviceAccountKey | string | Service account JSON string |

ExpoConfig

| Option | Type | Description | |---|---|---| | accessToken | string? | Expo access token (optional, for higher rate limits) |

License

MIT