import type { Static, TSchema } from "typebox"; import { Value } from "typebox/value"; export type ValidationResult = { ok: true; value: T } | { ok: false; errors: string[] }; export function validateSchema(schema: Schema, input: unknown): ValidationResult> { if (Value.Check(schema, input)) { return { ok: true, value: input as Static }; } const errors = [...Value.Errors(schema, input)].map((error) => { const path = "path" in error && typeof error.path === "string" && error.path ? error.path : "/"; return `${path}: ${error.message}`; }); return { ok: false, errors }; } export function assertValid(result: ValidationResult, label: string): T { if (!result.ok) { throw new Error(`${label}: ${result.errors.join("; ")}`); } return result.value; } export function uniqueValues(values: readonly string[], label: string): string[] { const seen = new Set(); const duplicates = new Set(); for (const value of values) { if (seen.has(value)) duplicates.add(`${label}:${value}`); seen.add(value); } return [...duplicates]; }