UNPKG

skex

Version:

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

192 lines (97 loc) 3.98 kB
/* IMPORT */ import isEqual from 'are-deeply-equal'; import Registry from './registry'; import type {FunctionMaybe, Schema} from './types'; /* MAIN */ const exit = ( message: string ): never => { throw new Error ( message ); }; const findLastIndex = <T> ( values: T[], iterator: ( value: T, index: number, arr: T[] ) => boolean ): number => { for ( let i = values.length - 1; i >= 0; i-- ) { const value = values[i]; if ( iterator ( value, i, values ) ) return i; } return -1; }; const forOwn = <T> ( object: Record<string, T>, iterator: ( value: T, key: string, object: Record<string, T> ) => void ): void => { for ( const key in object ) { if ( !object.hasOwnProperty ( key ) ) continue; const value = object[key]; iterator ( value, key, object ); } }; const isAny = ( value: unknown ): value is any => { return true; }; const isArray = ( value: unknown ): value is unknown[] => { return Array.isArray ( value ); }; const isBigInt = ( value: unknown ): value is bigint => { return typeof value === 'bigint'; }; const isBoolean = ( value: unknown ): value is boolean => { return typeof value === 'boolean'; }; const isFinite = ( value: unknown ): value is boolean => { return Number.isFinite ( value ); }; const isFunction = ( value: unknown ): value is Function => { return typeof value === 'function'; }; const isInteger = ( value: unknown ): value is number => { return Number.isInteger ( value ); }; const isNaN = ( value: unknown ): boolean => { return value !== value; }; const isNil = ( value: unknown ): value is null | undefined => { return value === null || value === undefined; }; const isNull = ( value: unknown ): value is null => { return value === null; }; const isNumber = ( value: unknown ): value is number => { return typeof value === 'number'; }; const isObject = ( value: unknown ): value is object => { return typeof value === 'object' && value !== null; }; const isOptional = ( value: unknown ): boolean => { //TODO: This should be more sophisticated, there could be or([ undefined () ]) for example... return ( Registry.has ( 'optional' ) && value instanceof Registry.get ( 'optional' ) ) || ( Registry.has ( 'undefined' ) && value instanceof Registry.get ( 'undefined' ) ); }; const isPlainObject = ( value: unknown ): value is Record<string, unknown> => { if ( typeof value !== 'object' || value === null ) return false; const prototype = Object.getPrototypeOf ( value ); if ( prototype === null ) return true; return Object.getPrototypeOf ( prototype ) === null; }; const isSchema = ( value: unknown ): value is Schema<unknown> => { //TODO: Not perfect, but good enough for our needs return isObject ( value ) && isFunction ( value['filter'] ) && isFunction ( value['test'] ) && isFunction ( value['traverse'] ); }; const isSymbol = ( value: unknown ): value is symbol => { return typeof value === 'symbol'; }; const isString = ( value: unknown ): value is string => { return typeof value === 'string'; }; const isUndefined = ( value: unknown ): value is undefined => { return value === undefined; }; const isUnknown = ( value: unknown ): value is unknown => { return true; }; const pick = <T extends object, K extends keyof T> ( object: T, keys: K[] ): Partial<Pick<T, K>> => { const picked: Partial<Pick<T, K>> = {}; for ( let i = 0, l = keys.length; i < l; i++ ) { const key = keys[i]; if ( !( key in object ) ) continue; picked[key] = object[key]; } return picked; }; const resolve = <T> ( value: FunctionMaybe<T> ): T => { return isFunction ( value ) ? value () : value; }; /* EXPORT */ export {exit, findLastIndex, forOwn, isAny, isArray, isBigInt, isBoolean, isFinite, isEqual, isFunction, isInteger, isNaN, isNil, isNull, isNumber, isObject, isOptional, isPlainObject, isSchema, isSymbol, isString, isUndefined, isUnknown, pick, resolve};