UNPKG

@idealite/web-services

Version:

Comprehensive web services library with webhook system and Mux integration

142 lines (141 loc) 6.32 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MuxWebhookReceiver = void 0; const base_webhook_receiver_abstract_1 = require("../abstracts/base-webhook-receiver.abstract"); const mux_webhook_verifier_1 = require("../utils/mux-webhook-verifier"); const mux_event_handlers_1 = require("../handlers/mux-event-handlers"); /** * Mux-specific webhook receiver implementation * Handles incoming webhooks from Mux video service */ class MuxWebhookReceiver extends base_webhook_receiver_abstract_1.BaseWebhookReceiver { constructor(webhookSecret) { super(); if (webhookSecret) { this.verifier = new mux_webhook_verifier_1.MuxWebhookVerifier(webhookSecret); } // Register default handlers this.registerDefaultHandlers(); } registerDefaultHandlers() { // Video asset handlers this.registerHandler(new mux_event_handlers_1.VideoAssetReadyHandler(true)); this.registerHandler(new mux_event_handlers_1.VideoAssetErrorHandler(true)); // Live stream handlers this.registerHandler(new mux_event_handlers_1.LiveStreamHandler('video.live_stream.connected', true)); this.registerHandler(new mux_event_handlers_1.LiveStreamHandler('video.live_stream.disconnected', true)); this.registerHandler(new mux_event_handlers_1.LiveStreamHandler('video.live_stream.recording', true)); this.registerHandler(new mux_event_handlers_1.LiveStreamHandler('video.live_stream.active', true)); this.registerHandler(new mux_event_handlers_1.LiveStreamHandler('video.live_stream.idle', true)); // Upload handlers this.registerHandler(new mux_event_handlers_1.MuxUploadHandler('video.upload.asset_created', true)); this.registerHandler(new mux_event_handlers_1.MuxUploadHandler('video.upload.errored', true)); this.registerHandler(new mux_event_handlers_1.MuxUploadHandler('video.upload.cancelled', true)); this.registerHandler(new mux_event_handlers_1.MuxUploadHandler('video.upload.timeout', true)); // General logging handler for all events this.registerHandler(new mux_event_handlers_1.MuxLoggingHandler('video.asset.created')); } handleUnknownType(payload) { console.warn('Unknown Mux webhook event:', { type: payload.type, id: payload.id, data: payload.data, }); return Promise.resolve(); } async handle(req, res) { try { // Get raw body and headers const rawBody = req.rawBody || Buffer.from(JSON.stringify(req.body)); const signature = req.headers['mux-signature']; const timestamp = req.headers['mux-timestamp']; // Verify signature if verifier is configured if (this.verifier && signature) { const payload = typeof rawBody === 'string' ? rawBody : rawBody.toString('utf8'); const isValid = this.verifier.verifyWithTimestamp(payload, signature, timestamp); if (!isValid) { console.warn('Mux webhook signature verification failed'); res.status(401).json({ error: 'Invalid signature' }); return; } } // Parse payload const muxPayload = typeof req.body === 'string' ? JSON.parse(req.body) : req.body; // Log incoming webhook console.warn(`Received Mux webhook: ${muxPayload.type}`, { id: muxPayload.id, dataId: muxPayload.data.id, environment: muxPayload.environment.name, }); // Convert to WebhookPayload format const webhookPayload = this.convertToWebhookPayload(muxPayload); // Process the webhook using base class method await this.processWebhook(webhookPayload); // Send success response res.status(200).json({ received: true, event: muxPayload.type, processed_at: new Date().toISOString(), }); } catch (error) { console.error('Error processing Mux webhook:', error); res.status(500).json({ error: 'Internal server error', message: error instanceof Error ? error.message : 'Unknown error', }); } } convertToWebhookPayload(muxPayload) { return { id: muxPayload.id, timestamp: muxPayload.created_at, type: muxPayload.type, data: muxPayload.data, metadata: { environment: muxPayload.environment, request_id: muxPayload.request_id, accessor: muxPayload.accessor, accessor_source: muxPayload.accessor_source, }, }; } /** * Express middleware for handling Mux webhooks */ getMiddleware() { return (req, res) => this.handle(req, res); } /** * Register a custom handler for a specific Mux event type */ registerMuxHandler(eventType, handler) { // Create a wrapper that adapts the custom handler to the WebhookEventHandler interface const wrappedHandler = { type: eventType, handle: async (webhookPayload) => { const metadata = webhookPayload.metadata; // Convert back to MuxWebhookPayload for the custom handler const muxPayload = { type: webhookPayload.type, created_at: webhookPayload.timestamp, id: webhookPayload.id, data: webhookPayload.data, environment: metadata?.environment || { name: 'unknown', id: 'unknown', }, request_id: metadata?.request_id, accessor: metadata?.accessor, accessor_source: metadata?.accessor_source, }; await handler(muxPayload); }, }; this.registerHandler(wrappedHandler); } } exports.MuxWebhookReceiver = MuxWebhookReceiver;