UNPKG

skex

Version:

A modern schema validation and filtration library with great TypeScript support.

126 lines (70 loc) 2.47 kB
/* IMPORT */ import Compound from './compound'; import Nillable from './nillable'; import Nullable from './nullable'; import Optional from './optional'; import Primitive from './primitive'; import Registry from '../registry'; import {anyOf, noneOf} from '../tests'; import {exit} from '../utils'; import type {OrState, Schema, Tests, Traverser} from '../types'; /* MAIN */ //TODO: Support filtering compound operators, shomehow class Or<T> extends Compound<unknown, T, OrState<T, T, unknown>> { /* VARIABLES */ protected filterable?: boolean; /* PUBLIC API */ filter ( value: unknown, defaultable: false, quiet: true ): boolean; filter ( value: unknown, defaultable?: boolean, quiet?: false ): T; filter ( value: unknown, defaultable?: boolean, quiet?: boolean ): T | boolean; filter ( value: unknown, defaultable: boolean = true, quiet: boolean = false ): T | boolean { this.filterable ??= this.state.options.every ( option => option instanceof Primitive ); if ( !this.filterable ) return exit ( 'The "or" operator only supports filtering primitives' ); for ( let i = 0, l = this.state.options.length; i < l; i++ ) { const filtered = this.state.options[i].filter ( value, false, true ); if ( filtered ) { break; } else { if ( i === l - 1 ) { return this._filterDefault ( defaultable, quiet ); } } } return quiet ? true : value; } test ( value: unknown ): value is T { return super._test ( value, TESTS ); } traverse ( traverser: Traverser, parent?: Schema, key?: string | number ): void { traverser ( this, parent, key ); this.state.options.forEach ( option => { option.traverse ( traverser, this ); }); } /* GENERIC TESTS API */ anyOf ( values: T[] ): Or<T> { return this.with ({ anyOf: values }); } noneOf ( values: T[] ): Or<T> { return this.with ({ noneOf: values }); } nillable (): Nillable<T> { return new Nillable ({ nillable: this }); } nullable (): Nullable<T> { return new Nullable ({ nullable: this }); } optional (): Optional<T> { return new Optional ({ optional: this }); } } /* UTILITIES */ const TESTS: Tests<unknown, OrState<unknown, unknown, unknown>> = { anyOf, noneOf, options: ( value, schemas ) => schemas.some ( option => option.test ( value ) ) }; /* INIT */ Registry.register ( 'or', Or ); /* EXPORT */ export default Or;