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

@jterrazz/broadcast

v0.1.1

Published

Multi-channel broadcast system for distributing announcements across platforms. Define an announcement once, send it everywhere — App Store In-App Events, Google Play, push notifications, email, and more.

Readme

@jterrazz/broadcast

Multi-channel broadcast system for distributing announcements across platforms. Define an announcement once, send it everywhere — App Store In-App Events, Google Play, push notifications, email, and more.

Install

npm install @jterrazz/broadcast

Quick Start

import { AppleAppStoreAdapter, sendBroadcast } from "@jterrazz/broadcast";

const apple = new AppleAppStoreAdapter({
  issuerId: "your-issuer-id",
  keyId: "YOUR_KEY_ID",
  privateKey: "-----BEGIN PRIVATE KEY-----\n...",
  appId: "6444444444",
});

await sendBroadcast(
  {
    title: "Season 2 is live!",
    shortDescription: "New features and challenges await",
    longDescription: "Explore new game modes, leaderboards, and exclusive rewards.",
    badge: "new-season",
    audience: "all",
    priority: "high",
    startDate: new Date("2026-04-01"),
    endDate: new Date("2026-04-30"),
    deepLink: "myapp://seasons/2",
  },
  [apple],
);

sendBroadcast fans out to all providers concurrently. If one fails, the others still succeed — each result includes a status field.

Broadcast Model

| Field | Type | Description | | ------------------ | -------------------- | -------------------------------------------------- | | title | string | Display title (max ~30 chars for App Store compat) | | shortDescription | string | Teaser for cards/previews (max ~50 chars) | | longDescription | string | Detail view description (max ~120 chars) | | startDate | Date | When the event starts | | endDate | Date | When the event ends | | badge | BroadcastBadge | Event category | | audience | BroadcastAudience | Target audience | | priority | "normal" \| "high" | Visibility level | | deepLink | string? | Deep link URL into the app | | requiresPurchase | boolean? | Whether participation requires a purchase | | territories | string[]? | ISO 3166-1 alpha-2 country codes (default: all) |

Badge Types

challenge · competition · live-event · major-update · new-season · premiere · special-event

Audience Types

all · new-users · active-users · lapsed-users

Providers

Apple App Store (In-App Events)

Creates In-App Events on the App Store via the App Store Connect API.

Setup

  1. Go to App Store ConnectUsers and AccessIntegrationsApp Store Connect API
  2. Click Generate API Key
    • Name: e.g. signews-broadcast
    • Access: Admin (required for In-App Events)
  3. Download the .p8 file — you can only download it once
  4. Note the Key ID shown in the table (e.g. 2X9R4HXF34)
  5. Copy the Issuer ID shown at the top of the page
  6. Find your App ID: go to Apps → your app → App InformationApple ID

Usage

import { readFileSync } from "node:fs";
import { AppleAppStoreAdapter } from "@jterrazz/broadcast";

const apple = new AppleAppStoreAdapter({
  issuerId: "57246542-96fe-1a63-e053-0824d011072a",
  keyId: "2X9R4HXF34",
  privateKey: readFileSync("./AuthKey_2X9R4HXF34.p8", "utf-8"),
  appId: "6444444444",
});

// Create an event
const result = await apple.create({
  title: "Election Live Coverage",
  shortDescription: "Real-time results & analysis",
  longDescription: "Follow live election coverage with AI-powered fact-checking and analysis.",
  badge: "live-event",
  audience: "all",
  priority: "high",
  startDate: new Date("2026-11-03"),
  endDate: new Date("2026-11-04"),
  deepLink: "signews://live/election-2026",
  territories: ["USA", "FRA"],
});

// List existing events
const events = await apple.list();

// Update an event
await apple.update("event-id", { priority: "normal" });

// Delete an event
await apple.delete("event-id");

Field Mapping

| Broadcast | Apple In-App Event | | ------------------ | ------------------------------------------------------------------------------ | | title | referenceName + localized name | | shortDescription | Localized shortDescription | | longDescription | Localized longDescription | | badge | badge (CHALLENGE, COMPETITION, etc.) | | audience | purpose (APPROPRIATE_FOR_ALL_USERS, ATTRACT_NEW_USERS, ATTRACT_LAPSED_USERS) | | priority | priority (NORMAL, HIGH) | | requiresPurchase | purchaseRequirement (NO_COST_ASSOCIATED, IN_APP_PURCHASE) | | territories | territorySchedules | | deepLink | deepLink |

Limits

  • Max 15 approved events at a time in App Store Connect
  • Max 10 events published simultaneously on the App Store
  • Events can last up to 31 days
  • Events can be promoted up to 14 days before start

More Providers (Planned)

  • Google Play Events — Google Play Store promotional events
  • Push Notifications — APNs and FCM
  • Email Digests — Transactional email providers
  • In-App Banners — JSON/REST endpoint for web and desktop apps

Multi-Provider Example

import { sendBroadcast } from "@jterrazz/broadcast";

const results = await sendBroadcast(broadcast, [apple, google, push]);

for (const result of results) {
  if (result.status === "failed") {
    console.error(`${result.provider} failed:`, result.raw);
  } else {
    console.log(`${result.provider}: ${result.status} (${result.id})`);
  }
}

Custom Provider

Implement BroadcastProviderPort to add your own channel:

import type { BroadcastProviderPort } from "@jterrazz/broadcast";

class SlackProvider implements BroadcastProviderPort {
  readonly name = "slack";

  async create(broadcast) {
    // Post to Slack webhook
  }

  async update(id, broadcast) {
    /* ... */
  }
  async delete(id) {
    /* ... */
  }
  async list() {
    /* ... */
  }
}

Development

npm install
npm test        # Run tests (vitest)
npm run build   # Build ESM + CJS (rolldown)
npm run lint    # Type check + oxlint + oxfmt