75 lines
2.4 KiB
TypeScript
75 lines
2.4 KiB
TypeScript
import { addIssue, BaseSchema, INVALID } from "../../core/schema/schema.js";
|
|
import type { AnySchema, ParseContext } from "../../types/common.js";
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Type helpers
|
|
// ---------------------------------------------------------------------------
|
|
|
|
type TupleOutputs<T extends AnySchema[]> = {
|
|
[K in keyof T]: T[K] extends BaseSchema<unknown, infer O> ? O : never;
|
|
};
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// TupleSchema
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export class TupleSchema<T extends AnySchema[]> extends BaseSchema<
|
|
TupleOutputs<T>,
|
|
TupleOutputs<T>
|
|
> {
|
|
private readonly _schemas: T;
|
|
|
|
constructor(schemas: T) {
|
|
super();
|
|
this._schemas = schemas;
|
|
}
|
|
|
|
_parse(input: unknown, ctx: ParseContext): TupleOutputs<T> | INVALID {
|
|
if (!Array.isArray(input)) {
|
|
return addIssue(ctx, {
|
|
code: "VALIDATION.INVALID_TYPE",
|
|
path: [...ctx.path],
|
|
message: `Expected tuple (array), received ${typeof input}`,
|
|
input,
|
|
});
|
|
}
|
|
|
|
if (input.length !== this._schemas.length) {
|
|
return addIssue(ctx, {
|
|
code: "VALIDATION.INVALID_TYPE",
|
|
path: [...ctx.path],
|
|
message: `Expected tuple of length ${this._schemas.length}, received length ${input.length}`,
|
|
input,
|
|
});
|
|
}
|
|
|
|
const out: unknown[] = [];
|
|
let hasInvalid = false;
|
|
|
|
for (let i = 0; i < this._schemas.length; i++) {
|
|
const schema = this._schemas[i]!;
|
|
const childCtx: ParseContext = {
|
|
path: [...ctx.path, i],
|
|
issues: [],
|
|
};
|
|
const result = schema._parse(input[i], childCtx);
|
|
if (result === INVALID || childCtx.issues.length > 0) {
|
|
ctx.issues.push(...childCtx.issues);
|
|
hasInvalid = true;
|
|
} else {
|
|
out.push(result);
|
|
}
|
|
}
|
|
|
|
return hasInvalid ? INVALID : (out as TupleOutputs<T>);
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Factory
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export function tuple<T extends AnySchema[]>(schemas: T): TupleSchema<T> {
|
|
return new TupleSchema(schemas);
|
|
}
|