@spoolcms/nextjs
Version:
The beautiful headless CMS for Next.js developers
126 lines (125 loc) • 4.18 kB
TypeScript
/**
* Webhook utilities for Spool CMS
* Use these functions in your Next.js webhook endpoints to verify and handle Spool webhooks
*
* NOTE: For live updates, use the new useSpoolLiveUpdates hook instead of webhooks.
* Webhooks are still useful for production deployments and server-side processing.
*/
export interface SpoolWebhookPayload {
event: 'content.created' | 'content.updated' | 'content.published' | 'content.deleted';
site_id: string;
collection: string;
slug?: string;
item_id: string;
timestamp: string;
}
/**
* Verify webhook signature from Spool CMS
* Use this in your webhook endpoint to ensure the request is from Spool
*
* @param payload - The raw request body as a string
* @param signature - The X-Spool-Signature-256 header value
* @param secret - Your webhook secret from Spool admin settings
* @returns true if signature is valid, false otherwise
*
* @example
* ```typescript
* import { verifySpoolWebhook } from '@spoolcms/nextjs';
*
* export async function POST(request: Request) {
* const payload = await request.text();
* const signature = request.headers.get('x-spool-signature-256');
* const secret = process.env.SPOOL_WEBHOOK_SECRET;
*
* if (secret && signature && !verifySpoolWebhook(payload, signature, secret)) {
* return new Response('Unauthorized', { status: 401 });
* }
*
* // Process webhook...
* }
* ```
*/
export declare function verifySpoolWebhook(payload: string, signature: string, secret: string): boolean;
/**
* Parse and validate Spool webhook payload
*
* @param payload - The raw request body as a string
* @returns Parsed webhook payload or null if invalid
*
* @example
* ```typescript
* import { parseSpoolWebhook } from '@spoolcms/nextjs';
*
* export async function POST(request: Request) {
* const payload = await request.text();
* const data = parseSpoolWebhook(payload);
*
* if (!data) {
* return new Response('Invalid payload', { status: 400 });
* }
*
* console.log(`Received ${data.event} for ${data.collection}/${data.slug}`);
* }
* ```
*/
export declare function parseSpoolWebhook(payload: string): SpoolWebhookPayload | null;
/**
* Get webhook headers from a Request object
* Extracts Spool-specific headers for logging and debugging
*
* @param request - The Next.js Request object
* @returns Object with Spool webhook headers
*
* @example
* ```typescript
* import { getSpoolWebhookHeaders } from '@spoolcms/nextjs';
*
* export async function POST(request: Request) {
* const headers = getSpoolWebhookHeaders(request);
* console.log(`Processing delivery ${headers.deliveryId} for event ${headers.event}`);
* }
* ```
*/
export declare function getSpoolWebhookHeaders(request: Request): {
signature?: string;
deliveryId?: string;
event?: string;
userAgent?: string;
};
/**
* Create a simple webhook handler with verification and parsing
*
* NOTE: For live updates, use the new useSpoolLiveUpdates hook instead.
* This webhook handler is for production deployments and server-side processing only.
*
* @param options - Configuration options
* @returns Webhook handler function
*
* @example
* ```typescript
* import { createSpoolWebhookHandler } from '@spoolcms/nextjs';
* import { revalidatePath } from 'next/cache';
*
* const handleWebhook = createSpoolWebhookHandler({
* secret: process.env.SPOOL_WEBHOOK_SECRET,
* onWebhook: async (data, headers) => {
* console.log(`Processing ${data.event} for ${data.collection}/${data.slug}`);
*
* // Revalidate paths based on collection
* if (data.collection === 'blog') {
* revalidatePath('/blog');
* if (data.slug) revalidatePath(`/blog/${data.slug}`);
* }
*
* revalidatePath('/');
* }
* });
*
* export const POST = handleWebhook;
* ```
*/
export declare function createSpoolWebhookHandler(options: {
secret?: string;
onWebhook?: (data: SpoolWebhookPayload, headers: ReturnType<typeof getSpoolWebhookHeaders>) => Promise<void> | void;
onError?: (error: Error, request: Request) => Promise<Response> | Response;
}): (request: Request) => Promise<Response>;