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

@hrefcl/apn

v4.0.0

Published

Apple Push Notification service (APNs) for Node.js - Maintained fork with security updates and TypeScript support

Readme

@hrefcl/apn

Apple Push Notification service (APNs) for Node.js - Maintained fork with security updates and TypeScript support.

npm version TypeScript License: MIT

Why this fork?

The original apn package has been unmaintained since 2019 and contains 32 security vulnerabilities in its dependencies. This fork:

  • Updates all dependencies to secure versions
  • Rewrites the codebase in TypeScript with full type definitions
  • Uses native Node.js http2 module (no deprecated packages)
  • Maintains API compatibility where possible
  • Adds support for modern APNs features (VoIP, Live Activities, MDM, Safari, etc.)

Installation

npm install @hrefcl/apn
# or
yarn add @hrefcl/apn

Requirements

  • Node.js >= 16.0.0
  • Apple Developer account with push notification capabilities
  • APNs authentication key (.p8 file)

Quick Start

import { Provider, Notification } from '@hrefcl/apn';

// Create provider with token-based authentication
const provider = new Provider({
  token: {
    key: '/path/to/AuthKey_XXXXXXXXXX.p8',
    keyId: 'XXXXXXXXXX',
    teamId: 'YYYYYYYYYY'
  },
  production: false // Use true for production
});

// Create notification
const notification = new Notification({
  alert: {
    title: 'New Message',
    body: 'Hello from APNs!'
  },
  badge: 1,
  sound: 'default',
  topic: 'com.example.myapp'
});

// Send to device(s)
const result = await provider.send(notification, [
  'device-token-1',
  'device-token-2'
]);

console.log(`Sent: ${result.sent.length}`);
console.log(`Failed: ${result.failed.length}`);

// Handle failures
for (const failure of result.failed) {
  console.log(`Device: ${failure.device}`);
  console.log(`Reason: ${failure.response?.reason}`);
}

// Shutdown when done
provider.shutdown();

API Reference

Provider

const provider = new Provider(options);

Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | token | Object | required | Token authentication options | | token.key | string/Buffer | required | Path to .p8 file or key content | | token.keyId | string | required | Key ID from Apple Developer | | token.teamId | string | required | Team ID from Apple Developer | | production | boolean | false | Use production environment | | host | string | auto | Custom APNs host | | port | number | 443 | Connection port | | requestTimeout | number | 5000 | Request timeout (ms) |

Methods

  • send(notification, recipients) - Send notification to device(s)
  • shutdown() - Close all connections

Notification

const notification = new Notification(options);

Supported pushType values: alert, background, voip, complication, fileprovider, mdm, liveactivity, location, pushtotalk.

Options

| Option | Type | Description | |--------|------|-------------| | alert | string/Object | Alert content | | badge | number | Badge number | | sound | string | Sound filename | | contentAvailable | boolean | Background fetch flag | | mutableContent | boolean | Service extension flag | | category | string | Action category | | threadId | string | Thread identifier | | targetContentId | string | Target content identifier | | interruptionLevel | string | Focus interruption level | | relevanceScore | number | Relevance score (0.0 to 1.0) | | filterCriteria | string | Notification filter criteria | | staleDate | number | Live Activity stale date | | contentState | Object | Live Activity content state | | timestamp | number | Live Activity timestamp | | event | string | Live Activity event (start/update/end) | | dismissalDate | number | Live Activity dismissal date | | topic | string | Bundle ID | | expiry | number/Date | Expiration time | | priority | number | Priority (1-10) | | collapseId | string | Collapse identifier | | pushType | string | Push type | | payload | Object | Custom data | | id | string | apns-id header (UUID) | | urlArgs | string[] | Safari push URL arguments | | mdm | string | MDM magic string |

Send Result

interface SendResult {
  sent: Array<{ device: string }>;
  failed: Array<{
    device: string;
    status?: string;
    response?: { reason: string };
    error?: Error;
  }>;
}

Error Handling

const result = await provider.send(notification, tokens);

for (const failure of result.failed) {
  switch (failure.response?.reason) {
    case 'BadDeviceToken':
      // Invalid token format
      break;
    case 'Unregistered':
      // Token no longer valid - remove from database
      await removeToken(failure.device);
      break;
    case 'PayloadTooLarge':
      // Payload exceeds 4KB
      break;
    case 'TooManyRequests':
      // Rate limited - implement backoff
      break;
    default:
      console.error(`Unknown error: ${failure.response?.reason}`);
  }
}

Background Notifications

const notification = new Notification({
  contentAvailable: true,
  topic: 'com.example.app',
  pushType: 'background',
  payload: {
    action: 'sync-data'
  }
});

Rich Notifications

const notification = new Notification({
  alert: {
    title: 'Photo from John',
    subtitle: 'Vacation 2024',
    body: 'Check out this amazing sunset!'
  },
  mutableContent: true, // Enable service extension
  category: 'PHOTO',
  payload: {
    imageUrl: 'https://example.com/photo.jpg'
  }
});

VoIP Notifications (5KB payload)

const notification = new Notification({
  pushType: 'voip',
  topic: 'com.example.app', // auto-appends .voip
  payload: {
    callerId: 'user-123',
    callerName: 'Jane Doe'
  }
});

Live Activities

const notification = new Notification({
  pushType: 'liveactivity',
  topic: 'com.example.app', // auto-appends .push-type.liveactivity
  contentState: { score: '2-1' },
  event: 'update',
  timestamp: Date.now()
});

Safari Push (url-args)

const notification = new Notification({
  urlArgs: ['inbox', 'message-123'],
  payload: { action: 'open' }
});

MDM

const notification = new Notification({
  mdm: 'a1b2c3d4e5f6'
});

apns-id

const notification = new Notification({
  id: '6c7f28b1-2a0d-4c72-b1c4-2d5f0d6b8a64',
  alert: 'Hello'
});

Migration from apn

This package is largely API-compatible with the original apn package:

// Before (apn)
const apn = require('apn');
const provider = new apn.Provider(options);

// After (@hrefcl/apn)
import { Provider } from '@hrefcl/apn';
const provider = new Provider(options);

Breaking Changes

  1. Node.js 16+ required - Older versions not supported
  2. Token authentication only - Certificate auth removed
  3. No proxy support - May be added in future versions

Security

This package fixes all 32 security vulnerabilities present in the original apn package:

  • CVE-2022-23529 (jsonwebtoken)
  • CVE-2022-23540 (jsonwebtoken)
  • CVE-2022-24772 (node-forge)
  • CVE-2022-24771 (node-forge)
  • CVE-2020-7720 (node-forge)
  • And 27 more...

License

MIT - See LICENSE for details.

Credits

  • Original authors: Andrew Naylor, Florian Reinhart
  • Maintained by: Href SpA

Links