schema/items/array.ts

77 lines
1.9 KiB
TypeScript

import { parceable } from "../Schema"
import SchemaItem from "../SchemaItem"
import { SchemaInfer, ValidationError, ValidationResult } from "../types"
export default class SchemaArray<Type extends SchemaItem> extends SchemaItem<Array<SchemaInfer<Type>>> {
public constructor(public readonly values: Type) { super(arguments) }
public unwrap() {
return this.values
}
/**
* transform the array so it only contains one of each elements
*/
@parceable()
public unique(): this {
this.postProcess.push((input) => input.filter((it, idx) => input.indexOf(it) === idx))
return this
}
public parse(input: unknown, options?: { fast?: boolean }): ValidationResult<Array<SchemaInfer<Type>>> {
// check errors from itself
let { valid, object, errors = [] } = super.parse(input, options)
// skip checking childs if self is not valid (maybe still try to check childs whan fast is false ?)
if (!valid) {
return {
valid,
object,
errors
} as ValidationResult<SchemaInfer<Type>>
}
const clone: Array<SchemaInfer<Type>> = []
const errs: Array<ValidationError> = []
for (let idx = 0; idx < (object as Array<Type>).length; idx++) {
const item = (object as Array<Type>)[idx]
const res = this.values.parse(item)
if (res.errors && res.errors.length > 0) {
const errors = res.errors.map((it) => ({
...it,
field: it.field ? `${idx}.${it.field}` : idx.toString()
}))
if (options?.fast) {
return {
valid: false,
object: clone as any,
errors: errors
}
}
errs.push(...errors)
} else {
clone.push(res.object)
}
}
if (errs.length > 0) {
return {
valid: false,
object: clone as any,
errors: errs
}
}
return {
valid: true,
object: clone as any
}
}
public override isOfType(input: unknown): input is Array<SchemaInfer<Type>> {
return Array.isArray(input)
}
}