922a57fe34
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>
84 lines
2.5 KiB
TypeScript
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 });
|
|
});
|