mirror of
https://github.com/saltbo/agent-kanban.git
synced 2026-09-19 09:01:47 +08:00
66 lines
3.5 KiB
TypeScript
66 lines
3.5 KiB
TypeScript
import type { Env } from "@server/env";
|
|
import { V2_API_VERSION as SHARED_V2_API_VERSION } from "@shared";
|
|
import type { Context, Next } from "hono";
|
|
import type { ContentfulStatusCode } from "hono/utils/http-status";
|
|
|
|
export const V2_API_VERSION = SHARED_V2_API_VERSION;
|
|
|
|
export function isPublishedV2Operation(method: string, path: string): boolean {
|
|
if (/^\/api\/tasks\/[^/]+\/events$/.test(path)) return method === "GET";
|
|
if (/^\/api\/tasks\/[^/]+\/claims$/.test(path)) return method === "POST";
|
|
if (path === "/api/boards") return method === "GET" || method === "POST";
|
|
if (/^\/api\/boards\/[^/]+$/.test(path)) return method === "GET" || method === "PATCH" || method === "DELETE";
|
|
if (/^\/api\/boards\/[^/]+\/labels$/.test(path)) return method === "POST";
|
|
if (/^\/api\/boards\/[^/]+\/labels\/[^/]+$/.test(path)) return method === "PATCH" || method === "DELETE";
|
|
if (/^\/api\/boards\/[^/]+\/stream$/.test(path)) return method === "GET";
|
|
if (path === "/api/repositories") return method === "GET" || method === "POST";
|
|
if (/^\/api\/repositories\/[^/]+$/.test(path)) return method === "GET" || method === "DELETE";
|
|
if (path === "/api/github-app/config" || path === "/api/github-app/repositories") return method === "GET";
|
|
if (/^\/api\/repository-installations\/[^/]+$/.test(path)) return method === "PUT";
|
|
if (/^\/api\/agents\/[^/]+\/permissions$/.test(path)) return method === "POST";
|
|
if (path === "/api/agents") return method === "GET" || method === "POST";
|
|
if (/^\/api\/agents\/[^/]+$/.test(path)) return method === "GET";
|
|
if (path === "/api/machines") return method === "GET" || method === "POST";
|
|
if (/^\/api\/machines\/[^/]+$/.test(path)) return method === "GET" || method === "DELETE";
|
|
if (path === "/api/tasks") return method === "GET" || method === "POST";
|
|
if (/^\/api\/tasks\/[^/]+$/.test(path)) return method === "GET" || method === "PATCH" || method === "DELETE";
|
|
if (/^\/api\/tasks\/[^/]+\/session(?:\/ws)?$/.test(path)) return method === "GET";
|
|
if (/^\/api\/tasks\/[^/]+\/stream$/.test(path)) return method === "GET";
|
|
if (/^\/api\/tasks\/[^/]+\/notes$/.test(path)) return method === "GET" || method === "POST";
|
|
if (/^\/api\/tasks\/[^/]+\/notes\/[^/]+$/.test(path)) return method === "GET";
|
|
return false;
|
|
}
|
|
|
|
export async function v2ApiVersionMiddleware(c: Context<{ Bindings: Env }>, next: Next): Promise<Response | undefined> {
|
|
const requestedVersion = c.req.header("API-Version");
|
|
if (requestedVersion !== undefined && requestedVersion !== V2_API_VERSION) {
|
|
return v2Problem(c, 400, "invalid-api-version", "Invalid API version", `Unsupported API-Version: ${requestedVersion}`);
|
|
}
|
|
c.header("API-Version", V2_API_VERSION);
|
|
c.header("Vary", "API-Version");
|
|
await next();
|
|
if (c.res.headers.has("ETag")) {
|
|
// If-Match requires the strong validator issued here, unchanged by edge compression.
|
|
c.header("Cache-Control", "private, no-cache, no-transform");
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
export function effectiveApiVersion(c: Context): string {
|
|
return c.req.header("API-Version") ?? V2_API_VERSION;
|
|
}
|
|
|
|
export function v2Problem(c: Context<{ Bindings: Env }>, status: ContentfulStatusCode, type: string, title: string, detail: string): Response {
|
|
return c.json(
|
|
{
|
|
type: new URL(`/api/problems/${type}`, c.req.url).toString(),
|
|
title,
|
|
status,
|
|
detail,
|
|
instance: `urn:request:${c.get("requestId")}`,
|
|
},
|
|
status,
|
|
{ "Content-Type": "application/problem+json", "API-Version": V2_API_VERSION, Vary: "API-Version" },
|
|
);
|
|
}
|