@idealite/web-services
Version:
Comprehensive web services library with webhook system and Mux integration
142 lines (141 loc) • 6.32 kB
JavaScript
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;
;