Files
Arcrun/cypher-executor/src/routes/webhooks-crud.ts
T
uncle6me-web 922a57fe34 arcrun — AI workflow execution engine (clean history)
Self-hosted 開源:WASM 零件 + recipe + cypher-executor,跑在你自己的 Cloudflare。

此為重建的乾淨歷史起點(移除曾誤 commit 的 GCP SA 金鑰,舊歷史保留在
richblack/arcrun 與本地 backup 分支)。含:
- acr init --self-hosted installer(建 KV/R2 + codeload 拉預編譯 wasm + wrangler deploy + seed recipe)
- recipe push 把關(資料外流提醒 + 打通檢查)
- 19 個正當零件預編譯 wasm(claude_api/km_writer/kbdb_upsert_block 排除:違反 DECISIONS §1)
- CLI / cypher-executor / registry / 完整 SDD

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 15:52:38 +08:00

84 lines
2.5 KiB
TypeScript

import { Hono } from 'hono';
import type { Bindings } from '../types';
import { validateAndParseWebhook } from '../actions/webhook-handlers';
export const webhooksCrudRouter = new Hono<{ Bindings: Bindings }>();
type WebhookRecord = {
graph: Record<string, unknown>;
description: string;
created_at: string;
};
// GET /webhooks/:token — 查詢 Webhook 基本資訊
webhooksCrudRouter.get('/webhooks/:token', async (c) => {
const token = c.req.param('token');
const raw = await c.env.WEBHOOKS.get(token, 'text');
if (!raw) return c.json({ error: 'not found' }, 404);
const record = await validateAndParseWebhook(raw);
if (!record) return c.json({ error: '資料損毀' }, 500);
return c.json({
token,
description: record.description,
created_at: record.created_at,
});
});
// PUT /webhooks/:token — 更新 Webhook 定義
webhooksCrudRouter.put('/webhooks/:token', 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 existing = await validateAndParseWebhook(raw);
if (!existing) return c.json({ error: 'webhook 定義損毀' }, 500);
const body = await c.req.json().catch(() => null);
if (!body) return c.json({ error: 'invalid json' }, 400);
const updatedRecord: WebhookRecord = {
graph: existing.graph,
description: existing.description,
created_at: existing.created_at,
};
if (body.description !== undefined) {
updatedRecord.description = typeof body.description === 'string' ? body.description : existing.description;
}
if (body.graph !== undefined) {
updatedRecord.graph = body.graph;
}
await c.env.WEBHOOKS.put(token, JSON.stringify(updatedRecord));
const baseUrl = new URL(c.req.url).origin;
return c.json({
token,
webhook_url: `${baseUrl}/webhooks/${token}/trigger`,
description: updatedRecord.description,
created_at: updatedRecord.created_at,
updated: true,
});
});
// DELETE /webhooks/:token — 刪除 Webhook
webhooksCrudRouter.delete('/webhooks/:token', async (c) => {
const token = c.req.param('token');
if (!token || token.length < 16) {
return c.json({ error: 'invalid token' }, 400);
}
const existing = await c.env.WEBHOOKS.get(token, 'text');
if (!existing) return c.json({ error: 'webhook not found' }, 404);
await c.env.WEBHOOKS.delete(token);
return c.json({ deleted: true, token });
});