import { describe, expect, test } from "bun:test" import { OpenApi } from "effect/unstable/httpapi" import { PublicApi } from "../../src/server/routes/instance/httpapi/public" type Method = "get" | "post" | "put" | "delete" | "patch" type OpenApiSchema = { readonly $ref?: string } type OpenApiResponse = { readonly description?: string readonly content?: Record } type OpenApiOperation = { readonly responses?: Record readonly security?: unknown } type OpenApiPathItem = Partial> type OpenApiSpec = { readonly paths: Record } const methods = ["get", "post", "put", "delete", "patch"] as const const allowedV2BuiltInEndpointErrors = [ "GET /api/session 400 effect_HttpApiError_BadRequest", "GET /api/session/{sessionID}/message 400 effect_HttpApiError_BadRequest", ] function v2Operations(spec: OpenApiSpec) { return Object.entries(spec.paths).flatMap(([path, item]) => path.startsWith("/api/") ? methods.flatMap((method) => { const operation = item[method] return operation ? [{ method, path, operation }] : [] }) : [], ) } function responseRef(response: OpenApiResponse | undefined) { return response?.content?.["application/json"]?.schema?.$ref } function componentName(ref: string) { return ref.replace("#/components/schemas/", "") } function isBuiltInEndpointError(name: string) { return name.startsWith("EffectHttpApiError") || name.startsWith("effect_HttpApiError_") } describe("PublicApi OpenAPI v2 errors", () => { test("preserves /api auth responses", () => { const spec = OpenApi.fromApi(PublicApi) as OpenApiSpec for (const route of v2Operations(spec)) { expect(route.operation.responses?.["401"], `${route.method.toUpperCase()} ${route.path}`).toBeDefined() expect(route.operation.security, `${route.method.toUpperCase()} ${route.path}`).toEqual([]) } }) test("does not rewrite /api endpoint errors to legacy error components", () => { const spec = OpenApi.fromApi(PublicApi) as OpenApiSpec const refs = v2Operations(spec) .flatMap((route) => Object.entries(route.operation.responses ?? {}).flatMap(([status, response]) => { const ref = responseRef(response) return ref ? [`${route.method.toUpperCase()} ${route.path} ${status} ${componentName(ref)}`] : [] }), ) .filter((entry) => entry.includes("BadRequestError") || entry.includes("NotFoundError")) expect(refs).toEqual(["GET /api/provider/{providerID} 404 NotFoundError"]) }) test("new /api endpoint errors cannot use built-in components without an explicit allowlist", () => { const spec = OpenApi.fromApi(PublicApi) as OpenApiSpec const builtInEndpointErrors = v2Operations(spec) .flatMap((route) => Object.entries(route.operation.responses ?? {}).flatMap(([status, response]) => { if (status === "401") return [] const ref = responseRef(response) if (!ref) return [] const name = componentName(ref) return isBuiltInEndpointError(name) ? [`${route.method.toUpperCase()} ${route.path} ${status} ${name}`] : [] }), ) .sort() expect(builtInEndpointErrors).toEqual(allowedV2BuiltInEndpointErrors) }) })