TypeScript SDK
With @todoke/sdk, you can implement everything from subscription registration to sending notifications in just a few lines.
Installation
Section titled “Installation”npm install @todoke/sdkbun add @todoke/sdkpnpm add @todoke/sdkInitializing the Client
Section titled “Initializing the Client”import { PushCF } from "@todoke/sdk";
const client = new PushCF({ apiKey: "pk_your_key", // baseUrl: "https://api.todoke.dev" // default value});Method Reference
Section titled “Method Reference”A PushCF instance provides the following three methods.
| Method | Description | Required scope |
|---|---|---|
notify(payload: NotifyPayload): Promise<void> | Sends a notification (POST /api/v1/notify) | notify or higher |
subscribe({ registration }: SubscribeOptions): Promise<void> | Registers the browser’s Push subscription | subscribe_only or higher |
getStats(): Promise<Stats> | Retrieves statistics (GET /api/v1/stats) | notify or higher |
Registering a Subscription
Section titled “Registering a Subscription”// Wait for Service Worker to be ready (place /sw.js in advance)const registration = await navigator.serviceWorker.ready;
// Register subscription (browser notification permission dialog appears)await client.subscribe({ registration });Internal Behavior
Section titled “Internal Behavior”subscribe performs the following three stages in order internally.
- Calls
GET /api/v1/vapid-public-keyto retrieve the app’s VAPID public key - Calls
registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey })with the retrieved key asapplicationServerKey(this is where the browser notification permission dialog appears) - Registers the created subscription info (
endpoint/p256dh/auth) with the server viaPOST /api/v1/subscriptions
Sending Notifications
Section titled “Sending Notifications”// Send to all subscribersawait client.notify({ title: "Announcement", body: "You have a new message", url: "https://yourapp.com/messages", icon: "https://yourapp.com/icon.png",});
// Send to a specific subscriberawait client.notify({ title: "For you", body: "Targeted notification", endpoint: "https://push.example.com/specific-endpoint",});Statistics
Section titled “Statistics”const stats = await client.getStats();// {// activeSubscribers: number,// totalSent: number,// totalFailed: number,// monthlySent: number// }Error Handling
Section titled “Error Handling”notify / subscribe / getStats all throw a PushCFError when the API returns an error response. PushCFError has status (the HTTP status code) and code (the API’s error code string; see the error code list) properties.
import { PushCF, PushCFError } from "@todoke/sdk";
try { await client.notify({ title: "Test", body: "Send" });} catch (err) { if (err instanceof PushCFError) { console.error(`[${err.code}] ${err.message} (status: ${err.status})`); }}Example of branching on a typical error code:
import { PushCF, PushCFError } from "@todoke/sdk";
try { await client.notify({ title: "hi", body: "yo" });} catch (err) { if (err instanceof PushCFError && err.code === "MONTHLY_LIMIT_EXCEEDED") { // Monthly limit reached. Wait until next month or upgrade your plan }}Type Definitions
Section titled “Type Definitions”type PushCFOptions = { apiKey: string; baseUrl?: string; // defaults to "https://api.todoke.dev"};
type NotifyPayload = { title: string; body: string; url?: string; // https:// only icon?: string; // https:// only badge?: string; // https:// only endpoint?: string; // if specified, sends only to this subscriber};
type SubscribeOptions = { registration: ServiceWorkerRegistration; // registered Service Worker};
type Stats = { activeSubscribers: number; totalSent: number; totalFailed: number; monthlySent: number;};