import type { TSchema } from "@sinclair/typebox"; import { Type } from "@sinclair/typebox"; import type { CheckerDefinition } from "../runner/types"; import { durationSchema } from "./fragments"; export function createExternalProbeConfigSchema(checkers: CheckerDefinition[]): Record { return { ...cloneSchema(createProbeConfigSchema(checkers, true)), $id: "https://dial.local/probe-config.schema.json", $schema: "http://json-schema.org/draft-07/schema#", definitions: {}, }; } export function createProbeConfigSchema(checkers: CheckerDefinition[], external = false): TSchema { return Type.Object( { defaults: Type.Optional(createDefaultsSchema(checkers)), runtime: Type.Optional( Type.Object( { maxConcurrentChecks: Type.Optional(Type.Integer({ minimum: 1 })) }, { additionalProperties: false }, ), ), server: Type.Optional( Type.Object( { dataDir: Type.Optional(Type.String()), host: Type.Optional(Type.String()), port: Type.Optional(Type.Integer({ maximum: 65535, minimum: 0 })), }, { additionalProperties: false }, ), ), targets: Type.Array(external ? createExternalTargetSchema(checkers) : createBaseTargetSchema(checkers), { minItems: 1, }), }, { additionalProperties: false }, ); } export function createTargetSchema(checker: CheckerDefinition): TSchema { const properties: Record = { expect: Type.Optional(checker.schemas.expect), group: Type.Optional(Type.String()), interval: Type.Optional(durationSchema), name: Type.String({ minLength: 1 }), timeout: Type.Optional(durationSchema), type: Type.Literal(checker.type), }; properties[checker.configKey] = checker.schemas.config; return Type.Object(properties, { additionalProperties: false }); } function cloneSchema(schema: TSchema): Record { return JSON.parse(JSON.stringify(schema)) as Record; } function createBaseTargetSchema(checkers: CheckerDefinition[]): TSchema { return Type.Object( { group: Type.Optional(Type.String()), interval: Type.Optional(durationSchema), name: Type.String({ minLength: 1 }), timeout: Type.Optional(durationSchema), type: Type.Union(checkers.map((checker) => Type.Literal(checker.type)) as unknown as [TSchema, ...TSchema[]]), }, { additionalProperties: true }, ); } function createDefaultsSchema(checkers: CheckerDefinition[]): TSchema { const properties: Record = { interval: Type.Optional(durationSchema), timeout: Type.Optional(durationSchema), }; for (const checker of checkers) { properties[checker.configKey] = Type.Optional(checker.schemas.defaults); } return Type.Object(properties, { additionalProperties: false }); } function createExternalTargetSchema(checkers: CheckerDefinition[]): TSchema { return Type.Union(checkers.map((checker) => createTargetSchema(checker)) as [TSchema, ...TSchema[]]); }