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

@swimmesberger/elarion-webpush

v0.3.2

Published

The browser half of Elarion Web Push: push availability detection (including the iOS Home Screen requirement), gesture-safe permission and subscribe/unsubscribe/refresh helpers over a pluggable server API, and a service-worker module for push, notificatio

Readme

@swimmesberger/elarion-webpush

The browser half of Elarion Web Push: reach a user's browser or installed PWA while the app is closed. The server half is the Elarion.WebPush NuGet package (IWebPushSender, VAPID keys, the subscription store).

  • pushAvailability() → 'available' | 'install-first' | 'unsupported'. install-first is iOS/iPadOS Safari outside a Home Screen app, where PushManager does not exist yet: show "Add to Home Screen first" instead of a switch that can never turn on.
  • enablePush(api) — asks for permission inside the click handler (before any await, which Safari requires) and subscribes.
  • subscribe, unsubscribe, isSubscribed, and refreshOnStart(api) — call the last one on every app start to heal subscriptions the push service rotated or the server cleaned up. They subscribe through the page's active service-worker registration (or the registration option) and wait at most registrationTimeoutMs (10 s) for a worker to activate, then throw a WebPushRegistrationError — navigator.serviceWorker.ready alone never settles when no worker is registered, for example on a dev server that does not serve one.
  • @swimmesberger/elarion-webpush/sw — registerWebPushHandlers(self) for the service worker: shows the notification, focuses or opens the app at its URL on click, and re-subscribes on pushsubscriptionchange.

Page

import { enablePush, fetchWebPushApi, pushAvailability, refreshOnStart } from '@swimmesberger/elarion-webpush'

const api = fetchWebPushApi() // the endpoints app.MapElarionWebPush() maps under /webpush

await navigator.serviceWorker.register('/sw.js', { type: 'module' })
void refreshOnStart(api)

switch (pushAvailability()) {
  case 'available':
    button.onclick = async () => console.log(await enablePush(api)) // 'subscribed' | 'denied' | 'dismissed'
    break
  case 'install-first':
    hint.textContent = 'Add this app to your Home Screen to turn on notifications.'
    break
}

When the application exposes its own webPush.* handlers instead of MapElarionWebPush, adapt the generated JSON-RPC client:

const api: WebPushServerApi = {
  getPublicKey: async () => (await rpc.webPush.publicKey({})).publicKey,
  subscribe: async (subscription) => { await rpc.webPush.subscribe(subscription) },
  unsubscribe: async (endpoint) => { await rpc.webPush.unsubscribe({ endpoint }) },
}

Service worker

import { registerWebPushHandlers } from '@swimmesberger/elarion-webpush/sw'

registerWebPushHandlers(self, { icon: '/icons/192.png', badge: '/icons/badge.png' })

The module is ESM: bundle the worker (e.g. vite-plugin-pwa injectManifest) or register it with { type: 'module' }.