From 0a20224d5ee94a815f72526e491c77af937e1e98 Mon Sep 17 00:00:00 2001 From: Thibault Le Ouay Date: Thu, 5 Jun 2025 11:23:20 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20typo=20api=20(#1267)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✏️ typo api * 🥰 * 🚀 * ci: apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- .../src/routes/v1/monitors/post_http.test.ts | 8 +-- .../src/routes/v1/monitors/post_http.ts | 4 +- apps/server/src/routes/v1/monitors/schema.ts | 68 ++++++++++++++++++- apps/server/src/routes/v1/monitors/utils.ts | 35 +++++++++- 4 files changed, 107 insertions(+), 8 deletions(-) diff --git a/apps/server/src/routes/v1/monitors/post_http.test.ts b/apps/server/src/routes/v1/monitors/post_http.test.ts index aae470a27..107c8ed52 100644 --- a/apps/server/src/routes/v1/monitors/post_http.test.ts +++ b/apps/server/src/routes/v1/monitors/post_http.test.ts @@ -25,11 +25,11 @@ test("create a valid monitor", async () => { public: true, assertions: [ { - type: "status", + kind: "statusCode", compare: "eq", target: 200, }, - { type: "header", compare: "not_eq", key: "key", target: "value" }, + { kind: "header", compare: "not_eq", key: "key", target: "value" }, ], }), }); @@ -62,11 +62,11 @@ test("create a status report with invalid payload should return 400", async () = public: true, assertions: [ { - type: "status", + kind: "status", compare: "eq", target: 200, }, - { type: "header", compare: "not_eq", key: "key", target: "value" }, + { kind: "header", compare: "not_eq", key: "key", target: "value" }, ], }), }); diff --git a/apps/server/src/routes/v1/monitors/post_http.ts b/apps/server/src/routes/v1/monitors/post_http.ts index 4c597abb9..96e95c02e 100644 --- a/apps/server/src/routes/v1/monitors/post_http.ts +++ b/apps/server/src/routes/v1/monitors/post_http.ts @@ -10,7 +10,7 @@ import { OpenStatusApiError, openApiErrorResponses } from "@/libs/errors"; import { trackMiddleware } from "@/libs/middlewares"; import type { monitorsApi } from "./index"; import { HTTPMonitorSchema, MonitorSchema } from "./schema"; -import { getAssertions } from "./utils"; +import { getAssertionNew, getAssertions } from "./utils"; const postRoute = createRoute({ method: "post", @@ -94,7 +94,7 @@ export function registerPostMonitorHTTP(api: typeof monitorsApi) { const headersEntries = headers ? headers.map(([key, value]) => ({ key: key, value: value })) : undefined; - const assert = assertions ? getAssertions(assertions) : []; + const assert = assertions ? getAssertionNew(assertions) : []; const _newMonitor = await db .insert(monitor) diff --git a/apps/server/src/routes/v1/monitors/schema.ts b/apps/server/src/routes/v1/monitors/schema.ts index a9d980010..b5fa64a94 100644 --- a/apps/server/src/routes/v1/monitors/schema.ts +++ b/apps/server/src/routes/v1/monitors/schema.ts @@ -378,8 +378,74 @@ const tcpRequestSchema = z.object({ }), }); +const statusCodeAssertion = z + .object({ + kind: z.literal("statusCode"), + compare: numberCompare.openapi({ + description: "Comparison operator", + examples: ["eq", "not_eq", "gt", "gte", "lt", "lte"], + }), + target: z.number().openapi({ + description: "Status code to assert", + examples: [200, 404, 418, 500], + }), + }) + .openapi({ + examples: [ + { + kind: "statusCode", + compare: "eq", + target: 200, + }, + { + kind: "statusCode", + compare: "not_eq", + target: 404, + }, + { + kind: "statusCode", + compare: "gt", + target: 300, + }, + ], + }); + +const headerAssertions = z.object({ + kind: z.literal("header"), + compare: stringCompare.openapi({ + description: "Comparison operator", + examples: ["eq", "not_eq", "contains", "not_contains"], + }), + key: z.string().openapi({ + description: "Header key to assert", + examples: ["Content-Type", "X-Request-ID"], + }), + target: z.string().openapi({ + description: "Header value to assert", + examples: ["application/json", "text/html"], + }), +}); + +const textBodyAssertions = z.object({ + kind: z.literal("textBody"), + compare: stringCompare.openapi({ + description: "Comparison operator", + examples: ["eq", "not_eq", "contains", "not_contains"], + }), + target: z.string().openapi({ + description: "Text body to assert", + examples: ["Hello, world!", "404 Not Found"], + }), +}); + +export const assertionsSchema = z.discriminatedUnion("kind", [ + statusCodeAssertion, + headerAssertions, + textBodyAssertions, +]); + export const HTTPMonitorSchema = baseRequest.extend({ - assertions: z.array(assertion).optional().openapi({ + assertions: z.array(assertionsSchema).optional().openapi({ description: "Assertions to run on the response", }), request: httpRequestSchema.openapi({ diff --git a/apps/server/src/routes/v1/monitors/utils.ts b/apps/server/src/routes/v1/monitors/utils.ts index 847e95237..abb4b223a 100644 --- a/apps/server/src/routes/v1/monitors/utils.ts +++ b/apps/server/src/routes/v1/monitors/utils.ts @@ -5,7 +5,7 @@ import { TextBodyAssertion, } from "@openstatus/assertions"; import type { z } from "zod"; -import type { assertion } from "./schema"; +import type { assertion, assertionsSchema } from "./schema"; export const getAssertions = ( assertions: z.infer[], @@ -25,3 +25,36 @@ export const getAssertions = ( } return assert; }; + +export const getAssertionNew = ( + assertions: z.infer[], +): Assertion[] => { + const assert: Assertion[] = []; + + for (const a of assertions) { + if (a.kind === "header") { + const { kind, ...rest } = a; + assert.push( + new HeaderAssertion({ + ...rest, + type: "header", + version: "v1", + }), + ); + } + if (a.kind === "textBody") { + const { kind, ...rest } = a; + + assert.push( + new TextBodyAssertion({ ...rest, type: "textBody", version: "v1" }), + ); + } + if (a.kind === "statusCode") { + const { kind, ...rest } = a; + assert.push( + new StatusAssertion({ ...rest, type: "status", version: "v1" }), + ); + } + } + return assert; +}; -- 2.54.0