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

@bayonai/push-notifications

v0.1.0

Published

Provider-neutral notification contracts with Capacitor Firebase and Firebase Admin adapters.

Readme

@bayonai/push-notifications

Provider-neutral notification contracts with optional Capacitor Firebase Messaging and Firebase Admin adapters.

Install

Install the package and only the peers used by the consuming runtime:

pnpm add @bayonai/push-notifications
pnpm add @capacitor/core @capacitor-firebase/messaging
pnpm add firebase-admin firebase-functions

Do not install @capacitor/push-notifications beside the Firebase Messaging adapter. Both plugins compete for native push registration callbacks.

Entry points

  • @bayonai/push-notifications: messages, audiences, validation, providers, installation registries, job queues, and dispatcher.
  • @bayonai/push-notifications/capacitor: framework-independent lifecycle controller.
  • @bayonai/push-notifications/capacitor-firebase: dynamically loaded Capacitor FCM adapter.
  • @bayonai/push-notifications/capacitor-local: dynamically loaded offline device scheduler using Capacitor Local Notifications.
  • @bayonai/push-notifications/firebase-admin: Firestore registry, authenticated callable factories, and FCM provider.

The Firebase adapter also supports web browsers. Supply the Firebase Web Push VAPID public key and a host-owned service worker path; the adapter registers the worker only when a browser explicitly requests permission.

import { createFirebaseMessagingAdapter } from "@bayonai/push-notifications/capacitor-firebase";

const adapter = createFirebaseMessagingAdapter({
  serviceWorkerPath: "/firebase-messaging-sw.js",
  vapidKey: "your-public-vapid-key",
});

Native code is dynamically imported only by the Capacitor Firebase entrypoint, so importing core or server contracts during SSR does not initialize Capacitor.

Offline device scheduling

Install @capacitor/local-notifications only in apps that schedule reminders on the device. This adapter is independent from the selected remote push provider.

import { createLocalNotificationScheduler } from "@bayonai/push-notifications/capacitor-local";

const scheduler = createLocalNotificationScheduler();
await scheduler.schedule([
  {
    body: "You have a Bounded reminder.",
    data: { openPath: "/notifications/open", schemaVersion: "1" },
    id: 42,
    scheduleAt: new Date(Date.now() + 60_000).toISOString(),
    title: "Bounded",
  },
]);

OneSignal is intentionally not part of this package's active Bounded implementation. Do not install its SDK or adapters alongside Firebase Messaging; a future provider migration must preserve existing FCM registrations and be planned as a separate release.

Client lifecycle

import { createNotificationLifecycleController } from "@bayonai/push-notifications/capacitor";
import { createFirebaseMessagingAdapter } from "@bayonai/push-notifications/capacitor-firebase";

const controller = createNotificationLifecycleController({
  adapter: createFirebaseMessagingAdapter(),
  appId: "com.example.app",
  provider: "fcm",
  registerInstallation: async (installation) => api.register(installation),
  revokeInstallation: async (installation) => api.revoke(installation),
});

await controller.start();
await controller.sync({
  enabled: true,
  identity: { ownerUserId: "authenticated-user-id" },
});

Call requestPermissionAndSync only after an explicit user action. Call disable before sign-out and stop when the host lifecycle is disposed. Injected loggers must redact provider errors and must never serialize target values; the package never intentionally emits a target as a standalone log field.

Server delivery

import { createNotificationDispatcher } from "@bayonai/push-notifications";
import {
  createFcmNotificationProvider,
  createFirestoreInstallationRegistry,
} from "@bayonai/push-notifications/firebase-admin";

const registry = createFirestoreInstallationRegistry(firestore);
const dispatcher = createNotificationDispatcher({
  appId: "com.example.app",
  provider: createFcmNotificationProvider(messaging),
  registry,
});

await dispatcher.send({
  audience: { kind: "users", userIds: ["user-id"] },
  message: {
    title: "New notification",
    body: "Open the app to review it.",
    data: { schemaVersion: "1", notificationId: "notification-id" },
  },
});

Topics and provider conditions are broadcast mechanisms, not authorization. Never place private content in topic messages. Scheduling requires an injected NotificationJobQueue and deliberately owns no campaign database or UI.

Firestore contract

The Firebase registry stores pushInstallations/{sha256} with server-only raw targets and ownership metadata. Host rules must deny all client access. The callable factories validate authentication, app ID, provider, platform, and target bounds before calling the registry.

Refresh registrations when an authenticated native app starts and when the provider emits a new token. Remove invalid targets after delivery and schedule pruneStale with an app-appropriate retention window.

Publishing

pnpm test
pnpm lint
pnpm build
pnpm consumer:smoke
pnpm pack:smoke

Publishing is intentionally separate from implementation. Bump the version and changelog, verify npm scope authorization, publish with public access, and test the registry artifact in a fresh Capacitor consumer before changing apps from workspace consumption.