### Complete Configuration Setup Source: https://github.com/draphy/pushforge/blob/master/_autodocs/INDEX.txt Illustrates a comprehensive configuration setup with all options. ```typescript complete setup(...) ``` -------------------------------- ### Development Setup for PushForge Source: https://github.com/draphy/pushforge/blob/master/README.md This bash snippet outlines the steps to set up the PushForge development environment. It involves cloning the repository, installing dependencies using pnpm, and building the project. ```bash git clone https://github.com/draphy/pushforge.git cd pushforge pnpm install pnpm build ``` -------------------------------- ### Testing Configuration Setup Source: https://github.com/draphy/pushforge/blob/master/_autodocs/INDEX.txt Provides examples for setting up the configuration for testing purposes. ```typescript testing setup(...) ``` -------------------------------- ### Install @pushforge/builder Source: https://github.com/draphy/pushforge/blob/master/_autodocs/cli-reference.md Install the package using npm. The CLI is then available via the 'pushforge' command. ```bash npm install @pushforge/builder ``` -------------------------------- ### Install Dependencies and Build Project Source: https://github.com/draphy/pushforge/blob/master/CONTRIBUTING.md Install project dependencies using pnpm and then build the project packages. ```bash # Install dependencies pnpm install # Build packages pnpm build ``` -------------------------------- ### TypeScript Configuration Setup Source: https://github.com/draphy/pushforge/blob/master/_autodocs/INDEX.txt Shows how to configure the service using TypeScript. ```typescript TypeScript setup(...) ``` -------------------------------- ### Example Usage Flow for Sending Push Notifications Source: https://github.com/draphy/pushforge/blob/master/_autodocs/vapid-authentication.md A complete example demonstrating the preparation of options, building the push HTTP request using `@pushforge/builder`, and sending the request with `fetch`. ```typescript import { buildPushHTTPRequest, type BuilderOptions, type PushMessage } from "@pushforge/builder"; // 1. Prepare options const options: BuilderOptions = { privateJWK: process.env.VAPID_PRIVATE_KEY, subscription: { endpoint: "https://fcm.googleapis.com/fcm/send/…", keys: { p256dh: "BNcRd…", auth: "tBHI…" } }, message: { payload: { title: "Alert", body: "Check this out" }, adminContact: "mailto:admin@example.com", options: { ttl: 3600, urgency: "high", topic: "alerts" } } }; // 2. Build request (internally: creates JWT, derives encryption, builds headers) const { endpoint, body, headers } = await buildPushHTTPRequest(options); // 3. Send const response = await fetch(endpoint, { method: "POST", headers, body }); // Headers sent include: // Authorization: vapid t=JWT..., k=PUBLIC_KEY... // Encryption: salt=... // Crypto-Key: dh=... // TTL: 3600 // Topic: alerts // Urgency: high // Content-Encoding: aesgcm // Content-Type: application/octet-stream // Content-Length: 1024 ``` -------------------------------- ### Minimal Configuration Setup Source: https://github.com/draphy/pushforge/blob/master/_autodocs/INDEX.txt Shows the most basic configuration required to set up the service. ```typescript minimal setup(...) ``` -------------------------------- ### Install PushForge and Generate VAPID Keys Source: https://github.com/draphy/pushforge/blob/master/README.md This command-line snippet installs the PushForge builder package and then generates the necessary VAPID keys for your application. VAPID keys are essential for authenticating your server with push services. ```bash # Install npm install @pushforge/builder # Generate VAPID keys npx @pushforge/builder vapid ``` -------------------------------- ### Topic Configuration Examples Source: https://github.com/draphy/pushforge/blob/master/_autodocs/configuration.md Examples of using the 'topic' option to group and replace push messages based on use cases like news categories or chat conversations. ```typescript // News notifications - replace old news with new news options: { topic: "breaking-news" } ``` ```typescript // Chat notifications - one notification per conversation options: { topic: "chat_user_123" } ``` ```typescript // Reminders - only latest reminder shows options: { topic: "daily-reminder" } ``` ```typescript // Stock alerts - latest price update options: { topic: "AAPL-alert" } ``` -------------------------------- ### CLI Help Command Source: https://github.com/draphy/pushforge/blob/master/_autodocs/configuration.md Display available commands and usage examples for the PushForge CLI tool. ```bash npx @pushforge/builder help # or npx @pushforge/builder --help # or npx @pushforge/builder -h ``` -------------------------------- ### Urgency Configuration Examples Source: https://github.com/draphy/pushforge/blob/master/_autodocs/configuration.md Examples of setting the 'urgency' option to control the delivery priority of push messages, from 'very-low' for background sync to 'high' for immediate alerts. ```typescript // Chat message - deliver quickly options: { urgency: "high" } ``` ```typescript // Social media update - can wait options: { urgency: "low" } ``` ```typescript // System maintenance alert - immediate options: { urgency: "high" } ``` ```typescript // Background sync - very low priority options: { urgency: "very-low" } ``` -------------------------------- ### TTL Configuration Examples Source: https://github.com/draphy/pushforge/blob/master/_autodocs/configuration.md Provides examples of setting the Time-to-Live (TTL) for push messages, including short expiry, half-day, full-day (maximum), and using a helper function for clarity. ```typescript // Short expiry (1 hour) options: { ttl: 3600 } // Half day options: { ttl: 12 * 60 * 60 } // 43,200 // Full day (maximum, also the default) options: { ttl: 24 * 60 * 60 } // 86,400 // TTL in days const ttlInDays = (days: number) => days * 24 * 60 * 60; options: { ttl: ttlInDays(1) } // 86,400 ``` -------------------------------- ### Encryption Details Source: https://github.com/draphy/pushforge/blob/master/_autodocs/INDEX.txt Provides examples related to the encryption process. ```typescript encryption details(...) ``` -------------------------------- ### Check Node.js and npm Versions Source: https://github.com/draphy/pushforge/blob/master/_autodocs/cli-reference.md Verifies that Node.js and npm are installed and meet the minimum required versions. ```bash node --version # Should be 20.0.0+ npm --version # Should be 7+ ``` -------------------------------- ### Payload Size Validation Examples Source: https://github.com/draphy/pushforge/blob/master/_autodocs/payload-encryption.md Illustrates payload size validation for PushForge. The first example shows a payload exceeding the maximum allowed size, while the second demonstrates an acceptable payload size. ```typescript const payload = "x".repeat(4077); // Too large // Throws: Payload too large. Maximum size is 4076 bytes, but received 4077 bytes ``` ```typescript const payload = "x".repeat(4076); // OK // Works fine ``` -------------------------------- ### CLI VAPID Command Usage Source: https://github.com/draphy/pushforge/blob/master/_autodocs/INDEX.txt Examples showing how to use the CLI command for VAPID authentication. ```bash cli vapid command(...) ``` -------------------------------- ### Full Notification Payload Example Source: https://github.com/draphy/pushforge/blob/master/packages/builder/README.md Demonstrates sending a push notification with a comprehensive payload, including title, body, icon, image, actions, and custom data. This example showcases advanced options for notification display and interaction. ```typescript const { endpoint, headers, body } = await buildPushHTTPRequest({ privateJWK, subscription, message: { payload: { title: "New Message", body: "John: Hey, are you free?", icon: "/icons/chat.png", badge: "/icons/badge.png", image: "/images/preview.jpg", tag: "chat-john", renotify: true, actions: [ { action: "reply", title: "Reply" }, { action: "dismiss", title: "Dismiss" } ], data: { url: "/chat/john", messageId: "123" } }, adminContact: "mailto:admin@example.com", options: { urgency: "high", ttl: 3600 } } }); ``` -------------------------------- ### Public API Import Example Source: https://github.com/draphy/pushforge/blob/master/_autodocs/utilities.md Shows the correct import paths for accessing the public API of the @pushforge/builder package. ```typescript // Exported from @pushforge/builder import { buildPushHTTPRequest, type BuilderOptions, type PushMessage, type PushSubscription, type PushOptions } from "@pushforge/builder"; ``` -------------------------------- ### Base64 Decode Example Source: https://github.com/draphy/pushforge/blob/master/_autodocs/utilities.md Example of using the base64Decode function to convert a base64 string into a binary string. It handles strings with or without padding. ```typescript import { base64Decode } from "@pushforge/builder"; const base64 = "SGVsbG8sIFdvcmxkIQ"; const binary = base64Decode(base64); // Result: "Hello, World!" (as binary string) // Without padding (adds automatically) const noPadding = "SGVsbG8sIFdvcmxkIQ"; const decoded = base64Decode(noPadding); // With padding const withPadding = "SGVsbG8sIFdvcmxkIQ=="; const decoded2 = base64Decode(withPadding); ``` -------------------------------- ### Error Handling Examples Source: https://github.com/draphy/pushforge/blob/master/_autodocs/INDEX.txt Demonstrates various approaches to handling errors within the system. ```typescript error handling(...) ``` -------------------------------- ### Minimal PushForge Configuration Source: https://github.com/draphy/pushforge/blob/master/_autodocs/configuration.md A basic example demonstrating the minimal configuration required to send a push notification using PushForge, including importing the necessary function and providing essential parameters. ```typescript import { buildPushHTTPRequest } from "@pushforge/builder"; const request = await buildPushHTTPRequest({ privateJWK: process.env.VAPID_PRIVATE_KEY, subscription: userSubscription, message: { payload: { title: "Hello" }, adminContact: "mailto:admin@example.com" } }); ``` -------------------------------- ### Example Conventional Commit Message Source: https://github.com/draphy/pushforge/blob/master/CONTRIBUTING.md An example of a commit message following the Conventional Commits format for a new feature. ```text feat: [WPN-123] Add support for Safari push notifications ``` -------------------------------- ### Build Push HTTP Request Function Usage Source: https://github.com/draphy/pushforge/blob/master/_autodocs/INDEX.txt Examples demonstrating the usage of the buildPushHTTPRequest function. ```typescript buildPushHTTPRequest(...) ``` -------------------------------- ### Send Notifications (Server) Source: https://github.com/draphy/pushforge/blob/master/packages/builder/README.md Build and send a push notification from the server using the VAPID private key and the user's subscription. This example demonstrates constructing the HTTP request for the push service. ```typescript import { buildPushHTTPRequest } from "@pushforge/builder"; // Your VAPID private key (JWK format from step 1) const privateJWK = { kty: "EC", crv: "P-256", x: "...", y: "...", d: "..." }; // The subscription object from the user's browser const subscription = { endpoint: "https://fcm.googleapis.com/fcm/send/...", keys: { p256dh: "BNcRd...", auth: "tBHI..." } }; // Build and send the notification const { endpoint, headers, body } = await buildPushHTTPRequest({ privateJWK, subscription, message: { payload: { title: "New Message", body: "You have a new notification!", icon: "/icon.png" }, adminContact: "mailto:admin@example.com" } }); const response = await fetch(endpoint, { method: "POST", headers, body }); if (response.status === 201) { console.log("Notification sent"); } ``` -------------------------------- ### TypeScript Setup for Sending Push Notifications Source: https://github.com/draphy/pushforge/blob/master/_autodocs/quick-start.md Set up TypeScript to send push notifications using the @pushforge/builder package. Ensure VAPID_PRIVATE_KEY is set in your environment. ```typescript import { buildPushHTTPRequest } from "@pushforge/builder"; import type { PushMessage, PushSubscription } from "@pushforge/builder"; interface NotificationPayload { title: string; body: string; icon?: string; image?: string; badge?: string; } async function sendPush( subscription: PushSubscription, payload: NotificationPayload ) { const response = await buildPushHTTPRequest({ privateJWK: process.env.VAPID_PRIVATE_KEY!, subscription, message: { payload, adminContact: "mailto:admin@example.com", options: { ttl: 3600, urgency: "high" } } }); return fetch(response.endpoint, { method: "POST", headers: response.headers, body: response.body }); } ``` -------------------------------- ### Update npm to Latest Version Source: https://github.com/draphy/pushforge/blob/master/_autodocs/cli-reference.md Installs the latest version of npm, which is recommended if 'npx: command not found' error occurs. ```bash npm install -g npm@latest ``` -------------------------------- ### Topic Replacement Example Source: https://github.com/draphy/pushforge/blob/master/_autodocs/configuration.md Demonstrates how sending a second message with the same topic replaces the first pending message, ensuring only the latest notification is seen by the user. ```typescript // First message await buildPushHTTPRequest({ privateJWK, subscription, message: { payload: { title: "AAPL", price: "150.00" }, adminContact: "mailto:admin@example.com", options: { topic: "stock-alert", ttl: 3600 } } }); // Second message with same topic - replaces the first await buildPushHTTPRequest({ privateJWK, subscription, message: { payload: { title: "AAPL", price: "150.25" }, // Updated price adminContact: "mailto:admin@example.com", options: { topic: "stock-alert", ttl: 3600 } } }); // User sees only the second message notification ``` -------------------------------- ### Serve Public Key via Backend API Source: https://github.com/draphy/pushforge/blob/master/_autodocs/configuration.md An example of a backend API endpoint that serves the VAPID public key. This key is then fetched by the frontend to subscribe the user to push notifications. ```typescript // Backend API endpoint app.get('/api/config/push-public-key', (req, res) => { res.json({ publicKey: process.env.VAPID_PUBLIC_KEY }); }); // Frontend const response = await fetch('/api/config/push-public-key'); const { publicKey } = await response.json(); const subscription = await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: publicKey }); ``` -------------------------------- ### Send Push Notification in Deno Source: https://github.com/draphy/pushforge/blob/master/packages/builder/README.md Example of sending a push notification using the buildPushHTTPRequest function in Deno. Requires setting the VAPID_PRIVATE_KEY environment variable. ```typescript import { buildPushHTTPRequest } from "npm:@pushforge/builder"; const { endpoint, headers, body } = await buildPushHTTPRequest({ privateJWK: JSON.parse(Deno.env.get("VAPID_PRIVATE_KEY")!), subscription, message: { payload: { title: "Hello from Deno!" }, adminContact: "mailto:admin@example.com" } }); await fetch(endpoint, { method: "POST", headers, body }); ``` -------------------------------- ### Send Push Notification in Bun Source: https://github.com/draphy/pushforge/blob/master/packages/builder/README.md Example of sending a push notification using the buildPushHTTPRequest function in Bun. Requires setting the VAPID_PRIVATE_KEY environment variable. ```typescript import { buildPushHTTPRequest } from "@pushforge/builder"; const { endpoint, headers, body } = await buildPushHTTPRequest({ privateJWK: JSON.parse(Bun.env.VAPID_PRIVATE_KEY!), subscription, message: { payload: { title: "Hello from Bun!" }, adminContact: "mailto:admin@example.com" } }); await fetch(endpoint, { method: "POST", headers, body }); ``` -------------------------------- ### Catching and Handling Errors Source: https://github.com/draphy/pushforge/blob/master/_autodocs/utilities.md Example of using a try-catch block to handle potential errors during the build process, with specific checks for common error messages. ```typescript try { await buildPushHTTPRequest(options); } catch (error) { if (error instanceof Error) { if (error.message.includes("Invalid JWK")) { // Handle JWK validation errors } else if (error.message.includes("TTL")) { // Handle TTL errors } else if (error.message.includes("Payload too large")) { // Handle payload size errors } else { // Other errors (encryption, network, etc.) } } } ``` -------------------------------- ### Load VAPID Private Key from Environment Source: https://github.com/draphy/pushforge/blob/master/_autodocs/configuration.md Example of loading the VAPID private key from an environment variable within a TypeScript application. Ensure the environment variable is set before runtime. ```typescript // Load from environment const VAPID_PRIVATE_KEY = process.env.VAPID_PRIVATE_KEY; if (!VAPID_PRIVATE_KEY) { throw new Error('VAPID_PRIVATE_KEY environment variable not set'); } // Use in your application await buildPushHTTPRequest({ privateJWK: VAPID_PRIVATE_KEY, subscription, message }); ``` -------------------------------- ### Error Handling with buildPushHTTPRequest Source: https://github.com/draphy/pushforge/blob/master/_autodocs/buildPushHTTPRequest.md Provides an example of how to implement error handling when using `buildPushHTTPRequest`, catching potential errors related to invalid keys, endpoints, or TTL values. ```APIDOC ## buildPushHTTPRequest Error Handling ### Description This example demonstrates how to catch and handle errors that may occur during the execution of `buildPushHTTPRequest`, such as issues with VAPID keys, subscription endpoints, or message options. ### Error Handling Use a `try...catch` block to handle potential errors. Specific error messages can be checked to provide more granular feedback. ### Request Example ```typescript try { const request = await buildPushHTTPRequest({ privateJWK: invalidKey, subscription, message }); } catch (error) { if (error instanceof Error) { if (error.message.includes("Invalid JWK")) { console.error("Invalid VAPID key:", error.message); } else if (error.message.includes("Invalid subscription endpoint")) { console.error("Invalid endpoint:", error.message); } else if (error.message.includes("TTL must be less")) { console.error("TTL too long:", error.message); } else { console.error("Encryption failed:", error.message); } } } ``` ``` -------------------------------- ### Valid P256DH Key Example Source: https://github.com/draphy/pushforge/blob/master/_autodocs/payload-encryption.md Demonstrates a valid p256dh key that decodes to exactly 65 bytes. This is used for secure key exchange in push notifications. ```typescript p256dh: "BNcRd8xz..." // ~87 base64url chars → 65 bytes ``` -------------------------------- ### CLI Commands for VAPID Key Generation and Help Source: https://github.com/draphy/pushforge/blob/master/_autodocs/utilities.md Demonstrates how to use the PushForge CLI to generate VAPID key pairs and access help information. ```bash # Generate new VAPID key pair npx @pushforge/builder vapid # Show help npx @pushforge/builder help npx @pushforge/builder --help npx @pushforge/builder -h # Default (shows help) npx @pushforge/builder ``` -------------------------------- ### Invalid P256DH Key Examples Source: https://github.com/draphy/pushforge/blob/master/_autodocs/payload-encryption.md Shows invalid p256dh keys that do not decode to the expected 65 bytes. These examples highlight incorrect lengths that will cause validation errors. ```typescript p256dh: "AAAA" // ~3 bytes ``` ```typescript p256dh: "BNcRd8" // ~4 bytes ``` -------------------------------- ### Run @pushforge/builder CLI Source: https://github.com/draphy/pushforge/blob/master/_autodocs/cli-reference.md Execute the CLI tool using npx, specifying the command and any options. ```bash npx @pushforge/builder [options] ``` -------------------------------- ### Recommended Environment Variables for PushForge Source: https://github.com/draphy/pushforge/blob/master/_autodocs/configuration.md Lists recommended environment variables for backend server configuration, including VAPID private and public keys. ```bash # Backend server configuration VAPID_PRIVATE_KEY="" VAPID_PUBLIC_KEY="" # For frontend distribution ``` -------------------------------- ### Minimal Configuration Source: https://github.com/draphy/pushforge/blob/master/_autodocs/buildPushHTTPRequest.md Shows the minimum required configuration for `buildPushHTTPRequest`, highlighting that the `options` field is optional and only TTL is strictly required within it if other options are omitted. ```APIDOC ## buildPushHTTPRequest Minimal Configuration ### Description This example shows the minimal configuration required for `buildPushHTTPRequest`. The `options` object is optional, and within it, `ttl` is a key parameter if other options are not specified. ### Parameters - **message.payload** (object) - Required. The notification content. - **message.adminContact** (string) - Required. The administrator's contact email. - **message.options.ttl** (number) - Optional. Time-to-live in seconds. If `options` is provided but `ttl` is omitted, a default TTL might be applied or an error could occur depending on the library's internal logic. However, the example implies `ttl` is the primary option needed if the `options` object is present. ### Request Example ```typescript // Only TTL is required in options if not all options provided const request = await buildPushHTTPRequest({ privateJWK, subscription, message: { payload: { title: "Alert" }, adminContact: "mailto:admin@example.com" // options field can be omitted if not needed } }); ``` ``` -------------------------------- ### Display Help Information Source: https://github.com/draphy/pushforge/blob/master/_autodocs/cli-reference.md Show help messages for the CLI, including available commands and syntax. ```bash npx @pushforge/builder help ``` ```bash npx @pushforge/builder --help ``` ```bash npx @pushforge/builder -h ``` -------------------------------- ### Environment-Specific Configuration Source: https://github.com/draphy/pushforge/blob/master/_autodocs/INDEX.txt Demonstrates how to configure the service for different environments. ```typescript environment-specific(...) ``` -------------------------------- ### Import All Types from @pushforge/builder Source: https://github.com/draphy/pushforge/blob/master/_autodocs/types.md Demonstrates how to import all exported types from the main entry point of the @pushforge/builder package. ```typescript // Import all types import type { PushMessage, PushSubscription, BuilderOptions, PushOptions, } from "@pushforge/builder"; ``` -------------------------------- ### Type Utility Usage Source: https://github.com/draphy/pushforge/blob/master/_autodocs/INDEX.txt Examples of using utility types for type manipulation. ```typescript type utilities(...) ``` -------------------------------- ### Generic Parameter Type Usage Source: https://github.com/draphy/pushforge/blob/master/_autodocs/INDEX.txt Examples of using generic parameters in type definitions. ```typescript generic parameters(...) ``` -------------------------------- ### Clone Repository and Set Up Upstream Remote Source: https://github.com/draphy/pushforge/blob/master/CONTRIBUTING.md Clone your fork of the repository and add the original repository as an upstream remote for fetching updates. ```bash git clone https://github.com/yourusername/pushforge.git cd pushforge git remote add upstream https://github.com/draphy/pushforge.git ``` -------------------------------- ### Jsonifiable Type Examples (Invalid) Source: https://github.com/draphy/pushforge/blob/master/_autodocs/types.md Illustrates values that do not conform to the Jsonifiable type, such as undefined, functions, and symbols. ```typescript undefined ``` ```typescript () => {} ``` ```typescript Symbol('sym') ``` ```typescript new Date() ``` ```typescript { a: undefined } ``` ```typescript { b: () => {} } ``` -------------------------------- ### Run Code Quality Tools Source: https://github.com/draphy/pushforge/blob/master/CONTRIBUTING.md Execute Biome for formatting and linting, run type checking, and perform a comprehensive check before committing. ```bash # Format and lint with Biome pnpm biome:format pnpm biome:lint # Run type checking pnpm type:check # Run all checks and build (recommended before commit) pnpm commit:check ``` -------------------------------- ### Minimal Configuration Request Source: https://github.com/draphy/pushforge/blob/master/_autodocs/buildPushHTTPRequest.md Shows the minimum required options for building a push request when not all options are needed. The 'options' field itself can be omitted if not required. ```typescript // Only TTL is required in options if not all options provided const request = await buildPushHTTPRequest({ privateJWK, subscription, message: { payload: { title: "Alert" }, adminContact: "mailto:admin@example.com" // options field can be omitted if not needed } }); ``` -------------------------------- ### Jsonifiable Type Examples (Valid) Source: https://github.com/draphy/pushforge/blob/master/_autodocs/types.md Demonstrates values that conform to the Jsonifiable type, including primitives, arrays, and objects. ```typescript "hello" ``` ```typescript 42 ``` ```typescript true ``` ```typescript null ``` ```typescript [1, "two", { three: true }] ``` ```typescript { title: "Hello", body: "World", count: 123 } ``` ```typescript { nested: { deeply: { data: [1, 2, 3] } } } ``` -------------------------------- ### Using buildPushHTTPRequest with fetch Source: https://github.com/draphy/pushforge/blob/master/_autodocs/vapid-authentication.md Demonstrates how to use the `buildPushHTTPRequest` function to generate headers and then send a push notification using `fetch`. ```typescript const headers = await vapidHeaders(...); // Usage with fetch await fetch(endpoint, { method: "POST", headers, body }); ``` -------------------------------- ### Get Public Key from JWK Source: https://github.com/draphy/pushforge/blob/master/_autodocs/module-index.md Extracts the public key information from a JSON Web Key (JWK) object. ```typescript export const getPublicKeyFromJwk(jwk: JsonWebKey): string ``` -------------------------------- ### RequireAtLeastOne Usage Example Source: https://github.com/draphy/pushforge/blob/master/_autodocs/utilities.md Demonstrates how to use the RequireAtLeastOne type to ensure an object has at least one of the specified optional properties. ```typescript // PushMessage.options requires at least one of ttl, topic, urgency options?: RequireAtLeastOne<{ ttl?: number; topic?: string; urgency?: 'very-low' | 'low' | 'normal' | 'high'; }>; ``` -------------------------------- ### RequireAtLeastOne Usage Example Source: https://github.com/draphy/pushforge/blob/master/_autodocs/types.md Compares the behavior of a type without RequireAtLeastOne to one with it, demonstrating how it enforces the presence of at least one property. ```typescript // Without RequireAtLeastOne type OptionsAny = { ttl?: number; topic?: string; urgency?: string; }; // All of these would be valid (undesirable): const opt1: OptionsAny = {}; const opt2: OptionsAny = { ttl: 3600 }; // With RequireAtLeastOne type OptionsRequired = RequireAtLeastOne<{ ttl?: number; topic?: string; urgency?: string; }>; // Empty object is now invalid: const opt3: OptionsRequired = {}; // ERROR // At least one field is required: const opt4: OptionsRequired = { ttl: 3600 }; // OK const opt5: OptionsRequired = { topic: "news", urgency: "high" }; // OK ``` -------------------------------- ### Generate Keys and Store in File Source: https://github.com/draphy/pushforge/blob/master/_autodocs/cli-reference.md Generate VAPID keys and redirect the output to a JSON file for local storage. ```bash # Generate keys npx @pushforge/builder vapid > vapid-keys.json # Keys are now in vapid-keys.json in JSON format cat vapid-keys.json ``` -------------------------------- ### Build Push HTTP Request with Invalid Endpoint URL Source: https://github.com/draphy/pushforge/blob/master/_autodocs/errors.md This example shows how an invalid URL format for the subscription endpoint triggers an error. ```typescript await buildPushHTTPRequest({ privateJWK, subscription: { endpoint: "not a url", // Invalid URL format keys: { p256dh: "...", auth: "..." } }, message }); // Throws: Error: Invalid subscription endpoint: 'not a url' is not a valid URL ``` -------------------------------- ### VAPID Public Key Format Source: https://github.com/draphy/pushforge/blob/master/_autodocs/cli-reference.md The public key is a Base64url-encoded string representing an EC P-256 uncompressed point. It starts with a 0x04 marker. ```bash BFb6M4yJ9nXNhBo8e4vvPYzHBGZiLIm... ^ ``` -------------------------------- ### Build Push HTTP Request with PushForge Source: https://github.com/draphy/pushforge/blob/master/README.md Use this snippet to construct the necessary HTTP request for sending a push notification. It requires your VAPID private key, the user's subscription details, and the message payload. Ensure you have the necessary environment variables or keys configured. ```typescript import { buildPushHTTPRequest } from "@pushforge/builder"; const { endpoint, headers, body } = await buildPushHTTPRequest({ privateJWK: VAPID_PRIVATE_KEY, subscription: userSubscription, message: { payload: { title: "Hello!", body: "This works everywhere." }, adminContact: "mailto:admin@example.com" } }); await fetch(endpoint, { method: "POST", headers, body }); ``` -------------------------------- ### Importing Builder Functions and Types Source: https://github.com/draphy/pushforge/blob/master/_autodocs/module-index.md Import core functions and types from the package root. This is the recommended way to use the library. ```typescript import { buildPushHTTPRequest } from "@pushforge/builder"; import type { BuilderOptions, PushMessage, PushSubscription, PushOptions } from "@pushforge/builder"; ``` -------------------------------- ### Environment Variables for VAPID Keys Source: https://github.com/draphy/pushforge/blob/master/_autodocs/quick-start.md Configure your environment with VAPID private and public keys for secure push notification generation. ```bash # .env VAPID_PRIVATE_KEY={"alg":"ES256","kty":"EC",...} VAPID_PUBLIC_KEY=BFb6M4yJ9nXNhBo8... NODE_ENV=production ``` -------------------------------- ### Main Entry Point Exports Source: https://github.com/draphy/pushforge/blob/master/_autodocs/module-index.md Exports from the main entry point of the @pushforge/builder package, including types and the main build function. ```typescript export type { PushMessage, PushSubscription, BuilderOptions, PushOptions, } from './types.js'; export { buildPushHTTPRequest } from './request.js'; ``` -------------------------------- ### Key Rotation Best Practice Source: https://github.com/draphy/pushforge/blob/master/_autodocs/INDEX.txt Demonstrates best practices for rotating cryptographic keys. ```typescript key rotation(...) ``` -------------------------------- ### Using String JWK Source: https://github.com/draphy/pushforge/blob/master/_autodocs/buildPushHTTPRequest.md Demonstrates how to pass the VAPID private key as a JSON string instead of a JavaScript object. ```APIDOC ## buildPushHTTPRequest with String JWK ### Description This example shows how to use `buildPushHTTPRequest` when the VAPID private key is provided as a JSON string. ### Parameters - **privateJWK** (string) - The VAPID private key as a JSON string. ### Request Example ```typescript const privateJWKString = '{"kty":"EC","crv":"P-256","d":"...","x":"...","y":"..."}'; const request = await buildPushHTTPRequest({ privateJWK: privateJWKString, // Pass as string subscription: userSubscription, message: { payload: { title: "Hello" }, adminContact: "mailto:admin@example.com", options: { ttl: 86400 } // 24 hours } }); ``` ``` -------------------------------- ### Vercel Edge Function to Send Push Notification Source: https://github.com/draphy/pushforge/blob/master/packages/builder/README.md Example of a Vercel Edge Function that processes a request, builds a push notification request using buildPushHTTPRequest, and sends it. ```typescript import { buildPushHTTPRequest } from "@pushforge/builder"; export const config = { runtime: "edge" }; export default async function handler(request: Request) { const subscription = await request.json(); const { endpoint, headers, body } = await buildPushHTTPRequest({ privateJWK: JSON.parse(process.env.VAPID_PRIVATE_KEY!), subscription, message: { payload: { title: "Edge Notification" }, adminContact: "mailto:admin@example.com" } }); await fetch(endpoint, { method: "POST", headers, body }); return new Response("Sent", { status: 200 }); } ``` -------------------------------- ### Cloudflare Worker to Send Push Notification Source: https://github.com/draphy/pushforge/blob/master/packages/builder/README.md Example of a Cloudflare Worker that receives a push subscription, builds a push HTTP request using buildPushHTTPRequest, and sends the notification. ```javascript export default { async fetch(request, env) { const subscription = await request.json(); const { endpoint, headers, body } = await buildPushHTTPRequest({ privateJWK: JSON.parse(env.VAPID_PRIVATE_KEY), subscription, message: { payload: { title: "Hello from the Edge!" }, adminContact: "mailto:admin@example.com" } }); return fetch(endpoint, { method: "POST", headers, body }); } }; ``` -------------------------------- ### Valid Message Configurations with Options Source: https://github.com/draphy/pushforge/blob/master/_autodocs/configuration.md Demonstrates valid configurations for the message.options object, including using only ttl, only topic, only urgency, or a combination of all three. ```typescript // Valid: only ttl message: { payload: { title: "Test" }, adminContact: "mailto:admin@example.com", options: { ttl: 3600 } } // Valid: only topic message: { payload: { title: "Test" }, adminContact: "mailto:admin@example.com", options: { topic: "news-updates" } } // Valid: only urgency message: { payload: { title: "Test" }, adminContact: "mailto:admin@example.com", options: { urgency: "high" } } // Valid: combination message: { payload: { title: "Test" }, adminContact: "mailto:admin@example.com", options: { ttl: 3600, topic: "news-updates", urgency: "high" } } ``` -------------------------------- ### TypeScript: Invalid p256dh Key Format Source: https://github.com/draphy/pushforge/blob/master/_autodocs/errors.md This error occurs when the p256dh key does not start with the expected 0x04 prefix, indicating an uncompressed elliptic curve point format. ```typescript const badKey = new Uint8Array(65); badKey[0] = 0x05; // Wrong prefix const badKeyB64 = base64UrlEncode(badKey); await buildPushHTTPRequest({ privateJWK, subscription: { endpoint: "https://fcm.googleapis.com/fcm/send/", keys: { p256dh: badKeyB64, auth: "valid_auth_key" } }, message }); // Throws: Error: Invalid p256dh key: expected uncompressed point format (0x04 prefix) but got 0x05 ``` -------------------------------- ### Performance Optimization Best Practice Source: https://github.com/draphy/pushforge/blob/master/_autodocs/INDEX.txt Provides guidance on optimizing the performance of the system. ```typescript performance optimization(...) ``` -------------------------------- ### Save VAPID Keys to File and Secure Permissions Source: https://github.com/draphy/pushforge/blob/master/_autodocs/cli-reference.md Demonstrates saving generated VAPID keys to a JSON file and setting restrictive file permissions. ```bash # Save to file npx @pushforge/builder vapid > ~/.pushforge/vapid-keys.json chmod 600 ~/.pushforge/vapid-keys.json # Or copy to secure location npx @pushforge/builder vapid | tee >(pbcopy) # Copy to clipboard on macOS ``` -------------------------------- ### Default CLI Behavior (No Arguments) Source: https://github.com/draphy/pushforge/blob/master/_autodocs/cli-reference.md When no arguments are provided, the CLI displays the help message and exits successfully. ```bash npx @pushforge/builder ``` -------------------------------- ### Secret Management Best Practice Source: https://github.com/draphy/pushforge/blob/master/_autodocs/INDEX.txt Illustrates best practices for managing secrets securely. ```typescript secret management(...) ``` -------------------------------- ### Send Push Notification in Convex Source: https://github.com/draphy/pushforge/blob/master/packages/builder/README.md Example of sending a push notification using the buildPushHTTPRequest function within a Convex action. Requires setting the VAPID_PRIVATE_KEY environment variable and using the Node.js runtime. ```typescript "use node"; import { action } from "./_generated/server"; import { buildPushHTTPRequest } from "@pushforge/builder"; import { v } from "convex/values"; export const sendPush = action({ args: { subscription: v.any(), title: v.string(), body: v.string() }, handler: async (ctx, { subscription, title, body }) => { const { endpoint, headers, body: reqBody } = await buildPushHTTPRequest({ privateJWK: JSON.parse(process.env.VAPID_PRIVATE_KEY!), subscription, message: { payload: { title, body }, adminContact: "mailto:admin@example.com" } }); await fetch(endpoint, { method: "POST", headers, body: reqBody }); } }); ``` -------------------------------- ### Display Help Message (CLI) Source: https://github.com/draphy/pushforge/blob/master/_autodocs/module-index.md CLI tool function to display the help message for the VAPID key generation tool. Activated by 'help', '--help', or '-h' arguments. ```typescript showHelp() ``` -------------------------------- ### Build Push HTTP Request with TTL Exceeding 24 Hours Source: https://github.com/draphy/pushforge/blob/master/_autodocs/errors.md This example shows the error triggered when the message's Time-to-Live (TTL) option is set to a value greater than 24 hours (86,400 seconds). ```typescript await buildPushHTTPRequest({ privateJWK, subscription, message: { payload: { title: "Test" }, adminContact: "mailto:admin@example.com", options: { ttl: 86401 // 24 hours + 1 second } } }); // Throws: Error: TTL must be less than 24 hours ``` -------------------------------- ### Generate and Capture VAPID Keys Source: https://github.com/draphy/pushforge/blob/master/_autodocs/cli-reference.md Generates VAPID keys using the Pushforge builder and saves the output to a file. ```bash npx @pushforge/builder vapid > vapid-keys.txt ``` -------------------------------- ### Import Crypto Module Source: https://github.com/draphy/pushforge/blob/master/_autodocs/crypto-module.md Imports the crypto module from `@pushforge/builder`. An error is thrown if the Web Crypto API is not available in the runtime environment. ```typescript import { crypto } from "@pushforge/builder"; // Error: Web Crypto API not available... ``` -------------------------------- ### Securely Load Private Key (Node.js) Source: https://github.com/draphy/pushforge/blob/master/_autodocs/cli-reference.md Demonstrates secure methods for loading the VAPID private key in a Node.js application, emphasizing environment variables and secret vaults. ```typescript // ✓ Good: Load from environment const privateJWK = process.env.VAPID_PRIVATE_KEY; // ✓ Good: Load from secure vault import { getSecret } from 'your-secret-manager'; const privateJWK = await getSecret('vapid-private-key'); // ✗ Bad: Hardcoded in code const privateJWK = '{"d":"secret..."}'; // Don't do this! // ✗ Bad: In version control // keys.json (never commit this!) ```