import * as plugins from '../../plugins.ts'; import { logger } from '../../logging.ts'; import type { OpsServer } from '../classes.opsserver.ts'; import * as interfaces from '../../../ts_interfaces/index.ts'; export class WebhookHandler { constructor(private opsServerRef: OpsServer) {} public registerRoutes(typedserver: plugins.typedserver.TypedServer): void { typedserver.addRoute('/webhook/:connectionId', 'POST', async (ctx) => { const connectionId = ctx.params.connectionId; // Validate connection exists const connection = this.opsServerRef.gitopsAppRef.connectionManager.getConnection(connectionId); if (!connection) { return new Response(JSON.stringify({ error: 'Connection not found' }), { status: 404, headers: { 'Content-Type': 'application/json' }, }); } // Parse event type from provider-specific headers const giteaEvent = ctx.headers.get('X-Gitea-Event'); const gitlabEvent = ctx.headers.get('X-Gitlab-Event'); const event = giteaEvent || gitlabEvent || 'unknown'; const provider = giteaEvent ? 'gitea' : gitlabEvent ? 'gitlab' : 'unknown'; logger.info(`Webhook received: ${provider}/${event} for connection ${connection.name} (${connectionId})`); // Broadcast to all connected frontends via TypedSocket try { const typedsocket = this.opsServerRef.server.typedserver.typedsocket; if (typedsocket) { const connections = await typedsocket.findAllTargetConnectionsByTag('allClients'); for (const conn of connections) { const req = typedsocket.createTypedRequest( 'webhookNotification', conn, ); req.fire({ connectionId, provider, event, timestamp: Date.now(), }).catch((err: any) => { logger.warn(`Failed to notify client: ${err.message || err}`); }); } } } catch (err: any) { logger.warn(`Failed to broadcast webhook event: ${err.message || err}`); } return new Response(JSON.stringify({ ok: true }), { status: 200, headers: { 'Content-Type': 'application/json' }, }); }); logger.info('WebhookHandler routes registered'); } }