import { BaseSchema, MaybeValid, Schema, SchemaType, ValidationError } from "../../Schema"; import { getErrorMessageForIncorrectType } from "../../utils/getErrorMessageForIncorrectType"; import { MaybePromise } from "../../utils/MaybePromise"; import { maybeSkipValidation } from "../../utils/maybeSkipValidation"; import { getSchemaUtils } from "../schema-utils"; export function list(schema: Schema): Schema { const baseSchema: BaseSchema = { parse: async (raw, opts) => validateAndTransformArray(raw, (item, index) => schema.parse(item, { ...opts, breadcrumbsPrefix: [...(opts?.breadcrumbsPrefix ?? []), `[${index}]`], }) ), json: (parsed, opts) => validateAndTransformArray(parsed, (item, index) => schema.json(item, { ...opts, breadcrumbsPrefix: [...(opts?.breadcrumbsPrefix ?? []), `[${index}]`], }) ), getType: () => SchemaType.LIST, }; return { ...maybeSkipValidation(baseSchema), ...getSchemaUtils(baseSchema), }; } async function validateAndTransformArray( value: unknown, transformItem: (item: Raw, index: number) => MaybePromise> ): Promise> { if (!Array.isArray(value)) { return { ok: false, errors: [ { message: getErrorMessageForIncorrectType(value, "list"), path: [], }, ], }; } const maybeValidItems = await Promise.all(value.map((item, index) => transformItem(item, index))); return maybeValidItems.reduce>( (acc, item) => { if (acc.ok && item.ok) { return { ok: true, value: [...acc.value, item.value], }; } const errors: ValidationError[] = []; if (!acc.ok) { errors.push(...acc.errors); } if (!item.ok) { errors.push(...item.errors); } return { ok: false, errors, }; }, { ok: true, value: [] } ); }