feat: add webhook_subscription table and CRUD endpoints

- Migration: CREATE TABLE webhook_subscription (id, did, method, url) with index on did
- db.ts: addWebhookSubscription and deleteWebhooksByDid helpers
- server.ts: POST /:did/webhooks (201) and DELETE /:did/webhooks (204)
This commit is contained in:
Julien Calixte
2026-02-25 22:46:45 +01:00
parent 6cc7866080
commit 373b7a6777
3 changed files with 65 additions and 1 deletions

View File

@@ -1,5 +1,10 @@
import { Application, Router } from "@oak/oak";
import { getNotes, getNotesByDid } from "./src/data/db.ts";
import {
addWebhookSubscription,
deleteWebhooksByDid,
getNotes,
getNotesByDid,
} from "./src/data/db.ts";
import { log } from "./src/log.ts";
const router = new Router();
@@ -23,6 +28,26 @@ router.get("/:did/notes", (ctx) => {
ctx.response.body = getNotesByDid(did, cursor, limit);
});
router.post("/:did/webhooks", async (ctx) => {
const { did } = ctx.params;
const body = await ctx.request.body.json();
const { method, url } = body ?? {};
if (!method || !url) {
ctx.response.status = 400;
ctx.response.body = { error: "method and url are required" };
return;
}
const subscription = addWebhookSubscription({ did, method, url });
ctx.response.status = 201;
ctx.response.body = subscription;
});
router.delete("/:did/webhooks", (ctx) => {
const { did } = ctx.params;
deleteWebhooksByDid(did);
ctx.response.status = 204;
});
// router.delete("/:did/:rkey", async (ctx) => {
// const { did, rkey } = ctx.params;
// let verifiedDid: string;

View File

@@ -67,6 +67,31 @@ export const saveCursor = (cursor: number) => {
);
};
type WebhookSubscriptionRow = {
id: number;
did: string;
method: string;
url: string;
};
export const addWebhookSubscription = (
{ did, method, url }: Omit<WebhookSubscriptionRow, "id">,
): WebhookSubscriptionRow => {
db.exec(
"INSERT INTO webhook_subscription (did, method, url) VALUES (?, ?, ?)",
did,
method,
url,
);
return db.prepare(
"SELECT id, did, method, url FROM webhook_subscription WHERE id = last_insert_rowid()",
).get<WebhookSubscriptionRow>()!;
};
export const deleteWebhooksByDid = (did: string): void => {
db.exec("DELETE FROM webhook_subscription WHERE did = ?", did);
};
export const upsertNote = (note: Note) => {
const now = new Date().toISOString();
db.exec(

View File

@@ -18,4 +18,18 @@ db.exec(`
);
`);
db.exec(`
CREATE TABLE IF NOT EXISTS webhook_subscription (
id INTEGER PRIMARY KEY,
did TEXT NOT NULL,
method TEXT NOT NULL,
url TEXT NOT NULL
);
`);
db.exec(`
CREATE INDEX IF NOT EXISTS idx_webhook_subscription_did
ON webhook_subscription(did);
`);
db.close();