Initial Commit
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user