Suite of AT Protocol TypeScript libraries built on web standards
1import {
2 type Infer,
3 Schema,
4 type ValidationResult,
5 type Validator,
6 type ValidatorContext,
7} from "../validation.ts";
8
9export type ArraySchemaOptions = {
10 minLength?: number;
11 maxLength?: number;
12};
13
14export class ArraySchema<
15 const S extends Validator,
16> extends Schema<Infer<S>[]> {
17 constructor(
18 readonly items: S,
19 readonly options: ArraySchemaOptions = {},
20 ) {
21 super();
22 }
23
24 validateInContext(
25 input: unknown,
26 ctx: ValidatorContext,
27 ): ValidationResult<Infer<S>[]> {
28 if (!Array.isArray(input)) {
29 return ctx.issueInvalidType(input, "array");
30 }
31
32 const { minLength } = this.options;
33 if (minLength != null && input.length < minLength) {
34 return ctx.issueTooSmall(input, "array", minLength, input.length);
35 }
36
37 const { maxLength } = this.options;
38 if (maxLength != null && input.length > maxLength) {
39 return ctx.issueTooBig(input, "array", maxLength, input.length);
40 }
41
42 let copy: unknown[] | undefined;
43
44 for (let i = 0; i < input.length; i++) {
45 const result = ctx.validateChild(
46 input as Record<number, unknown>,
47 i,
48 this.items,
49 );
50 if (!result.success) return result;
51
52 if (result.value !== input[i]) {
53 copy ??= [...input];
54 copy[i] = result.value;
55 }
56 }
57
58 return ctx.success((copy ?? input) as Infer<S>[]);
59 }
60}