import { Hono } from 'hono'; import type { Bindings } from '../types'; import { generateToken, validateAndParseWebhook, executeWebhookGraph } from '../actions/webhook-handlers'; import { resolveWebhookGraph } from '../actions/webhook-graph-resolver'; export const webhooksRouter = new Hono<{ Bindings: Bindings }>(); type WebhookRecord = { graph: Record; description: string; created_at: string; }; // POST /webhooks — 接受 graph、triplets 或直接 nodes/edges webhooksRouter.post('/webhooks', async (c) => { const body = await c.req.json().catch(() => null); if (!body) return c.json({ error: 'invalid json' }, 400); const description = typeof body.description === 'string' ? body.description : ''; const resolved = await resolveWebhookGraph(body as Record, description, c.env); if (resolved.error) { const statusCode = resolved.missingNodes ? 422 : 400; return c.json( { error: resolved.error, ...(resolved.missingNodes && { missing: resolved.missingNodes }) }, statusCode, ); } const token = generateToken(); const record: WebhookRecord = { graph: resolved.resolvedGraph, description, created_at: new Date().toISOString(), }; await c.env.WEBHOOKS.put(token, JSON.stringify(record)); const baseUrl = new URL(c.req.url).origin; return c.json({ token, webhook_url: `${baseUrl}/webhooks/${token}/trigger`, description: record.description, created_at: record.created_at, }, 201); }); // POST /webhooks/:token/trigger — 觸發執行 webhooksRouter.post('/webhooks/:token/trigger', async (c) => { const token = c.req.param('token'); if (!token || token.length < 16) { return c.json({ error: 'invalid token' }, 400); } const raw = await c.env.WEBHOOKS.get(token, 'text'); if (!raw) return c.json({ error: 'webhook not found' }, 404); const record = await validateAndParseWebhook(raw); if (!record) return c.json({ error: 'webhook 定義損毀' }, 500); let triggerContext: Record = {}; try { const body = await c.req.json().catch(() => null); if (body && typeof body === 'object') { triggerContext = body as Record; } } catch { // 無 body 時使用空 context } const result = await executeWebhookGraph(c.env, record.graph, triggerContext, token); return c.json(result, result.success ? 200 : 500); });