UNPKG

jet-schema

Version:

Simple, typescript-first schema validation tool

105 lines (104 loc) 5.05 kB
import { TEnum } from './util'; import { TFormatError, TOnError } from './error-stuff'; type TStaticObj<Prop> = string extends keyof Prop ? never : { [key: string]: string | number | boolean | TStaticObj<Prop>; }; type TConvertInterfaceToType<Prop> = { [K in keyof Prop]: Prop[K]; }; type IsStaticObj<P, Prop = NonNullable<P>> = (TConvertInterfaceToType<Prop> extends TStaticObj<Prop> ? true : false); type NotUndef<T> = Exclude<T, undefined>; type AddNullablesHelper<T, isN> = isN extends true ? NonNullable<T> | null : NonNullable<T>; type AddNullables<T, isU, isN> = (isU extends true ? AddNullablesHelper<NotUndef<T>, isN> | undefined : AddNullablesHelper<NotUndef<T>, isN>); type GetTypePredicate<T> = T extends (x: unknown) => x is infer U ? U : never; export interface IValidatorObj<T = unknown> { vf: TValidatorFn<T>; default?: T; transform?: (arg: unknown) => T; formatError?: TFormatError; } type TValidatorFn<T = unknown> = (arg: unknown) => arg is T; type IValidatorFnOrObj<T> = TValidatorFn<T> | IValidatorObj<T>; type TPickRetVal<T, NnT = NonNullable<T>> = { test: (arg: unknown) => arg is T; default: () => T; } & (IsStaticObj<T> extends true ? { pick: <K extends keyof NnT>(prop: K) => TPickRetVal<NnT[K]>; new: (arg?: Partial<NonNullable<T>>) => NonNullable<T>; schema: () => ISchema<T>; } : unknown); export interface ISchema<T = unknown> { new: (arg?: Partial<NonNullable<T>>) => NonNullable<T>; test: (arg: unknown) => arg is T; pick: <K extends keyof T>(prop: K) => TPickRetVal<T[K]>; parse: (arg: unknown) => NonNullable<T>; _schemaOptions: { optional: boolean; nullable: boolean; init: boolean | null; id?: string; safety?: 'pass' | 'filter' | 'strict'; }; } export type TSchemaFnObjArg<T> = Required<{ [K in keyof T]: (T[K] extends (string | number) ? (IValidatorFnOrObj<T[K]> | TEnum) : T[K] extends Date ? (DateConstructor | IValidatorFnOrObj<T[K]>) : IsStaticObj<T[K]> extends true ? ISchema<T[K]> : IValidatorFnOrObj<T[K]>); }>; interface IJetOptions<M> { globals?: M extends IValidatorObj[] ? M : never; cloneFn?: (value: unknown) => unknown; onError?: TOnError; } type TGlobalsArr<M> = { [K in keyof M]: { vf: TValidatorFn; } & ('vf' extends keyof M[K] ? { default?: GetTypePredicate<M[K]['vf']>; transform?: (arg: unknown) => GetTypePredicate<M[K]['vf']>; formatError?: TFormatError; } : never); }; type TSchemaOptions<T = unknown> = (unknown extends T ? (IOptNul | IOptNotNul | INotOptButNul | INotOptOrNul | INullish) : (undefined extends T ? (null extends T ? (IOptNul | INullish) : IOptNotNul) : (null extends T ? INotOptButNul : INotOptOrNul))); interface ISchemaOptionsBase { id?: string; safety?: 'pass' | 'filter' | 'strict'; } export interface IOptNul extends ISchemaOptionsBase { optional: true; nullable: true; init?: null | boolean; nullish?: undefined; } export interface IOptNotNul extends ISchemaOptionsBase { optional: true; nullable?: false; init?: boolean; } export interface INotOptButNul extends ISchemaOptionsBase { optional?: false; nullable: true; init?: null | true; } export interface INotOptOrNul extends ISchemaOptionsBase { optional?: false; nullable?: false; init?: true; } export interface INullish extends ISchemaOptionsBase { nullish: true; optional?: undefined; nullable?: undefined; init?: null | boolean; } type TSchemaOptionsHelper<T, R> = (unknown extends T ? ([] | [R]) : undefined extends T ? [R] : null extends T ? [R] : ([] | [R])); export type PublicInferType<S> = (S extends ISchema<infer X> ? X : never); type InferTypes<U, R, Schema = MakeKeysOptIfUndef<InferTypesHelper<U>>> = ('nullish' extends keyof R ? AddNullables<Schema, true, true> : AddNullables<Schema, 'optional' extends keyof R ? R['optional'] : false, 'nullable' extends keyof R ? R['nullable'] : false>); type MakeKeysOptIfUndef<T> = { [K in keyof T]-?: (x: undefined extends T[K] ? Partial<Record<K, T[K]>> : Record<K, T[K]>) => void; }[keyof T] extends (x: infer I) => void ? I extends infer U ? { [K in keyof U]: U[K]; } : never : never; type InferTypesHelper<U> = { [K in keyof U]: (U[K] extends DateConstructor ? Date : U[K] extends IValidatorFnOrObj<infer X> ? X : U[K] extends ISchema<infer X> ? X : U[K] extends unknown[] ? never : U[K] extends TEnum ? U[K][keyof U[K]] : never); }; declare function jetSchema<M extends TGlobalsArr<M>>(options?: IJetOptions<M>): <T, U extends TSchemaFnObjArg<T> = Required<{ [K in keyof T]: T[K] extends string | number ? TEnum | IValidatorFnOrObj<T[K]> : T[K] extends Date ? DateConstructor | IValidatorFnOrObj<T[K]> : IsStaticObj<T[K], NonNullable<T[K]>> extends true ? ISchema<T[K]> : IValidatorFnOrObj<T[K]>; }>, R extends TSchemaOptions<T> = TSchemaOptions<T>>(schemaFnObjArg: U, ...options: TSchemaOptionsHelper<T, R>) => unknown extends T ? ISchema<InferTypes<U, R>> : ISchema<T>; export default jetSchema;