Comparing version 1.0.0-alpha.3 to 1.0.0-alpha.4
import type { AnyObject, InternalOptions, Callback, Message, Maybe } from './types'; | ||
import type Reference from './Reference'; | ||
import { Defined, Flags, NotNull, SetFlag, Thunk, ToggleDefault, ISchema, UnsetFlag } from './util/types'; | ||
import BaseSchema, { SchemaInnerTypeDescription, SchemaSpec } from './schema'; | ||
import { Defined, Flags, NotNull, SetFlag, Thunk, ToggleDefault, ISchema, UnsetFlag, Concat } from './util/types'; | ||
import Schema, { SchemaInnerTypeDescription, SchemaSpec } from './schema'; | ||
import { ResolveOptions } from './Condition'; | ||
export declare type RejectorFn = (value: any, index: number, array: any[]) => boolean; | ||
export declare type RejectorFn = (value: any, index: number, array: readonly any[]) => boolean; | ||
export declare function create<C extends AnyObject = AnyObject, T = any>(type?: ISchema<T, C>): ArraySchema<T, C, undefined, "", T[] | undefined>; | ||
@@ -11,6 +11,5 @@ export declare namespace create { | ||
} | ||
export default class ArraySchema<T, TContext, TDefault = undefined, TFlags extends Flags = '', TIn extends any[] | null | undefined = T[] | undefined> extends BaseSchema<TIn, TContext, TDefault, TFlags> { | ||
export default class ArraySchema<T, TContext, TDefault = undefined, TFlags extends Flags = '', TIn extends any[] | null | undefined = T[] | undefined> extends Schema<TIn, TContext, TDefault, TFlags> { | ||
innerType?: ISchema<T, TContext>; | ||
constructor(type?: ISchema<T, TContext>); | ||
protected _typeCheck(v: any): v is NonNullable<TIn>; | ||
private get _subType(); | ||
@@ -20,4 +19,4 @@ protected _cast(_value: any, _opts: InternalOptions<TContext>): any; | ||
clone(spec?: SchemaSpec<any>): this; | ||
concat<TOther extends ArraySchema<any, any, any>>(schema: TOther): TOther; | ||
concat(schema: any): any; | ||
concat<IT, IC, ID, IF extends Flags, IIn extends Maybe<IT[]>>(schema: ArraySchema<IT, IC, ID, IF, IIn>): ArraySchema<Concat<T, IT>, TContext & IC, Extract<IF, 'd'> extends never ? TDefault : ID, TFlags | IF, Concat<TIn, IIn>>; | ||
concat(schema: this): this; | ||
of<U>(schema: ISchema<U, TContext>): ArraySchema<U, TContext, TFlags>; | ||
@@ -37,6 +36,4 @@ length(length: number | Reference<number>, message?: Message<{ | ||
} | ||
export default interface ArraySchema<T, TContext, TDefault = undefined, TFlags extends Flags = '', TIn extends any[] | null | undefined = T[] | undefined> extends BaseSchema<TIn, TContext, TDefault, TFlags> { | ||
export default interface ArraySchema<T, TContext, TDefault = undefined, TFlags extends Flags = '', TIn extends any[] | null | undefined = T[] | undefined> extends Schema<TIn, TContext, TDefault, TFlags> { | ||
default<D extends Maybe<TIn>>(def: Thunk<D>): ArraySchema<T, TContext, D, ToggleDefault<TFlags, D>, TIn>; | ||
concat<IT, IC, ID, IF extends Flags, IIn extends Maybe<IT[]>>(schema: ArraySchema<IT, IC, ID, IF, IIn>): ArraySchema<NonNullable<T> | IT, TContext & IC, Extract<IF, 'd'> extends never ? TDefault : ID, TFlags | IF, IIn>; | ||
concat(schema: this): this; | ||
defined(msg?: Message): ArraySchema<T, TContext, TDefault, TFlags, Defined<TIn>>; | ||
@@ -43,0 +40,0 @@ optional(): ArraySchema<T, TContext, TDefault, TFlags, TIn | undefined>; |
@@ -9,10 +9,15 @@ function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } | ||
import ValidationError from './ValidationError'; | ||
import BaseSchema from './schema'; | ||
import Schema from './schema'; | ||
export function create(type) { | ||
return new ArraySchema(type); | ||
} | ||
export default class ArraySchema extends BaseSchema { | ||
export default class ArraySchema extends Schema { | ||
constructor(type) { | ||
super({ | ||
type: 'array' | ||
type: 'array', | ||
check(v) { | ||
return Array.isArray(v); | ||
} | ||
}); // `undefined` specifically means uninitialized, as opposed to | ||
@@ -24,9 +29,14 @@ // "no subtype" | ||
this.withMutation(() => { | ||
this.transform(function (values) { | ||
if (typeof values === 'string') try { | ||
values = JSON.parse(values); | ||
} catch (err) { | ||
values = null; | ||
this.transform((values, _, ctx) => { | ||
if (!ctx.spec.coarce) return values; | ||
if (typeof values === 'string') { | ||
try { | ||
values = JSON.parse(values); | ||
} catch (err) { | ||
values = null; | ||
} | ||
} | ||
return this.isType(values) ? values : null; | ||
return ctx.isType(values) ? values : null; | ||
}); | ||
@@ -36,6 +46,2 @@ }); | ||
_typeCheck(v) { | ||
return Array.isArray(v); | ||
} | ||
get _subType() { | ||
@@ -42,0 +48,0 @@ return this.innerType; |
@@ -1,4 +0,4 @@ | ||
import BaseSchema from './schema'; | ||
import type { AnyObject, Maybe, Message } from './types'; | ||
import type { Defined, Flags, NotNull, SetFlag, Thunk, ToggleDefault } from './util/types'; | ||
import Schema from './schema'; | ||
import type { AnyObject, Maybe, Message, Optionals } from './types'; | ||
import type { Defined, Flags, NotNull, SetFlag, Thunk, ToggleDefault, UnsetFlag } from './util/types'; | ||
export declare function create(): BooleanSchema; | ||
@@ -9,7 +9,6 @@ export declare function create<T extends boolean, TContext = AnyObject>(): BooleanSchema<T | undefined, TContext>; | ||
} | ||
export default class BooleanSchema<TType extends Maybe<boolean> = boolean | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends BaseSchema<TType, TContext, TDefault, TFlags> { | ||
export default class BooleanSchema<TType extends Maybe<boolean> = boolean | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends Schema<TType, TContext, TDefault, TFlags> { | ||
constructor(); | ||
protected _typeCheck(v: any): v is NonNullable<TType>; | ||
isTrue(message?: Message<any> | undefined): BooleanSchema<TType | true, TContext, TFlags>; | ||
isFalse(message?: Message<any> | undefined): BooleanSchema<TType | false, TContext, TFlags>; | ||
isTrue(message?: Message<any> | undefined): BooleanSchema<true | Optionals<TType>, TContext, TFlags>; | ||
isFalse(message?: Message<any> | undefined): BooleanSchema<false | Optionals<TType>, TContext, TFlags>; | ||
default<D extends Maybe<TType>>(def: Thunk<D>): BooleanSchema<TType, TContext, D, ToggleDefault<TFlags, D>>; | ||
@@ -22,3 +21,4 @@ defined(msg?: Message): BooleanSchema<Defined<TType>, TContext, TDefault, TFlags>; | ||
nonNullable(msg?: Message): BooleanSchema<NotNull<TType>, TContext, TDefault, TFlags>; | ||
strip(): BooleanSchema<TType, TContext, TDefault, SetFlag<TFlags, 's'>>; | ||
strip(enabled: false): BooleanSchema<TType, TContext, TDefault, UnsetFlag<TFlags, 's'>>; | ||
strip(enabled?: true): BooleanSchema<TType, TContext, TDefault, SetFlag<TFlags, 's'>>; | ||
} |
@@ -1,2 +0,2 @@ | ||
import BaseSchema from './schema'; | ||
import Schema from './schema'; | ||
import { boolean as locale } from './locale'; | ||
@@ -7,10 +7,16 @@ import isAbsent from './util/isAbsent'; | ||
} | ||
export default class BooleanSchema extends BaseSchema { | ||
export default class BooleanSchema extends Schema { | ||
constructor() { | ||
super({ | ||
type: 'boolean' | ||
type: 'boolean', | ||
check(v) { | ||
if (v instanceof Boolean) v = v.valueOf(); | ||
return typeof v === 'boolean'; | ||
} | ||
}); | ||
this.withMutation(() => { | ||
this.transform(function (value) { | ||
if (!this.isType(value)) { | ||
this.transform((value, _raw, ctx) => { | ||
if (ctx.spec.coarce && !ctx.isType(value)) { | ||
if (/^(true|1)$/i.test(String(value))) return true; | ||
@@ -25,7 +31,2 @@ if (/^(false|0)$/i.test(String(value))) return false; | ||
_typeCheck(v) { | ||
if (v instanceof Boolean) v = v.valueOf(); | ||
return typeof v === 'boolean'; | ||
} | ||
isTrue(message = locale.isValue) { | ||
@@ -92,4 +93,4 @@ return this.test({ | ||
strip() { | ||
return super.strip(); | ||
strip(v) { | ||
return super.strip(v); | ||
} | ||
@@ -96,0 +97,0 @@ |
import Reference from './Reference'; | ||
import type { ISchema } from './util/types'; | ||
export interface ConditionBuilder<T extends ISchema<any, any>> { | ||
(this: T, value: any, schema: T): ISchema<any, any> | void; | ||
(v1: any, v2: any, schema: T): ISchema<any, any> | void; | ||
(v1: any, v2: any, v3: any, schema: T): ISchema<any, any> | void; | ||
(v1: any, v2: any, v3: any, v4: any, schema: T): ISchema<any, any> | void; | ||
} | ||
export declare type ConditionConfig<T extends ISchema<any>> = { | ||
export declare type ConditionBuilder<T extends ISchema<any, any>, U extends ISchema<any, any> = T> = (values: any[], schema: T, options: ResolveOptions) => U; | ||
export declare type ConditionConfig<T extends ISchema<any>, TThen extends ISchema<any, any> = T, TOtherwise extends ISchema<any, any> = T> = { | ||
is: any | ((...values: any[]) => boolean); | ||
then?: (schema: T) => ISchema<any>; | ||
otherwise?: (schema: T) => ISchema<any>; | ||
then?: (schema: T) => TThen; | ||
otherwise?: (schema: T) => TOtherwise; | ||
}; | ||
export declare type ConditionOptions<T extends ISchema<any, any>> = ConditionBuilder<T> | ConditionConfig<T>; | ||
export declare type ResolveOptions<TContext = any> = { | ||
@@ -20,8 +14,9 @@ value?: any; | ||
}; | ||
declare class Condition<T extends ISchema<any, any> = ISchema<any, any>> { | ||
refs: Reference[]; | ||
fn: ConditionBuilder<T>; | ||
constructor(refs: Reference[], options: ConditionOptions<T>); | ||
resolve(base: T, options: ResolveOptions): ISchema<any, import("./types").AnyObject, any, any> | T; | ||
declare class Condition<TIn extends ISchema<any, any> = ISchema<any, any>, TOut extends ISchema<any, any> = TIn> { | ||
refs: readonly Reference[]; | ||
fn: ConditionBuilder<TIn, TOut>; | ||
static fromOptions<TIn extends ISchema<any, any>, TThen extends ISchema<any, any>, TOtherwise extends ISchema<any, any>>(refs: Reference[], config: ConditionConfig<TIn, TThen, TOtherwise>): Condition<TIn, TThen | TOtherwise>; | ||
constructor(refs: readonly Reference[], builder: ConditionBuilder<TIn, TOut>); | ||
resolve(base: TIn, options: ResolveOptions): ISchema<any, any, any, any>; | ||
} | ||
export default Condition; |
import isSchema from './util/isSchema'; | ||
class Condition { | ||
constructor(refs, options) { | ||
this.fn = void 0; | ||
this.refs = refs; | ||
this.refs = refs; | ||
if (typeof options === 'function') { | ||
this.fn = options; | ||
return; | ||
} | ||
if (!('is' in options)) throw new TypeError('`is:` is required for `when()` conditions'); | ||
if (!options.then && !options.otherwise) throw new TypeError('either `then:` or `otherwise:` is required for `when()` conditions'); | ||
static fromOptions(refs, config) { | ||
if (!config.then && !config.otherwise) throw new TypeError('either `then:` or `otherwise:` is required for `when()` conditions'); | ||
let { | ||
@@ -20,21 +10,29 @@ is, | ||
otherwise | ||
} = options; | ||
} = config; | ||
let check = typeof is === 'function' ? is : (...values) => values.every(value => value === is); | ||
this.fn = function (...args) { | ||
return new Condition(refs, (values, schema) => { | ||
var _branch; | ||
let _opts = args.pop(); | ||
let schema = args.pop(); | ||
let branch = check(...args) ? then : otherwise; | ||
let branch = check(...values) ? then : otherwise; | ||
return (_branch = branch == null ? void 0 : branch(schema)) != null ? _branch : schema; | ||
}; | ||
}); | ||
} | ||
constructor(refs, builder) { | ||
this.fn = void 0; | ||
this.refs = refs; | ||
this.refs = refs; | ||
this.fn = builder; | ||
} | ||
resolve(base, options) { | ||
let values = this.refs.map(ref => // TODO: ? operator here? | ||
ref.getValue(options == null ? void 0 : options.value, options == null ? void 0 : options.parent, options == null ? void 0 : options.context)); | ||
let schema = this.fn.apply(base, values.concat(base, options)); | ||
if (schema === undefined || schema === base) return base; | ||
let schema = this.fn(values, base, options); | ||
if (schema === undefined || // @ts-ignore this can be base | ||
schema === base) { | ||
return base; | ||
} | ||
if (!isSchema(schema)) throw new TypeError('conditions must return a schema object'); | ||
@@ -41,0 +39,0 @@ return schema.resolve(options); |
import Ref from './Reference'; | ||
import type { AnyObject, Maybe, Message } from './types'; | ||
import type { Defined, Flags, NotNull, SetFlag, Thunk, ToggleDefault, UnsetFlag } from './util/types'; | ||
import BaseSchema from './schema'; | ||
import Schema from './schema'; | ||
export declare function create(): DateSchema; | ||
@@ -11,6 +11,5 @@ export declare function create<T extends Date, TContext = AnyObject>(): DateSchema<T | undefined, TContext>; | ||
} | ||
export default class DateSchema<TType extends Maybe<Date> = Date | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends BaseSchema<TType, TContext, TDefault, TFlags> { | ||
export default class DateSchema<TType extends Maybe<Date> = Date | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends Schema<TType, TContext, TDefault, TFlags> { | ||
static INVALID_DATE: Date; | ||
constructor(); | ||
protected _typeCheck(v: any): v is NonNullable<TType>; | ||
private prepareParam; | ||
@@ -24,3 +23,3 @@ min(min: unknown | Ref<Date>, message?: Message<{ | ||
} | ||
export default interface DateSchema<TType extends Maybe<Date>, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends BaseSchema<TType, TContext, TDefault, TFlags> { | ||
export default interface DateSchema<TType extends Maybe<Date>, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends Schema<TType, TContext, TDefault, TFlags> { | ||
default<D extends Maybe<TType>>(def: Thunk<D>): DateSchema<TType, TContext, D, ToggleDefault<TFlags, D>>; | ||
@@ -27,0 +26,0 @@ concat<TOther extends DateSchema<any, any>>(schema: TOther): TOther; |
@@ -6,3 +6,3 @@ // @ts-ignore | ||
import Ref from './Reference'; | ||
import BaseSchema from './schema'; | ||
import Schema from './schema'; | ||
let invalidDate = new Date(''); | ||
@@ -15,13 +15,18 @@ | ||
} | ||
export default class DateSchema extends BaseSchema { | ||
export default class DateSchema extends Schema { | ||
constructor() { | ||
super({ | ||
type: 'date' | ||
type: 'date', | ||
check(v) { | ||
return isDate(v) && !isNaN(v.getTime()); | ||
} | ||
}); | ||
this.withMutation(() => { | ||
this.transform(function (value) { | ||
if (this.isType(value)) return value; | ||
this.transform((value, _raw, ctx) => { | ||
if (!ctx.spec.coarce || ctx.isType(value)) return value; | ||
value = isoParse(value); // 0 is a valid timestamp equivalent to 1970-01-01T00:00:00Z(unix epoch) or before. | ||
return !isNaN(value) ? new Date(value) : invalidDate; | ||
return !isNaN(value) ? new Date(value) : DateSchema.INVALID_DATE; | ||
}); | ||
@@ -31,6 +36,2 @@ }); | ||
_typeCheck(v) { | ||
return isDate(v) && !isNaN(v.getTime()); | ||
} | ||
prepareParam(ref, name) { | ||
@@ -37,0 +38,0 @@ let param; |
@@ -1,2 +0,2 @@ | ||
import Mixed, { create as mixedCreate, MixedSchema } from './mixed'; | ||
import MixedSchema, { create as mixedCreate, MixedOptions, TypeGuard } from './mixed'; | ||
import BooleanSchema, { create as boolCreate } from './boolean'; | ||
@@ -14,3 +14,3 @@ import StringSchema, { create as stringCreate } from './string'; | ||
import setLocale from './setLocale'; | ||
import BaseSchema, { AnySchema } from './schema'; | ||
import Schema, { AnySchema } from './schema'; | ||
import type { InferType } from './util/types'; | ||
@@ -20,5 +20,5 @@ declare function addMethod<T extends AnySchema>(schemaType: (...arg: any[]) => T, name: string, fn: (this: T, ...args: any[]) => T): void; | ||
export declare type AnyObjectSchema = ObjectSchema<any, any, any, any>; | ||
export type { AnyObject, InferType, InferType as Asserts, AnySchema }; | ||
export type { AnyObject, InferType, InferType as Asserts, AnySchema, MixedOptions, TypeGuard, }; | ||
export { mixedCreate as mixed, boolCreate as bool, boolCreate as boolean, stringCreate as string, numberCreate as number, dateCreate as date, objectCreate as object, arrayCreate as array, refCreate as ref, lazyCreate as lazy, reach, isSchema, addMethod, setLocale, ValidationError, }; | ||
export { BaseSchema, Mixed as MixedSchema, MixedSchema as MixedSchemaClass, BooleanSchema, StringSchema, NumberSchema, DateSchema, ObjectSchema, ArraySchema, }; | ||
export { Schema, MixedSchema, BooleanSchema, StringSchema, NumberSchema, DateSchema, ObjectSchema, ArraySchema, }; | ||
export type { CreateErrorOptions, TestContext, TestFunction, TestOptions, TestConfig, } from './util/createValidation'; |
@@ -1,2 +0,2 @@ | ||
import Mixed, { create as mixedCreate, MixedSchema } from './mixed'; | ||
import MixedSchema, { create as mixedCreate } from './mixed'; | ||
import BooleanSchema, { create as boolCreate } from './boolean'; | ||
@@ -14,3 +14,3 @@ import StringSchema, { create as stringCreate } from './string'; | ||
import setLocale from './setLocale'; | ||
import BaseSchema from './schema'; | ||
import Schema from './schema'; | ||
@@ -25,2 +25,2 @@ function addMethod(schemaType, name, fn) { | ||
export { mixedCreate as mixed, boolCreate as bool, boolCreate as boolean, stringCreate as string, numberCreate as number, dateCreate as date, objectCreate as object, arrayCreate as array, refCreate as ref, lazyCreate as lazy, reach, isSchema, addMethod, setLocale, ValidationError }; | ||
export { BaseSchema, Mixed as MixedSchema, MixedSchema as MixedSchemaClass, BooleanSchema, StringSchema, NumberSchema, DateSchema, ObjectSchema, ArraySchema }; | ||
export { Schema, MixedSchema, BooleanSchema, StringSchema, NumberSchema, DateSchema, ObjectSchema, ArraySchema }; |
@@ -5,3 +5,3 @@ import type { AnyObject, Callback, ValidateOptions } from './types'; | ||
import { Flags, ISchema } from './util/types'; | ||
import { BaseSchema } from '.'; | ||
import { Schema } from '.'; | ||
export declare type LazyBuilder<T, TContext = AnyObject, TDefault = any, TFlags extends Flags = any> = (value: any, options: ResolveOptions) => ISchema<T, TContext, TFlags, TDefault>; | ||
@@ -24,3 +24,3 @@ export declare function create<T, TContext = AnyObject, TFlags extends Flags = any, TDefault = any>(builder: LazyBuilder<T, TContext, TDefault, TFlags>): Lazy<T, TContext, TDefault, TFlags>; | ||
private _resolve; | ||
resolve(options: ResolveOptions<TContext>): BaseSchema<T, TContext, TDefault, TFlags>; | ||
resolve(options: ResolveOptions<TContext>): Schema<T, TContext, TDefault, TFlags>; | ||
cast(value: any, options?: CastOptions<TContext>): T; | ||
@@ -27,0 +27,0 @@ validate(value: any, options?: ValidateOptions, maybeCb?: Callback): Promise<T>; |
@@ -5,2 +5,4 @@ import printValue from './util/printValue'; | ||
required: '${path} is a required field', | ||
defined: '${path} must be defined', | ||
notNull: '${path} cannot be null', | ||
oneOf: '${path} must be one of the following values: ${values}', | ||
@@ -14,7 +16,5 @@ notOneOf: '${path} must not be one of the following values: ${values}', | ||
}) => { | ||
let isCast = originalValue != null && originalValue !== value; | ||
return `${path} must be a \`${type}\` type, ` + `but the final value was: \`${printValue(value, true)}\`` + (isCast ? ` (cast from the value \`${printValue(originalValue, true)}\`).` : '.'); | ||
}, | ||
defined: '${path} must be defined', | ||
notNull: '${path} cannot be null' | ||
const castMsg = originalValue != null && originalValue !== value ? ` (cast from the value \`${printValue(originalValue, true)}\`).` : '.'; | ||
return type !== 'mixed' ? `${path} must be a \`${type}\` type, ` + `but the final value was: \`${printValue(value, true)}\`` + castMsg : `${path} must match the configured type. ` + `The validated value was: \`${printValue(value, true)}\`` + castMsg; | ||
} | ||
}; | ||
@@ -21,0 +21,0 @@ export let string = { |
@@ -1,8 +0,20 @@ | ||
import { AnyObject, Maybe, Message, Optionals } from './types'; | ||
import type { Defined, Flags, SetFlag, Thunk, ToggleDefault, UnsetFlag } from './util/types'; | ||
import BaseSchema from './schema'; | ||
export declare class MixedSchema<TType = any, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends BaseSchema<TType, TContext, TDefault, TFlags> { | ||
import { AnyObject, Maybe, Message } from './types'; | ||
import type { Concat, Defined, Flags, SetFlag, Thunk, ToggleDefault, UnsetFlag } from './util/types'; | ||
import Schema from './schema'; | ||
export declare type TypeGuard<TType> = (value: any) => value is NonNullable<TType>; | ||
export interface MixedOptions<TType> { | ||
type?: string; | ||
check?: TypeGuard<TType>; | ||
} | ||
export declare function create<TType = any>(spec?: MixedOptions<TType> | TypeGuard<TType>): MixedSchema<TType | undefined, AnyObject, undefined, "">; | ||
export declare namespace create { | ||
var prototype: MixedSchema<any, any, any, any>; | ||
} | ||
export default class MixedSchema<TType = any, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends Schema<TType, TContext, TDefault, TFlags> { | ||
constructor(spec?: MixedOptions<TType> | TypeGuard<TType>); | ||
} | ||
export default interface MixedSchema<TType = any, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends Schema<TType, TContext, TDefault, TFlags> { | ||
default<D extends Maybe<TType>>(def: Thunk<D>): MixedSchema<TType, TContext, D, ToggleDefault<TFlags, D>>; | ||
concat<IT, IC, ID, IF extends Flags>(schema: MixedSchema<IT, IC, ID, IF>): MixedSchema<NonNullable<TType> | IT, TContext & IC, ID, TFlags | IF>; | ||
concat<IT, IC, ID, IF extends Flags>(schema: BaseSchema<IT, IC, ID, IF>): MixedSchema<NonNullable<TType> | Optionals<IT>, TContext & IC, ID, TFlags | IF>; | ||
concat<IT, IC, ID, IF extends Flags>(schema: MixedSchema<IT, IC, ID, IF>): MixedSchema<Concat<TType, IT>, TContext & IC, ID, TFlags | IF>; | ||
concat<IT, IC, ID, IF extends Flags>(schema: Schema<IT, IC, ID, IF>): MixedSchema<Concat<TType, IT>, TContext & IC, ID, TFlags | IF>; | ||
concat(schema: this): this; | ||
@@ -18,7 +30,1 @@ defined(msg?: Message): MixedSchema<Defined<TType>, TContext, TDefault, TFlags>; | ||
} | ||
declare const Mixed: typeof MixedSchema; | ||
export default Mixed; | ||
export declare function create<TType = any>(): MixedSchema<TType | undefined, AnyObject, undefined, "">; | ||
export declare namespace create { | ||
var prototype: MixedSchema<any, any, any, any>; | ||
} |
@@ -1,8 +0,22 @@ | ||
import BaseSchema from './schema'; | ||
const Mixed = BaseSchema; | ||
export default Mixed; | ||
export function create() { | ||
return new Mixed(); | ||
} // XXX: this is using the Base schema so that `addMethod(mixed)` works as a base class | ||
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } | ||
create.prototype = Mixed.prototype; | ||
import Schema from './schema'; | ||
const returnsTrue = () => true; | ||
export function create(spec) { | ||
return new MixedSchema(spec); | ||
} | ||
export default class MixedSchema extends Schema { | ||
constructor(spec) { | ||
super(typeof spec === 'function' ? { | ||
type: 'mixed', | ||
check: spec | ||
} : _extends({ | ||
type: 'mixed', | ||
check: returnsTrue | ||
}, spec)); | ||
} | ||
} | ||
create.prototype = MixedSchema.prototype; |
import type { AnyObject, Maybe, Message } from './types'; | ||
import type Reference from './Reference'; | ||
import type { Concat, Defined, Flags, NotNull, SetFlag, Thunk, ToggleDefault, UnsetFlag } from './util/types'; | ||
import BaseSchema from './schema'; | ||
import Schema from './schema'; | ||
export declare function create(): NumberSchema; | ||
@@ -10,5 +10,4 @@ export declare function create<T extends number, TContext = AnyObject>(): NumberSchema<T | undefined, TContext>; | ||
} | ||
export default class NumberSchema<TType extends Maybe<number> = number | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends BaseSchema<TType, TContext, TDefault, TFlags> { | ||
export default class NumberSchema<TType extends Maybe<number> = number | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends Schema<TType, TContext, TDefault, TFlags> { | ||
constructor(); | ||
protected _typeCheck(value: any): value is NonNullable<TType>; | ||
min(min: number | Reference<number>, message?: Message<{ | ||
@@ -36,3 +35,3 @@ min: number; | ||
} | ||
export default interface NumberSchema<TType extends Maybe<number> = number | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends BaseSchema<TType, TContext, TDefault, TFlags> { | ||
export default interface NumberSchema<TType extends Maybe<number> = number | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends Schema<TType, TContext, TDefault, TFlags> { | ||
default<D extends Maybe<TType>>(def: Thunk<D>): NumberSchema<TType, TContext, D, ToggleDefault<TFlags, D>>; | ||
@@ -39,0 +38,0 @@ concat<UType extends Maybe<number>, UContext, UFlags extends Flags, UDefault>(schema: NumberSchema<UType, UContext, UDefault, UFlags>): NumberSchema<Concat<TType, UType>, TContext & UContext, UDefault, TFlags | UFlags>; |
import { number as locale } from './locale'; | ||
import isAbsent from './util/isAbsent'; | ||
import BaseSchema from './schema'; | ||
import Schema from './schema'; | ||
@@ -10,9 +10,16 @@ let isNaN = value => value != +value; | ||
} | ||
export default class NumberSchema extends BaseSchema { | ||
export default class NumberSchema extends Schema { | ||
constructor() { | ||
super({ | ||
type: 'number' | ||
type: 'number', | ||
check(value) { | ||
if (value instanceof Number) value = value.valueOf(); | ||
return typeof value === 'number' && !isNaN(value); | ||
} | ||
}); | ||
this.withMutation(() => { | ||
this.transform(function (value) { | ||
this.transform((value, _raw, ctx) => { | ||
if (!ctx.spec.coarce) return value; | ||
let parsed = value; | ||
@@ -27,3 +34,3 @@ | ||
if (this.isType(parsed)) return parsed; | ||
if (ctx.isType(parsed)) return parsed; | ||
return parseFloat(parsed); | ||
@@ -34,7 +41,2 @@ }); | ||
_typeCheck(value) { | ||
if (value instanceof Number) value = value.valueOf(); | ||
return typeof value === 'number' && !isNaN(value); | ||
} | ||
min(min, message = locale.min) { | ||
@@ -41,0 +43,0 @@ return this.test({ |
@@ -5,5 +5,5 @@ import { Flags, ISchema, SetFlag, ToggleDefault, UnsetFlag } from './util/types'; | ||
import type Reference from './Reference'; | ||
import BaseSchema, { SchemaObjectDescription, SchemaSpec } from './schema'; | ||
import Schema, { SchemaObjectDescription, SchemaSpec } from './schema'; | ||
import { ResolveOptions } from './Condition'; | ||
import type { AnyObject, DefaultFromShape, MakePartial, ObjectShape, PartialDeep, TypeFromShape } from './util/objectTypes'; | ||
import type { AnyObject, ConcatObjectTypes, DefaultFromShape, MakePartial, ObjectShape, PartialDeep, TypeFromShape } from './util/objectTypes'; | ||
export type { AnyObject }; | ||
@@ -17,7 +17,7 @@ declare type MakeKeysOptional<T> = T extends AnyObject ? _<MakePartial<T>> : T; | ||
}; | ||
export declare function create<C = AnyObject, S extends ObjectShape = {}>(spec?: S): ObjectSchema<_<TypeFromShape<S, C>>, C, _<DefaultFromShape<S>>, "d">; | ||
export declare function create<C = AnyObject, S extends ObjectShape = {}>(spec?: S): ObjectSchema<_<TypeFromShape<S, C>>, C, _<DefaultFromShape<S>>, "">; | ||
export declare namespace create { | ||
var prototype: ObjectSchema<any, any, any, any>; | ||
} | ||
export default interface ObjectSchema<TIn extends Maybe<AnyObject>, TContext = AnyObject, TDefault = any, TFlags extends Flags = 'd'> extends BaseSchema<MakeKeysOptional<TIn>, TContext, TDefault, TFlags> { | ||
export default interface ObjectSchema<TIn extends Maybe<AnyObject>, TContext = AnyObject, TDefault = any, TFlags extends Flags = ''> extends Schema<MakeKeysOptional<TIn>, TContext, TDefault, TFlags> { | ||
default<D extends Maybe<AnyObject>>(def: Thunk<D>): ObjectSchema<TIn, TContext, D, ToggleDefault<TFlags, 'd'>>; | ||
@@ -33,3 +33,3 @@ defined(msg?: Message): ObjectSchema<Defined<TIn>, TContext, TDefault, TFlags>; | ||
} | ||
export default class ObjectSchema<TIn extends Maybe<AnyObject>, TContext = AnyObject, TDefault = any, TFlags extends Flags = 'd'> extends BaseSchema<MakeKeysOptional<TIn>, TContext, TDefault, TFlags> { | ||
export default class ObjectSchema<TIn extends Maybe<AnyObject>, TContext = AnyObject, TDefault = any, TFlags extends Flags = ''> extends Schema<MakeKeysOptional<TIn>, TContext, TDefault, TFlags> { | ||
fields: Shape<NonNullable<TIn>, TContext>; | ||
@@ -41,15 +41,14 @@ spec: ObjectSchemaSpec; | ||
constructor(spec?: Shape<TIn, TContext>); | ||
protected _typeCheck(value: any): value is NonNullable<MakeKeysOptional<TIn>>; | ||
protected _cast(_value: any, options?: InternalOptions<TContext>): any; | ||
protected _validate(_value: any, opts: InternalOptions<TContext> | undefined, callback: Callback): void; | ||
clone(spec?: ObjectSchemaSpec): this; | ||
concat<IIn, IC, ID, IF extends Flags>(schema: ObjectSchema<IIn, IC, ID, IF>): ObjectSchema<NonNullable<TIn> | IIn, TContext & IC, TDefault & ID, TFlags | IF>; | ||
concat<IIn, IC, ID, IF extends Flags>(schema: ObjectSchema<IIn, IC, ID, IF>): ObjectSchema<ConcatObjectTypes<TIn, IIn>, TContext & IC, Extract<IF, 'd'> extends never ? _<ConcatObjectTypes<TDefault, ID>> : ID, TFlags | IF>; | ||
concat(schema: this): this; | ||
protected _getDefault(): any; | ||
private setFields; | ||
shape<U extends ObjectShape>(additions: U, excludes?: [string, string][]): ObjectSchema<_<{ [P in keyof TIn]: P extends keyof U ? TypeFromShape<U, TContext>[P] : TIn[P]; } & TypeFromShape<U, TContext>> | _<Extract<TIn, null | undefined>>, TContext, Extract<TFlags, "d"> extends never ? _<TDefault & DefaultFromShape<U>> : TDefault, TFlags>; | ||
shape<U extends ObjectShape>(additions: U, excludes?: readonly [string, string][]): ObjectSchema<_<{ [P in keyof TIn]: P extends keyof U ? TypeFromShape<U, TContext>[P] : TIn[P]; } & TypeFromShape<U, TContext>> | _<Extract<TIn, null | undefined>>, TContext, Extract<TFlags, "d"> extends never ? _<TDefault & DefaultFromShape<U>> : TDefault, TFlags>; | ||
partial(): ObjectSchema<Partial<TIn>, TContext, TDefault, TFlags>; | ||
deepPartial(): ObjectSchema<PartialDeep<TIn>, TContext, TDefault, TFlags>; | ||
pick<TKey extends keyof TIn>(keys: TKey[]): ObjectSchema<{ [K in TKey]: TIn[K]; }, TContext, TDefault, TFlags>; | ||
omit<TKey extends keyof TIn>(keys: TKey[]): ObjectSchema<Omit<TIn, TKey>, TContext, TDefault, TFlags>; | ||
pick<TKey extends keyof TIn>(keys: readonly TKey[]): ObjectSchema<{ [K in TKey]: TIn[K]; }, TContext, TDefault, TFlags>; | ||
omit<TKey extends keyof TIn>(keys: readonly TKey[]): ObjectSchema<Omit<TIn, TKey>, TContext, TDefault, TFlags>; | ||
from(from: string, to: keyof TIn, alias?: boolean): this; | ||
@@ -56,0 +55,0 @@ noUnknown(message?: Message): this; |
@@ -11,3 +11,3 @@ function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } | ||
import ValidationError from './ValidationError'; | ||
import BaseSchema from './schema'; | ||
import Schema from './schema'; | ||
@@ -33,7 +33,11 @@ const deepHas = (obj, p) => { | ||
} | ||
export default class ObjectSchema extends BaseSchema { | ||
//readonly (keyof TIn & string)[] | ||
export default class ObjectSchema extends Schema { | ||
constructor(spec) { | ||
super({ | ||
type: 'object' | ||
type: 'object', | ||
check(value) { | ||
return isObject(value) || typeof value === 'function'; | ||
} | ||
}); | ||
@@ -45,3 +49,3 @@ this.fields = Object.create(null); | ||
this.withMutation(() => { | ||
this.transform(function coerce(value) { | ||
this.transform((value, _raw, ctx) => { | ||
if (typeof value === 'string') { | ||
@@ -55,3 +59,3 @@ try { | ||
if (this.isType(value)) return value; | ||
if (ctx.isType(value)) return value; | ||
return null; | ||
@@ -66,6 +70,2 @@ }); | ||
_typeCheck(value) { | ||
return isObject(value) || typeof value === 'function'; | ||
} | ||
_cast(_value, options = {}) { | ||
@@ -106,3 +106,3 @@ var _options$stripUnknown; | ||
}); | ||
let fieldSpec = field instanceof BaseSchema ? field.spec : undefined; | ||
let fieldSpec = field instanceof Schema ? field.spec : undefined; | ||
let strict = fieldSpec == null ? void 0 : fieldSpec.strict; | ||
@@ -217,8 +217,3 @@ | ||
const target = nextFields[field]; | ||
if (target === undefined) { | ||
nextFields[field] = schemaOrRef; | ||
} else if (target instanceof BaseSchema && schemaOrRef instanceof BaseSchema) { | ||
nextFields[field] = schemaOrRef.concat(target); | ||
} | ||
nextFields[field] = target === undefined ? schemaOrRef : target; | ||
} | ||
@@ -277,3 +272,3 @@ | ||
for (const [key, schema] of Object.entries(this.fields)) { | ||
partial[key] = schema instanceof BaseSchema ? schema.optional() : schema; | ||
partial[key] = schema instanceof Schema ? schema.optional() : schema; | ||
} | ||
@@ -288,3 +283,3 @@ | ||
for (const [key, schema] of Object.entries(this.fields)) { | ||
if (schema instanceof ObjectSchema) partial[key] = schema.deepPartial();else partial[key] = schema instanceof BaseSchema ? schema.optional() : schema; | ||
if (schema instanceof ObjectSchema) partial[key] = schema.deepPartial();else partial[key] = schema instanceof Schema ? schema.optional() : schema; | ||
} | ||
@@ -291,0 +286,0 @@ |
@@ -1,2 +0,2 @@ | ||
import { ConditionOptions, ResolveOptions } from './Condition'; | ||
import { ConditionBuilder, ConditionConfig, ResolveOptions } from './Condition'; | ||
import { TestFunction, Test, TestConfig } from './util/createValidation'; | ||
@@ -6,4 +6,5 @@ import { ValidateOptions, TransformFunction, Message, Callback, InternalOptions, Maybe, ExtraParams, AnyObject } from './types'; | ||
import Reference from './Reference'; | ||
import type { Defined, Flags, ISchema, ResolveFlags, Thunk } from './util/types'; | ||
import type { Flags, ISchema, ResolveFlags, Thunk } from './util/types'; | ||
export declare type SchemaSpec<TDefault> = { | ||
coarce: boolean; | ||
nullable: boolean; | ||
@@ -19,7 +20,8 @@ optional: boolean; | ||
}; | ||
export declare type SchemaOptions<TDefault> = { | ||
type?: string; | ||
export declare type SchemaOptions<TType, TDefault> = { | ||
type: string; | ||
spec?: SchemaSpec<TDefault>; | ||
check: (value: any) => value is NonNullable<TType>; | ||
}; | ||
export declare type AnySchema<TType = any, C = AnyObject, D = any, F extends Flags = Flags> = BaseSchema<TType, C, D, F>; | ||
export declare type AnySchema<TType = any, C = AnyObject, D = any, F extends Flags = Flags> = Schema<TType, C, D, F>; | ||
export interface CastOptions<C = {}> { | ||
@@ -36,3 +38,2 @@ parent?: any; | ||
} | ||
export declare type Cast<T, D> = T extends undefined ? D extends undefined ? T : Defined<T> : T; | ||
export interface SchemaInnerTypeDescription extends SchemaDescription { | ||
@@ -63,3 +64,3 @@ innerType?: SchemaFieldDescription; | ||
} | ||
export default abstract class BaseSchema<TType = any, TContext = AnyObject, TDefault = any, TFlags extends Flags = ''> implements ISchema<TType, TContext, TFlags, TDefault> { | ||
export default abstract class Schema<TType = any, TContext = AnyObject, TDefault = any, TFlags extends Flags = ''> implements ISchema<TType, TContext, TFlags, TDefault> { | ||
readonly type: string; | ||
@@ -80,6 +81,6 @@ readonly __outputType: ResolveFlags<TType, TFlags>; | ||
protected exclusiveTests: Record<string, boolean>; | ||
protected _typeCheck: (value: any) => value is NonNullable<TType>; | ||
spec: SchemaSpec<any>; | ||
constructor(options?: SchemaOptions<any>); | ||
constructor(options: SchemaOptions<TType, any>); | ||
get _type(): string; | ||
protected _typeCheck(_value: any): _value is NonNullable<TType>; | ||
clone(spec?: Partial<SchemaSpec<any>>): this; | ||
@@ -95,7 +96,3 @@ label(label: string): this; | ||
/** | ||
* | ||
* @param {*} value | ||
* @param {Object} options | ||
* @param {*=} options.parent | ||
* @param {*=} options.context | ||
* Run the configured transform pipeline over an input value. | ||
*/ | ||
@@ -140,4 +137,6 @@ cast(value: any, options?: CastOptions<TContext>): this['__outputType']; | ||
test(name: string, message: Message, test: TestFunction<this['__outputType'], TContext>): this; | ||
when(options: ConditionOptions<this>): this; | ||
when(keys: string | string[], options: ConditionOptions<this>): this; | ||
when<U extends ISchema<any> = this>(builder: ConditionBuilder<this, U>): U; | ||
when<U extends ISchema<any> = this>(keys: string | string[], builder: ConditionBuilder<this, U>): U; | ||
when<UThen extends ISchema<any> = this, UOtherwise extends ISchema<any> = this>(options: ConditionConfig<this, UThen, UOtherwise>): UThen | UOtherwise; | ||
when<UThen extends ISchema<any> = this, UOtherwise extends ISchema<any> = this>(keys: string | string[], options: ConditionConfig<this, UThen, UOtherwise>): UThen | UOtherwise; | ||
typeError(message: Message): this; | ||
@@ -147,3 +146,3 @@ oneOf<U extends TType>(enums: ReadonlyArray<U | Reference>, message?: Message<{ | ||
}>): any; | ||
notOneOf<U extends TType>(enums: Array<Maybe<U> | Reference>, message?: Message<{ | ||
notOneOf<U extends TType>(enums: ReadonlyArray<Maybe<U> | Reference>, message?: Message<{ | ||
values: any; | ||
@@ -159,9 +158,9 @@ }>): this; | ||
} | ||
export default interface BaseSchema<TType = any, TContext = AnyObject, TDefault = any, TFlags extends Flags = ''> { | ||
export default interface Schema<TType = any, TContext = AnyObject, TDefault = any, TFlags extends Flags = ''> { | ||
validateAt(path: string, value: any, options?: ValidateOptions<TContext>): Promise<any>; | ||
validateSyncAt(path: string, value: any, options?: ValidateOptions<TContext>): any; | ||
equals: BaseSchema['oneOf']; | ||
is: BaseSchema['oneOf']; | ||
not: BaseSchema['notOneOf']; | ||
nope: BaseSchema['notOneOf']; | ||
equals: Schema['oneOf']; | ||
is: Schema['oneOf']; | ||
not: Schema['notOneOf']; | ||
nope: Schema['notOneOf']; | ||
} |
@@ -16,3 +16,3 @@ function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } | ||
import toArray from './util/toArray'; | ||
export default class BaseSchema { | ||
export default class Schema { | ||
constructor(options) { | ||
@@ -29,2 +29,3 @@ this.type = void 0; | ||
this.exclusiveTests = Object.create(null); | ||
this._typeCheck = void 0; | ||
this.spec = void 0; | ||
@@ -36,3 +37,4 @@ this.tests = []; | ||
}); | ||
this.type = (options == null ? void 0 : options.type) || 'mixed'; | ||
this.type = options.type; | ||
this._typeCheck = options.check; | ||
this.spec = _extends({ | ||
@@ -44,3 +46,4 @@ strip: false, | ||
nullable: false, | ||
optional: true | ||
optional: true, | ||
coarce: true | ||
}, options == null ? void 0 : options.spec); | ||
@@ -57,6 +60,2 @@ this.withMutation(s => { | ||
_typeCheck(_value) { | ||
return true; | ||
} | ||
clone(spec) { | ||
@@ -73,2 +72,3 @@ if (this._mutate) { | ||
next.type = this.type; | ||
next._typeCheck = this._typeCheck; | ||
next._whitelist = this._whitelist.clone(); | ||
@@ -160,7 +160,3 @@ next._blacklist = this._blacklist.clone(); | ||
/** | ||
* | ||
* @param {*} value | ||
* @param {Object} options | ||
* @param {*=} options.parent | ||
* @param {*=} options.context | ||
* Run the configured transform pipeline over an input value. | ||
*/ | ||
@@ -482,3 +478,3 @@ | ||
}); | ||
next.conditions.push(new Condition(deps, options)); | ||
next.conditions.push(typeof options === 'function' ? new Condition(deps, options) : Condition.fromOptions(deps, options)); | ||
return next; | ||
@@ -558,3 +554,3 @@ } | ||
return next; | ||
} //BaseSchema<TType, SetFlag<TFlags, 's'>> | ||
} //Schema<TType, SetFlag<TFlags, 's'>> | ||
@@ -600,5 +596,5 @@ | ||
// @ts-expect-error | ||
BaseSchema.prototype.__isYupSchema__ = true; | ||
Schema.prototype.__isYupSchema__ = true; | ||
for (const method of ['validate', 'validateSync']) BaseSchema.prototype[`${method}At`] = function (path, value, options = {}) { | ||
for (const method of ['validate', 'validateSync']) Schema.prototype[`${method}At`] = function (path, value, options = {}) { | ||
const { | ||
@@ -615,4 +611,4 @@ parent, | ||
for (const alias of ['equals', 'is']) BaseSchema.prototype[alias] = BaseSchema.prototype.oneOf; | ||
for (const alias of ['equals', 'is']) Schema.prototype[alias] = Schema.prototype.oneOf; | ||
for (const alias of ['not', 'nope']) BaseSchema.prototype[alias] = BaseSchema.prototype.notOneOf; | ||
for (const alias of ['not', 'nope']) Schema.prototype[alias] = Schema.prototype.notOneOf; |
@@ -5,3 +5,3 @@ import { MixedLocale } from './locale'; | ||
import type { Concat, Defined, Flags, NotNull, SetFlag, Thunk, ToggleDefault, UnsetFlag } from './util/types'; | ||
import BaseSchema from './schema'; | ||
import Schema from './schema'; | ||
export declare type MatchOptions = { | ||
@@ -20,5 +20,4 @@ excludeEmptyString?: boolean; | ||
export { create }; | ||
export default class StringSchema<TType extends Maybe<string> = string | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends BaseSchema<TType, TContext, TDefault, TFlags> { | ||
export default class StringSchema<TType extends Maybe<string> = string | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends Schema<TType, TContext, TDefault, TFlags> { | ||
constructor(); | ||
protected _typeCheck(value: any): value is NonNullable<TType>; | ||
protected _isPresent(value: any): boolean; | ||
@@ -49,3 +48,3 @@ length(length: number | Reference<number>, message?: Message<{ | ||
} | ||
export default interface StringSchema<TType extends Maybe<string> = string | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends BaseSchema<TType, TContext, TDefault, TFlags> { | ||
export default interface StringSchema<TType extends Maybe<string> = string | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends Schema<TType, TContext, TDefault, TFlags> { | ||
default<D extends Maybe<TType>>(def: Thunk<D>): StringSchema<TType, TContext, D, ToggleDefault<TFlags, D>>; | ||
@@ -52,0 +51,0 @@ oneOf<U extends TType>(arrayOfValues: ReadonlyArray<U | Reference>, message?: MixedLocale['oneOf']): StringSchema<U | Optionals<TType>, TContext, TDefault, TFlags>; |
import { string as locale } from './locale'; | ||
import isAbsent from './util/isAbsent'; | ||
import BaseSchema from './schema'; | ||
import Schema from './schema'; | ||
let rEmail = // eslint-disable-next-line | ||
@@ -20,12 +20,20 @@ /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i; | ||
export { create }; | ||
export default class StringSchema extends BaseSchema { | ||
export default class StringSchema extends Schema { | ||
constructor() { | ||
super({ | ||
type: 'string' | ||
type: 'string', | ||
check(value) { | ||
if (value instanceof String) value = value.valueOf(); | ||
return typeof value === 'string'; | ||
} | ||
}); | ||
this.withMutation(() => { | ||
this.transform(function (value) { | ||
if (this.isType(value)) return value; | ||
this.transform((value, _raw, ctx) => { | ||
if (!ctx.spec.coarce || ctx.isType(value)) return value; // don't ever convert arrays | ||
if (Array.isArray(value)) return value; | ||
const strValue = value != null && value.toString ? value.toString() : value; | ||
const strValue = value != null && value.toString ? value.toString() : value; // no one wants plain objects converted to [Object object] | ||
if (strValue === objStringTag) return value; | ||
@@ -37,7 +45,2 @@ return strValue; | ||
_typeCheck(value) { | ||
if (value instanceof String) value = value.valueOf(); | ||
return typeof value === 'string'; | ||
} | ||
_isPresent(value) { | ||
@@ -44,0 +47,0 @@ return super._isPresent(value) && !!value.length; |
@@ -15,2 +15,3 @@ import ValidationError from '../ValidationError'; | ||
options: ValidateOptions<TContext>; | ||
originalValue: any; | ||
parent: any; | ||
@@ -17,0 +18,0 @@ from?: Array<{ |
@@ -19,2 +19,5 @@ import type Reference from '../Reference'; | ||
} & U) | Optionals<T>; | ||
export declare type ConcatObjectTypes<T extends Maybe<AnyObject>, U extends Maybe<AnyObject>> = ({ | ||
[P in keyof T]: P extends keyof NonNullable<U> ? NonNullable<U>[P] : T[P]; | ||
} & U) | Optionals<U>; | ||
export declare type PartialDeep<T> = T extends string | number | bigint | boolean | null | undefined | symbol | Date ? T | undefined : T extends Array<infer ArrayType> ? Array<PartialDeep<ArrayType>> : T extends ReadonlyArray<infer ArrayType> ? ReadonlyArray<ArrayType> : { | ||
@@ -21,0 +24,0 @@ [K in keyof T]?: PartialDeep<T[K]>; |
@@ -9,3 +9,3 @@ import Reference from '../Reference'; | ||
toArray(): unknown[]; | ||
resolveAll(resolve: (v: unknown) => unknown): unknown; | ||
resolveAll(resolve: (v: unknown) => unknown): unknown[]; | ||
add(value: unknown): void; | ||
@@ -12,0 +12,0 @@ delete(value: unknown): void; |
import ValidationError from '../ValidationError'; | ||
export default function sortByKeyOrder(keys: string[]): (a: ValidationError, b: ValidationError) => number; | ||
export default function sortByKeyOrder(keys: readonly string[]): (a: ValidationError, b: ValidationError) => number; |
@@ -1,1 +0,1 @@ | ||
export default function toArray<T>(value?: null | T | T[]): T[]; | ||
export default function toArray<T>(value?: null | T | readonly T[]): T[]; |
@@ -11,4 +11,4 @@ declare type Params = Record<string, unknown>; | ||
static isError(err: any): err is ValidationError; | ||
constructor(errorOrErrors: string | ValidationError | ValidationError[], value?: any, field?: string, type?: string); | ||
constructor(errorOrErrors: string | ValidationError | readonly ValidationError[], value?: any, field?: string, type?: string); | ||
} | ||
export {}; |
import type { AnyObject, InternalOptions, Callback, Message, Maybe } from './types'; | ||
import type Reference from './Reference'; | ||
import { Defined, Flags, NotNull, SetFlag, Thunk, ToggleDefault, ISchema, UnsetFlag } from './util/types'; | ||
import BaseSchema, { SchemaInnerTypeDescription, SchemaSpec } from './schema'; | ||
import { Defined, Flags, NotNull, SetFlag, Thunk, ToggleDefault, ISchema, UnsetFlag, Concat } from './util/types'; | ||
import Schema, { SchemaInnerTypeDescription, SchemaSpec } from './schema'; | ||
import { ResolveOptions } from './Condition'; | ||
export declare type RejectorFn = (value: any, index: number, array: any[]) => boolean; | ||
export declare type RejectorFn = (value: any, index: number, array: readonly any[]) => boolean; | ||
export declare function create<C extends AnyObject = AnyObject, T = any>(type?: ISchema<T, C>): ArraySchema<T, C, undefined, "", T[] | undefined>; | ||
@@ -11,6 +11,5 @@ export declare namespace create { | ||
} | ||
export default class ArraySchema<T, TContext, TDefault = undefined, TFlags extends Flags = '', TIn extends any[] | null | undefined = T[] | undefined> extends BaseSchema<TIn, TContext, TDefault, TFlags> { | ||
export default class ArraySchema<T, TContext, TDefault = undefined, TFlags extends Flags = '', TIn extends any[] | null | undefined = T[] | undefined> extends Schema<TIn, TContext, TDefault, TFlags> { | ||
innerType?: ISchema<T, TContext>; | ||
constructor(type?: ISchema<T, TContext>); | ||
protected _typeCheck(v: any): v is NonNullable<TIn>; | ||
private get _subType(); | ||
@@ -20,4 +19,4 @@ protected _cast(_value: any, _opts: InternalOptions<TContext>): any; | ||
clone(spec?: SchemaSpec<any>): this; | ||
concat<TOther extends ArraySchema<any, any, any>>(schema: TOther): TOther; | ||
concat(schema: any): any; | ||
concat<IT, IC, ID, IF extends Flags, IIn extends Maybe<IT[]>>(schema: ArraySchema<IT, IC, ID, IF, IIn>): ArraySchema<Concat<T, IT>, TContext & IC, Extract<IF, 'd'> extends never ? TDefault : ID, TFlags | IF, Concat<TIn, IIn>>; | ||
concat(schema: this): this; | ||
of<U>(schema: ISchema<U, TContext>): ArraySchema<U, TContext, TFlags>; | ||
@@ -37,6 +36,4 @@ length(length: number | Reference<number>, message?: Message<{ | ||
} | ||
export default interface ArraySchema<T, TContext, TDefault = undefined, TFlags extends Flags = '', TIn extends any[] | null | undefined = T[] | undefined> extends BaseSchema<TIn, TContext, TDefault, TFlags> { | ||
export default interface ArraySchema<T, TContext, TDefault = undefined, TFlags extends Flags = '', TIn extends any[] | null | undefined = T[] | undefined> extends Schema<TIn, TContext, TDefault, TFlags> { | ||
default<D extends Maybe<TIn>>(def: Thunk<D>): ArraySchema<T, TContext, D, ToggleDefault<TFlags, D>, TIn>; | ||
concat<IT, IC, ID, IF extends Flags, IIn extends Maybe<IT[]>>(schema: ArraySchema<IT, IC, ID, IF, IIn>): ArraySchema<NonNullable<T> | IT, TContext & IC, Extract<IF, 'd'> extends never ? TDefault : ID, TFlags | IF, IIn>; | ||
concat(schema: this): this; | ||
defined(msg?: Message): ArraySchema<T, TContext, TDefault, TFlags, Defined<TIn>>; | ||
@@ -43,0 +40,0 @@ optional(): ArraySchema<T, TContext, TDefault, TFlags, TIn | undefined>; |
@@ -34,3 +34,8 @@ "use strict"; | ||
super({ | ||
type: 'array' | ||
type: 'array', | ||
check(v) { | ||
return Array.isArray(v); | ||
} | ||
}); // `undefined` specifically means uninitialized, as opposed to | ||
@@ -42,9 +47,14 @@ // "no subtype" | ||
this.withMutation(() => { | ||
this.transform(function (values) { | ||
if (typeof values === 'string') try { | ||
values = JSON.parse(values); | ||
} catch (err) { | ||
values = null; | ||
this.transform((values, _, ctx) => { | ||
if (!ctx.spec.coarce) return values; | ||
if (typeof values === 'string') { | ||
try { | ||
values = JSON.parse(values); | ||
} catch (err) { | ||
values = null; | ||
} | ||
} | ||
return this.isType(values) ? values : null; | ||
return ctx.isType(values) ? values : null; | ||
}); | ||
@@ -54,6 +64,2 @@ }); | ||
_typeCheck(v) { | ||
return Array.isArray(v); | ||
} | ||
get _subType() { | ||
@@ -60,0 +66,0 @@ return this.innerType; |
@@ -1,4 +0,4 @@ | ||
import BaseSchema from './schema'; | ||
import type { AnyObject, Maybe, Message } from './types'; | ||
import type { Defined, Flags, NotNull, SetFlag, Thunk, ToggleDefault } from './util/types'; | ||
import Schema from './schema'; | ||
import type { AnyObject, Maybe, Message, Optionals } from './types'; | ||
import type { Defined, Flags, NotNull, SetFlag, Thunk, ToggleDefault, UnsetFlag } from './util/types'; | ||
export declare function create(): BooleanSchema; | ||
@@ -9,7 +9,6 @@ export declare function create<T extends boolean, TContext = AnyObject>(): BooleanSchema<T | undefined, TContext>; | ||
} | ||
export default class BooleanSchema<TType extends Maybe<boolean> = boolean | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends BaseSchema<TType, TContext, TDefault, TFlags> { | ||
export default class BooleanSchema<TType extends Maybe<boolean> = boolean | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends Schema<TType, TContext, TDefault, TFlags> { | ||
constructor(); | ||
protected _typeCheck(v: any): v is NonNullable<TType>; | ||
isTrue(message?: Message<any> | undefined): BooleanSchema<TType | true, TContext, TFlags>; | ||
isFalse(message?: Message<any> | undefined): BooleanSchema<TType | false, TContext, TFlags>; | ||
isTrue(message?: Message<any> | undefined): BooleanSchema<true | Optionals<TType>, TContext, TFlags>; | ||
isFalse(message?: Message<any> | undefined): BooleanSchema<false | Optionals<TType>, TContext, TFlags>; | ||
default<D extends Maybe<TType>>(def: Thunk<D>): BooleanSchema<TType, TContext, D, ToggleDefault<TFlags, D>>; | ||
@@ -22,3 +21,4 @@ defined(msg?: Message): BooleanSchema<Defined<TType>, TContext, TDefault, TFlags>; | ||
nonNullable(msg?: Message): BooleanSchema<NotNull<TType>, TContext, TDefault, TFlags>; | ||
strip(): BooleanSchema<TType, TContext, TDefault, SetFlag<TFlags, 's'>>; | ||
strip(enabled: false): BooleanSchema<TType, TContext, TDefault, UnsetFlag<TFlags, 's'>>; | ||
strip(enabled?: true): BooleanSchema<TType, TContext, TDefault, SetFlag<TFlags, 's'>>; | ||
} |
@@ -24,7 +24,13 @@ "use strict"; | ||
super({ | ||
type: 'boolean' | ||
type: 'boolean', | ||
check(v) { | ||
if (v instanceof Boolean) v = v.valueOf(); | ||
return typeof v === 'boolean'; | ||
} | ||
}); | ||
this.withMutation(() => { | ||
this.transform(function (value) { | ||
if (!this.isType(value)) { | ||
this.transform((value, _raw, ctx) => { | ||
if (ctx.spec.coarce && !ctx.isType(value)) { | ||
if (/^(true|1)$/i.test(String(value))) return true; | ||
@@ -39,7 +45,2 @@ if (/^(false|0)$/i.test(String(value))) return false; | ||
_typeCheck(v) { | ||
if (v instanceof Boolean) v = v.valueOf(); | ||
return typeof v === 'boolean'; | ||
} | ||
isTrue(message = _locale.boolean.isValue) { | ||
@@ -106,4 +107,4 @@ return this.test({ | ||
strip() { | ||
return super.strip(); | ||
strip(v) { | ||
return super.strip(v); | ||
} | ||
@@ -110,0 +111,0 @@ |
import Reference from './Reference'; | ||
import type { ISchema } from './util/types'; | ||
export interface ConditionBuilder<T extends ISchema<any, any>> { | ||
(this: T, value: any, schema: T): ISchema<any, any> | void; | ||
(v1: any, v2: any, schema: T): ISchema<any, any> | void; | ||
(v1: any, v2: any, v3: any, schema: T): ISchema<any, any> | void; | ||
(v1: any, v2: any, v3: any, v4: any, schema: T): ISchema<any, any> | void; | ||
} | ||
export declare type ConditionConfig<T extends ISchema<any>> = { | ||
export declare type ConditionBuilder<T extends ISchema<any, any>, U extends ISchema<any, any> = T> = (values: any[], schema: T, options: ResolveOptions) => U; | ||
export declare type ConditionConfig<T extends ISchema<any>, TThen extends ISchema<any, any> = T, TOtherwise extends ISchema<any, any> = T> = { | ||
is: any | ((...values: any[]) => boolean); | ||
then?: (schema: T) => ISchema<any>; | ||
otherwise?: (schema: T) => ISchema<any>; | ||
then?: (schema: T) => TThen; | ||
otherwise?: (schema: T) => TOtherwise; | ||
}; | ||
export declare type ConditionOptions<T extends ISchema<any, any>> = ConditionBuilder<T> | ConditionConfig<T>; | ||
export declare type ResolveOptions<TContext = any> = { | ||
@@ -20,8 +14,9 @@ value?: any; | ||
}; | ||
declare class Condition<T extends ISchema<any, any> = ISchema<any, any>> { | ||
refs: Reference[]; | ||
fn: ConditionBuilder<T>; | ||
constructor(refs: Reference[], options: ConditionOptions<T>); | ||
resolve(base: T, options: ResolveOptions): ISchema<any, import("./types").AnyObject, any, any> | T; | ||
declare class Condition<TIn extends ISchema<any, any> = ISchema<any, any>, TOut extends ISchema<any, any> = TIn> { | ||
refs: readonly Reference[]; | ||
fn: ConditionBuilder<TIn, TOut>; | ||
static fromOptions<TIn extends ISchema<any, any>, TThen extends ISchema<any, any>, TOtherwise extends ISchema<any, any>>(refs: Reference[], config: ConditionConfig<TIn, TThen, TOtherwise>): Condition<TIn, TThen | TOtherwise>; | ||
constructor(refs: readonly Reference[], builder: ConditionBuilder<TIn, TOut>); | ||
resolve(base: TIn, options: ResolveOptions): ISchema<any, any, any, any>; | ||
} | ||
export default Condition; |
@@ -13,14 +13,4 @@ "use strict"; | ||
class Condition { | ||
constructor(refs, options) { | ||
this.fn = void 0; | ||
this.refs = refs; | ||
this.refs = refs; | ||
if (typeof options === 'function') { | ||
this.fn = options; | ||
return; | ||
} | ||
if (!('is' in options)) throw new TypeError('`is:` is required for `when()` conditions'); | ||
if (!options.then && !options.otherwise) throw new TypeError('either `then:` or `otherwise:` is required for `when()` conditions'); | ||
static fromOptions(refs, config) { | ||
if (!config.then && !config.otherwise) throw new TypeError('either `then:` or `otherwise:` is required for `when()` conditions'); | ||
let { | ||
@@ -30,21 +20,29 @@ is, | ||
otherwise | ||
} = options; | ||
} = config; | ||
let check = typeof is === 'function' ? is : (...values) => values.every(value => value === is); | ||
this.fn = function (...args) { | ||
return new Condition(refs, (values, schema) => { | ||
var _branch; | ||
let _opts = args.pop(); | ||
let schema = args.pop(); | ||
let branch = check(...args) ? then : otherwise; | ||
let branch = check(...values) ? then : otherwise; | ||
return (_branch = branch == null ? void 0 : branch(schema)) != null ? _branch : schema; | ||
}; | ||
}); | ||
} | ||
constructor(refs, builder) { | ||
this.fn = void 0; | ||
this.refs = refs; | ||
this.refs = refs; | ||
this.fn = builder; | ||
} | ||
resolve(base, options) { | ||
let values = this.refs.map(ref => // TODO: ? operator here? | ||
ref.getValue(options == null ? void 0 : options.value, options == null ? void 0 : options.parent, options == null ? void 0 : options.context)); | ||
let schema = this.fn.apply(base, values.concat(base, options)); | ||
if (schema === undefined || schema === base) return base; | ||
let schema = this.fn(values, base, options); | ||
if (schema === undefined || // @ts-ignore this can be base | ||
schema === base) { | ||
return base; | ||
} | ||
if (!(0, _isSchema.default)(schema)) throw new TypeError('conditions must return a schema object'); | ||
@@ -51,0 +49,0 @@ return schema.resolve(options); |
import Ref from './Reference'; | ||
import type { AnyObject, Maybe, Message } from './types'; | ||
import type { Defined, Flags, NotNull, SetFlag, Thunk, ToggleDefault, UnsetFlag } from './util/types'; | ||
import BaseSchema from './schema'; | ||
import Schema from './schema'; | ||
export declare function create(): DateSchema; | ||
@@ -11,6 +11,5 @@ export declare function create<T extends Date, TContext = AnyObject>(): DateSchema<T | undefined, TContext>; | ||
} | ||
export default class DateSchema<TType extends Maybe<Date> = Date | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends BaseSchema<TType, TContext, TDefault, TFlags> { | ||
export default class DateSchema<TType extends Maybe<Date> = Date | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends Schema<TType, TContext, TDefault, TFlags> { | ||
static INVALID_DATE: Date; | ||
constructor(); | ||
protected _typeCheck(v: any): v is NonNullable<TType>; | ||
private prepareParam; | ||
@@ -24,3 +23,3 @@ min(min: unknown | Ref<Date>, message?: Message<{ | ||
} | ||
export default interface DateSchema<TType extends Maybe<Date>, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends BaseSchema<TType, TContext, TDefault, TFlags> { | ||
export default interface DateSchema<TType extends Maybe<Date>, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends Schema<TType, TContext, TDefault, TFlags> { | ||
default<D extends Maybe<TType>>(def: Thunk<D>): DateSchema<TType, TContext, D, ToggleDefault<TFlags, D>>; | ||
@@ -27,0 +26,0 @@ concat<TOther extends DateSchema<any, any>>(schema: TOther): TOther; |
@@ -33,10 +33,15 @@ "use strict"; | ||
super({ | ||
type: 'date' | ||
type: 'date', | ||
check(v) { | ||
return isDate(v) && !isNaN(v.getTime()); | ||
} | ||
}); | ||
this.withMutation(() => { | ||
this.transform(function (value) { | ||
if (this.isType(value)) return value; | ||
this.transform((value, _raw, ctx) => { | ||
if (!ctx.spec.coarce || ctx.isType(value)) return value; | ||
value = (0, _isodate.default)(value); // 0 is a valid timestamp equivalent to 1970-01-01T00:00:00Z(unix epoch) or before. | ||
return !isNaN(value) ? new Date(value) : invalidDate; | ||
return !isNaN(value) ? new Date(value) : DateSchema.INVALID_DATE; | ||
}); | ||
@@ -46,6 +51,2 @@ }); | ||
_typeCheck(v) { | ||
return isDate(v) && !isNaN(v.getTime()); | ||
} | ||
prepareParam(ref, name) { | ||
@@ -52,0 +53,0 @@ let param; |
@@ -1,2 +0,2 @@ | ||
import Mixed, { create as mixedCreate, MixedSchema } from './mixed'; | ||
import MixedSchema, { create as mixedCreate, MixedOptions, TypeGuard } from './mixed'; | ||
import BooleanSchema, { create as boolCreate } from './boolean'; | ||
@@ -14,3 +14,3 @@ import StringSchema, { create as stringCreate } from './string'; | ||
import setLocale from './setLocale'; | ||
import BaseSchema, { AnySchema } from './schema'; | ||
import Schema, { AnySchema } from './schema'; | ||
import type { InferType } from './util/types'; | ||
@@ -20,5 +20,5 @@ declare function addMethod<T extends AnySchema>(schemaType: (...arg: any[]) => T, name: string, fn: (this: T, ...args: any[]) => T): void; | ||
export declare type AnyObjectSchema = ObjectSchema<any, any, any, any>; | ||
export type { AnyObject, InferType, InferType as Asserts, AnySchema }; | ||
export type { AnyObject, InferType, InferType as Asserts, AnySchema, MixedOptions, TypeGuard, }; | ||
export { mixedCreate as mixed, boolCreate as bool, boolCreate as boolean, stringCreate as string, numberCreate as number, dateCreate as date, objectCreate as object, arrayCreate as array, refCreate as ref, lazyCreate as lazy, reach, isSchema, addMethod, setLocale, ValidationError, }; | ||
export { BaseSchema, Mixed as MixedSchema, MixedSchema as MixedSchemaClass, BooleanSchema, StringSchema, NumberSchema, DateSchema, ObjectSchema, ArraySchema, }; | ||
export { Schema, MixedSchema, BooleanSchema, StringSchema, NumberSchema, DateSchema, ObjectSchema, ArraySchema, }; | ||
export type { CreateErrorOptions, TestContext, TestFunction, TestOptions, TestConfig, } from './util/createValidation'; |
@@ -12,8 +12,2 @@ "use strict"; | ||
}); | ||
Object.defineProperty(exports, "BaseSchema", { | ||
enumerable: true, | ||
get: function () { | ||
return _schema.default; | ||
} | ||
}); | ||
Object.defineProperty(exports, "BooleanSchema", { | ||
@@ -37,8 +31,2 @@ enumerable: true, | ||
}); | ||
Object.defineProperty(exports, "MixedSchemaClass", { | ||
enumerable: true, | ||
get: function () { | ||
return _mixed.MixedSchema; | ||
} | ||
}); | ||
Object.defineProperty(exports, "NumberSchema", { | ||
@@ -56,2 +44,8 @@ enumerable: true, | ||
}); | ||
Object.defineProperty(exports, "Schema", { | ||
enumerable: true, | ||
get: function () { | ||
return _schema.default; | ||
} | ||
}); | ||
Object.defineProperty(exports, "StringSchema", { | ||
@@ -58,0 +52,0 @@ enumerable: true, |
@@ -5,3 +5,3 @@ import type { AnyObject, Callback, ValidateOptions } from './types'; | ||
import { Flags, ISchema } from './util/types'; | ||
import { BaseSchema } from '.'; | ||
import { Schema } from '.'; | ||
export declare type LazyBuilder<T, TContext = AnyObject, TDefault = any, TFlags extends Flags = any> = (value: any, options: ResolveOptions) => ISchema<T, TContext, TFlags, TDefault>; | ||
@@ -24,3 +24,3 @@ export declare function create<T, TContext = AnyObject, TFlags extends Flags = any, TDefault = any>(builder: LazyBuilder<T, TContext, TDefault, TFlags>): Lazy<T, TContext, TDefault, TFlags>; | ||
private _resolve; | ||
resolve(options: ResolveOptions<TContext>): BaseSchema<T, TContext, TDefault, TFlags>; | ||
resolve(options: ResolveOptions<TContext>): Schema<T, TContext, TDefault, TFlags>; | ||
cast(value: any, options?: CastOptions<TContext>): T; | ||
@@ -27,0 +27,0 @@ validate(value: any, options?: ValidateOptions, maybeCb?: Callback): Promise<T>; |
@@ -15,2 +15,4 @@ "use strict"; | ||
required: '${path} is a required field', | ||
defined: '${path} must be defined', | ||
notNull: '${path} cannot be null', | ||
oneOf: '${path} must be one of the following values: ${values}', | ||
@@ -24,7 +26,5 @@ notOneOf: '${path} must not be one of the following values: ${values}', | ||
}) => { | ||
let isCast = originalValue != null && originalValue !== value; | ||
return `${path} must be a \`${type}\` type, ` + `but the final value was: \`${(0, _printValue.default)(value, true)}\`` + (isCast ? ` (cast from the value \`${(0, _printValue.default)(originalValue, true)}\`).` : '.'); | ||
}, | ||
defined: '${path} must be defined', | ||
notNull: '${path} cannot be null' | ||
const castMsg = originalValue != null && originalValue !== value ? ` (cast from the value \`${(0, _printValue.default)(originalValue, true)}\`).` : '.'; | ||
return type !== 'mixed' ? `${path} must be a \`${type}\` type, ` + `but the final value was: \`${(0, _printValue.default)(value, true)}\`` + castMsg : `${path} must match the configured type. ` + `The validated value was: \`${(0, _printValue.default)(value, true)}\`` + castMsg; | ||
} | ||
}; | ||
@@ -31,0 +31,0 @@ exports.mixed = mixed; |
@@ -1,8 +0,20 @@ | ||
import { AnyObject, Maybe, Message, Optionals } from './types'; | ||
import type { Defined, Flags, SetFlag, Thunk, ToggleDefault, UnsetFlag } from './util/types'; | ||
import BaseSchema from './schema'; | ||
export declare class MixedSchema<TType = any, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends BaseSchema<TType, TContext, TDefault, TFlags> { | ||
import { AnyObject, Maybe, Message } from './types'; | ||
import type { Concat, Defined, Flags, SetFlag, Thunk, ToggleDefault, UnsetFlag } from './util/types'; | ||
import Schema from './schema'; | ||
export declare type TypeGuard<TType> = (value: any) => value is NonNullable<TType>; | ||
export interface MixedOptions<TType> { | ||
type?: string; | ||
check?: TypeGuard<TType>; | ||
} | ||
export declare function create<TType = any>(spec?: MixedOptions<TType> | TypeGuard<TType>): MixedSchema<TType | undefined, AnyObject, undefined, "">; | ||
export declare namespace create { | ||
var prototype: MixedSchema<any, any, any, any>; | ||
} | ||
export default class MixedSchema<TType = any, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends Schema<TType, TContext, TDefault, TFlags> { | ||
constructor(spec?: MixedOptions<TType> | TypeGuard<TType>); | ||
} | ||
export default interface MixedSchema<TType = any, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends Schema<TType, TContext, TDefault, TFlags> { | ||
default<D extends Maybe<TType>>(def: Thunk<D>): MixedSchema<TType, TContext, D, ToggleDefault<TFlags, D>>; | ||
concat<IT, IC, ID, IF extends Flags>(schema: MixedSchema<IT, IC, ID, IF>): MixedSchema<NonNullable<TType> | IT, TContext & IC, ID, TFlags | IF>; | ||
concat<IT, IC, ID, IF extends Flags>(schema: BaseSchema<IT, IC, ID, IF>): MixedSchema<NonNullable<TType> | Optionals<IT>, TContext & IC, ID, TFlags | IF>; | ||
concat<IT, IC, ID, IF extends Flags>(schema: MixedSchema<IT, IC, ID, IF>): MixedSchema<Concat<TType, IT>, TContext & IC, ID, TFlags | IF>; | ||
concat<IT, IC, ID, IF extends Flags>(schema: Schema<IT, IC, ID, IF>): MixedSchema<Concat<TType, IT>, TContext & IC, ID, TFlags | IF>; | ||
concat(schema: this): this; | ||
@@ -18,7 +30,1 @@ defined(msg?: Message): MixedSchema<Defined<TType>, TContext, TDefault, TFlags>; | ||
} | ||
declare const Mixed: typeof MixedSchema; | ||
export default Mixed; | ||
export declare function create<TType = any>(): MixedSchema<TType | undefined, AnyObject, undefined, "">; | ||
export declare namespace create { | ||
var prototype: MixedSchema<any, any, any, any>; | ||
} |
@@ -13,11 +13,24 @@ "use strict"; | ||
const Mixed = _schema.default; | ||
var _default = Mixed; | ||
exports.default = _default; | ||
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } | ||
function create() { | ||
return new Mixed(); | ||
} // XXX: this is using the Base schema so that `addMethod(mixed)` works as a base class | ||
const returnsTrue = () => true; | ||
function create(spec) { | ||
return new MixedSchema(spec); | ||
} | ||
create.prototype = Mixed.prototype; | ||
class MixedSchema extends _schema.default { | ||
constructor(spec) { | ||
super(typeof spec === 'function' ? { | ||
type: 'mixed', | ||
check: spec | ||
} : _extends({ | ||
type: 'mixed', | ||
check: returnsTrue | ||
}, spec)); | ||
} | ||
} | ||
exports.default = MixedSchema; | ||
create.prototype = MixedSchema.prototype; |
import type { AnyObject, Maybe, Message } from './types'; | ||
import type Reference from './Reference'; | ||
import type { Concat, Defined, Flags, NotNull, SetFlag, Thunk, ToggleDefault, UnsetFlag } from './util/types'; | ||
import BaseSchema from './schema'; | ||
import Schema from './schema'; | ||
export declare function create(): NumberSchema; | ||
@@ -10,5 +10,4 @@ export declare function create<T extends number, TContext = AnyObject>(): NumberSchema<T | undefined, TContext>; | ||
} | ||
export default class NumberSchema<TType extends Maybe<number> = number | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends BaseSchema<TType, TContext, TDefault, TFlags> { | ||
export default class NumberSchema<TType extends Maybe<number> = number | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends Schema<TType, TContext, TDefault, TFlags> { | ||
constructor(); | ||
protected _typeCheck(value: any): value is NonNullable<TType>; | ||
min(min: number | Reference<number>, message?: Message<{ | ||
@@ -36,3 +35,3 @@ min: number; | ||
} | ||
export default interface NumberSchema<TType extends Maybe<number> = number | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends BaseSchema<TType, TContext, TDefault, TFlags> { | ||
export default interface NumberSchema<TType extends Maybe<number> = number | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends Schema<TType, TContext, TDefault, TFlags> { | ||
default<D extends Maybe<TType>>(def: Thunk<D>): NumberSchema<TType, TContext, D, ToggleDefault<TFlags, D>>; | ||
@@ -39,0 +38,0 @@ concat<UType extends Maybe<number>, UContext, UFlags extends Flags, UDefault>(schema: NumberSchema<UType, UContext, UDefault, UFlags>): NumberSchema<Concat<TType, UType>, TContext & UContext, UDefault, TFlags | UFlags>; |
@@ -26,6 +26,13 @@ "use strict"; | ||
super({ | ||
type: 'number' | ||
type: 'number', | ||
check(value) { | ||
if (value instanceof Number) value = value.valueOf(); | ||
return typeof value === 'number' && !isNaN(value); | ||
} | ||
}); | ||
this.withMutation(() => { | ||
this.transform(function (value) { | ||
this.transform((value, _raw, ctx) => { | ||
if (!ctx.spec.coarce) return value; | ||
let parsed = value; | ||
@@ -40,3 +47,3 @@ | ||
if (this.isType(parsed)) return parsed; | ||
if (ctx.isType(parsed)) return parsed; | ||
return parseFloat(parsed); | ||
@@ -47,7 +54,2 @@ }); | ||
_typeCheck(value) { | ||
if (value instanceof Number) value = value.valueOf(); | ||
return typeof value === 'number' && !isNaN(value); | ||
} | ||
min(min, message = _locale.number.min) { | ||
@@ -54,0 +56,0 @@ return this.test({ |
@@ -5,5 +5,5 @@ import { Flags, ISchema, SetFlag, ToggleDefault, UnsetFlag } from './util/types'; | ||
import type Reference from './Reference'; | ||
import BaseSchema, { SchemaObjectDescription, SchemaSpec } from './schema'; | ||
import Schema, { SchemaObjectDescription, SchemaSpec } from './schema'; | ||
import { ResolveOptions } from './Condition'; | ||
import type { AnyObject, DefaultFromShape, MakePartial, ObjectShape, PartialDeep, TypeFromShape } from './util/objectTypes'; | ||
import type { AnyObject, ConcatObjectTypes, DefaultFromShape, MakePartial, ObjectShape, PartialDeep, TypeFromShape } from './util/objectTypes'; | ||
export type { AnyObject }; | ||
@@ -17,7 +17,7 @@ declare type MakeKeysOptional<T> = T extends AnyObject ? _<MakePartial<T>> : T; | ||
}; | ||
export declare function create<C = AnyObject, S extends ObjectShape = {}>(spec?: S): ObjectSchema<_<TypeFromShape<S, C>>, C, _<DefaultFromShape<S>>, "d">; | ||
export declare function create<C = AnyObject, S extends ObjectShape = {}>(spec?: S): ObjectSchema<_<TypeFromShape<S, C>>, C, _<DefaultFromShape<S>>, "">; | ||
export declare namespace create { | ||
var prototype: ObjectSchema<any, any, any, any>; | ||
} | ||
export default interface ObjectSchema<TIn extends Maybe<AnyObject>, TContext = AnyObject, TDefault = any, TFlags extends Flags = 'd'> extends BaseSchema<MakeKeysOptional<TIn>, TContext, TDefault, TFlags> { | ||
export default interface ObjectSchema<TIn extends Maybe<AnyObject>, TContext = AnyObject, TDefault = any, TFlags extends Flags = ''> extends Schema<MakeKeysOptional<TIn>, TContext, TDefault, TFlags> { | ||
default<D extends Maybe<AnyObject>>(def: Thunk<D>): ObjectSchema<TIn, TContext, D, ToggleDefault<TFlags, 'd'>>; | ||
@@ -33,3 +33,3 @@ defined(msg?: Message): ObjectSchema<Defined<TIn>, TContext, TDefault, TFlags>; | ||
} | ||
export default class ObjectSchema<TIn extends Maybe<AnyObject>, TContext = AnyObject, TDefault = any, TFlags extends Flags = 'd'> extends BaseSchema<MakeKeysOptional<TIn>, TContext, TDefault, TFlags> { | ||
export default class ObjectSchema<TIn extends Maybe<AnyObject>, TContext = AnyObject, TDefault = any, TFlags extends Flags = ''> extends Schema<MakeKeysOptional<TIn>, TContext, TDefault, TFlags> { | ||
fields: Shape<NonNullable<TIn>, TContext>; | ||
@@ -41,15 +41,14 @@ spec: ObjectSchemaSpec; | ||
constructor(spec?: Shape<TIn, TContext>); | ||
protected _typeCheck(value: any): value is NonNullable<MakeKeysOptional<TIn>>; | ||
protected _cast(_value: any, options?: InternalOptions<TContext>): any; | ||
protected _validate(_value: any, opts: InternalOptions<TContext> | undefined, callback: Callback): void; | ||
clone(spec?: ObjectSchemaSpec): this; | ||
concat<IIn, IC, ID, IF extends Flags>(schema: ObjectSchema<IIn, IC, ID, IF>): ObjectSchema<NonNullable<TIn> | IIn, TContext & IC, TDefault & ID, TFlags | IF>; | ||
concat<IIn, IC, ID, IF extends Flags>(schema: ObjectSchema<IIn, IC, ID, IF>): ObjectSchema<ConcatObjectTypes<TIn, IIn>, TContext & IC, Extract<IF, 'd'> extends never ? _<ConcatObjectTypes<TDefault, ID>> : ID, TFlags | IF>; | ||
concat(schema: this): this; | ||
protected _getDefault(): any; | ||
private setFields; | ||
shape<U extends ObjectShape>(additions: U, excludes?: [string, string][]): ObjectSchema<_<{ [P in keyof TIn]: P extends keyof U ? TypeFromShape<U, TContext>[P] : TIn[P]; } & TypeFromShape<U, TContext>> | _<Extract<TIn, null | undefined>>, TContext, Extract<TFlags, "d"> extends never ? _<TDefault & DefaultFromShape<U>> : TDefault, TFlags>; | ||
shape<U extends ObjectShape>(additions: U, excludes?: readonly [string, string][]): ObjectSchema<_<{ [P in keyof TIn]: P extends keyof U ? TypeFromShape<U, TContext>[P] : TIn[P]; } & TypeFromShape<U, TContext>> | _<Extract<TIn, null | undefined>>, TContext, Extract<TFlags, "d"> extends never ? _<TDefault & DefaultFromShape<U>> : TDefault, TFlags>; | ||
partial(): ObjectSchema<Partial<TIn>, TContext, TDefault, TFlags>; | ||
deepPartial(): ObjectSchema<PartialDeep<TIn>, TContext, TDefault, TFlags>; | ||
pick<TKey extends keyof TIn>(keys: TKey[]): ObjectSchema<{ [K in TKey]: TIn[K]; }, TContext, TDefault, TFlags>; | ||
omit<TKey extends keyof TIn>(keys: TKey[]): ObjectSchema<Omit<TIn, TKey>, TContext, TDefault, TFlags>; | ||
pick<TKey extends keyof TIn>(keys: readonly TKey[]): ObjectSchema<{ [K in TKey]: TIn[K]; }, TContext, TDefault, TFlags>; | ||
omit<TKey extends keyof TIn>(keys: readonly TKey[]): ObjectSchema<Omit<TIn, TKey>, TContext, TDefault, TFlags>; | ||
from(from: string, to: keyof TIn, alias?: boolean): this; | ||
@@ -56,0 +55,0 @@ noUnknown(message?: Message): this; |
@@ -51,6 +51,10 @@ "use strict"; | ||
class ObjectSchema extends _schema.default { | ||
//readonly (keyof TIn & string)[] | ||
constructor(spec) { | ||
super({ | ||
type: 'object' | ||
type: 'object', | ||
check(value) { | ||
return isObject(value) || typeof value === 'function'; | ||
} | ||
}); | ||
@@ -62,3 +66,3 @@ this.fields = Object.create(null); | ||
this.withMutation(() => { | ||
this.transform(function coerce(value) { | ||
this.transform((value, _raw, ctx) => { | ||
if (typeof value === 'string') { | ||
@@ -72,3 +76,3 @@ try { | ||
if (this.isType(value)) return value; | ||
if (ctx.isType(value)) return value; | ||
return null; | ||
@@ -83,6 +87,2 @@ }); | ||
_typeCheck(value) { | ||
return isObject(value) || typeof value === 'function'; | ||
} | ||
_cast(_value, options = {}) { | ||
@@ -233,8 +233,3 @@ var _options$stripUnknown; | ||
const target = nextFields[field]; | ||
if (target === undefined) { | ||
nextFields[field] = schemaOrRef; | ||
} else if (target instanceof _schema.default && schemaOrRef instanceof _schema.default) { | ||
nextFields[field] = schemaOrRef.concat(target); | ||
} | ||
nextFields[field] = target === undefined ? schemaOrRef : target; | ||
} | ||
@@ -241,0 +236,0 @@ |
@@ -1,2 +0,2 @@ | ||
import { ConditionOptions, ResolveOptions } from './Condition'; | ||
import { ConditionBuilder, ConditionConfig, ResolveOptions } from './Condition'; | ||
import { TestFunction, Test, TestConfig } from './util/createValidation'; | ||
@@ -6,4 +6,5 @@ import { ValidateOptions, TransformFunction, Message, Callback, InternalOptions, Maybe, ExtraParams, AnyObject } from './types'; | ||
import Reference from './Reference'; | ||
import type { Defined, Flags, ISchema, ResolveFlags, Thunk } from './util/types'; | ||
import type { Flags, ISchema, ResolveFlags, Thunk } from './util/types'; | ||
export declare type SchemaSpec<TDefault> = { | ||
coarce: boolean; | ||
nullable: boolean; | ||
@@ -19,7 +20,8 @@ optional: boolean; | ||
}; | ||
export declare type SchemaOptions<TDefault> = { | ||
type?: string; | ||
export declare type SchemaOptions<TType, TDefault> = { | ||
type: string; | ||
spec?: SchemaSpec<TDefault>; | ||
check: (value: any) => value is NonNullable<TType>; | ||
}; | ||
export declare type AnySchema<TType = any, C = AnyObject, D = any, F extends Flags = Flags> = BaseSchema<TType, C, D, F>; | ||
export declare type AnySchema<TType = any, C = AnyObject, D = any, F extends Flags = Flags> = Schema<TType, C, D, F>; | ||
export interface CastOptions<C = {}> { | ||
@@ -36,3 +38,2 @@ parent?: any; | ||
} | ||
export declare type Cast<T, D> = T extends undefined ? D extends undefined ? T : Defined<T> : T; | ||
export interface SchemaInnerTypeDescription extends SchemaDescription { | ||
@@ -63,3 +64,3 @@ innerType?: SchemaFieldDescription; | ||
} | ||
export default abstract class BaseSchema<TType = any, TContext = AnyObject, TDefault = any, TFlags extends Flags = ''> implements ISchema<TType, TContext, TFlags, TDefault> { | ||
export default abstract class Schema<TType = any, TContext = AnyObject, TDefault = any, TFlags extends Flags = ''> implements ISchema<TType, TContext, TFlags, TDefault> { | ||
readonly type: string; | ||
@@ -80,6 +81,6 @@ readonly __outputType: ResolveFlags<TType, TFlags>; | ||
protected exclusiveTests: Record<string, boolean>; | ||
protected _typeCheck: (value: any) => value is NonNullable<TType>; | ||
spec: SchemaSpec<any>; | ||
constructor(options?: SchemaOptions<any>); | ||
constructor(options: SchemaOptions<TType, any>); | ||
get _type(): string; | ||
protected _typeCheck(_value: any): _value is NonNullable<TType>; | ||
clone(spec?: Partial<SchemaSpec<any>>): this; | ||
@@ -95,7 +96,3 @@ label(label: string): this; | ||
/** | ||
* | ||
* @param {*} value | ||
* @param {Object} options | ||
* @param {*=} options.parent | ||
* @param {*=} options.context | ||
* Run the configured transform pipeline over an input value. | ||
*/ | ||
@@ -140,4 +137,6 @@ cast(value: any, options?: CastOptions<TContext>): this['__outputType']; | ||
test(name: string, message: Message, test: TestFunction<this['__outputType'], TContext>): this; | ||
when(options: ConditionOptions<this>): this; | ||
when(keys: string | string[], options: ConditionOptions<this>): this; | ||
when<U extends ISchema<any> = this>(builder: ConditionBuilder<this, U>): U; | ||
when<U extends ISchema<any> = this>(keys: string | string[], builder: ConditionBuilder<this, U>): U; | ||
when<UThen extends ISchema<any> = this, UOtherwise extends ISchema<any> = this>(options: ConditionConfig<this, UThen, UOtherwise>): UThen | UOtherwise; | ||
when<UThen extends ISchema<any> = this, UOtherwise extends ISchema<any> = this>(keys: string | string[], options: ConditionConfig<this, UThen, UOtherwise>): UThen | UOtherwise; | ||
typeError(message: Message): this; | ||
@@ -147,3 +146,3 @@ oneOf<U extends TType>(enums: ReadonlyArray<U | Reference>, message?: Message<{ | ||
}>): any; | ||
notOneOf<U extends TType>(enums: Array<Maybe<U> | Reference>, message?: Message<{ | ||
notOneOf<U extends TType>(enums: ReadonlyArray<Maybe<U> | Reference>, message?: Message<{ | ||
values: any; | ||
@@ -159,9 +158,9 @@ }>): this; | ||
} | ||
export default interface BaseSchema<TType = any, TContext = AnyObject, TDefault = any, TFlags extends Flags = ''> { | ||
export default interface Schema<TType = any, TContext = AnyObject, TDefault = any, TFlags extends Flags = ''> { | ||
validateAt(path: string, value: any, options?: ValidateOptions<TContext>): Promise<any>; | ||
validateSyncAt(path: string, value: any, options?: ValidateOptions<TContext>): any; | ||
equals: BaseSchema['oneOf']; | ||
is: BaseSchema['oneOf']; | ||
not: BaseSchema['notOneOf']; | ||
nope: BaseSchema['notOneOf']; | ||
equals: Schema['oneOf']; | ||
is: Schema['oneOf']; | ||
not: Schema['notOneOf']; | ||
nope: Schema['notOneOf']; | ||
} |
@@ -36,3 +36,3 @@ "use strict"; | ||
class BaseSchema { | ||
class Schema { | ||
constructor(options) { | ||
@@ -49,2 +49,3 @@ this.type = void 0; | ||
this.exclusiveTests = Object.create(null); | ||
this._typeCheck = void 0; | ||
this.spec = void 0; | ||
@@ -56,3 +57,4 @@ this.tests = []; | ||
}); | ||
this.type = (options == null ? void 0 : options.type) || 'mixed'; | ||
this.type = options.type; | ||
this._typeCheck = options.check; | ||
this.spec = _extends({ | ||
@@ -64,3 +66,4 @@ strip: false, | ||
nullable: false, | ||
optional: true | ||
optional: true, | ||
coarce: true | ||
}, options == null ? void 0 : options.spec); | ||
@@ -77,6 +80,2 @@ this.withMutation(s => { | ||
_typeCheck(_value) { | ||
return true; | ||
} | ||
clone(spec) { | ||
@@ -93,2 +92,3 @@ if (this._mutate) { | ||
next.type = this.type; | ||
next._typeCheck = this._typeCheck; | ||
next._whitelist = this._whitelist.clone(); | ||
@@ -180,7 +180,3 @@ next._blacklist = this._blacklist.clone(); | ||
/** | ||
* | ||
* @param {*} value | ||
* @param {Object} options | ||
* @param {*=} options.parent | ||
* @param {*=} options.context | ||
* Run the configured transform pipeline over an input value. | ||
*/ | ||
@@ -502,3 +498,3 @@ | ||
}); | ||
next.conditions.push(new _Condition.default(deps, options)); | ||
next.conditions.push(typeof options === 'function' ? new _Condition.default(deps, options) : _Condition.default.fromOptions(deps, options)); | ||
return next; | ||
@@ -578,3 +574,3 @@ } | ||
return next; | ||
} //BaseSchema<TType, SetFlag<TFlags, 's'>> | ||
} //Schema<TType, SetFlag<TFlags, 's'>> | ||
@@ -620,7 +616,7 @@ | ||
exports.default = BaseSchema; | ||
exports.default = Schema; | ||
// @ts-expect-error | ||
BaseSchema.prototype.__isYupSchema__ = true; | ||
Schema.prototype.__isYupSchema__ = true; | ||
for (const method of ['validate', 'validateSync']) BaseSchema.prototype[`${method}At`] = function (path, value, options = {}) { | ||
for (const method of ['validate', 'validateSync']) Schema.prototype[`${method}At`] = function (path, value, options = {}) { | ||
const { | ||
@@ -637,4 +633,4 @@ parent, | ||
for (const alias of ['equals', 'is']) BaseSchema.prototype[alias] = BaseSchema.prototype.oneOf; | ||
for (const alias of ['equals', 'is']) Schema.prototype[alias] = Schema.prototype.oneOf; | ||
for (const alias of ['not', 'nope']) BaseSchema.prototype[alias] = BaseSchema.prototype.notOneOf; | ||
for (const alias of ['not', 'nope']) Schema.prototype[alias] = Schema.prototype.notOneOf; |
@@ -5,3 +5,3 @@ import { MixedLocale } from './locale'; | ||
import type { Concat, Defined, Flags, NotNull, SetFlag, Thunk, ToggleDefault, UnsetFlag } from './util/types'; | ||
import BaseSchema from './schema'; | ||
import Schema from './schema'; | ||
export declare type MatchOptions = { | ||
@@ -20,5 +20,4 @@ excludeEmptyString?: boolean; | ||
export { create }; | ||
export default class StringSchema<TType extends Maybe<string> = string | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends BaseSchema<TType, TContext, TDefault, TFlags> { | ||
export default class StringSchema<TType extends Maybe<string> = string | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends Schema<TType, TContext, TDefault, TFlags> { | ||
constructor(); | ||
protected _typeCheck(value: any): value is NonNullable<TType>; | ||
protected _isPresent(value: any): boolean; | ||
@@ -49,3 +48,3 @@ length(length: number | Reference<number>, message?: Message<{ | ||
} | ||
export default interface StringSchema<TType extends Maybe<string> = string | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends BaseSchema<TType, TContext, TDefault, TFlags> { | ||
export default interface StringSchema<TType extends Maybe<string> = string | undefined, TContext = AnyObject, TDefault = undefined, TFlags extends Flags = ''> extends Schema<TType, TContext, TDefault, TFlags> { | ||
default<D extends Maybe<TType>>(def: Thunk<D>): StringSchema<TType, TContext, D, ToggleDefault<TFlags, D>>; | ||
@@ -52,0 +51,0 @@ oneOf<U extends TType>(arrayOfValues: ReadonlyArray<U | Reference>, message?: MixedLocale['oneOf']): StringSchema<U | Optionals<TType>, TContext, TDefault, TFlags>; |
@@ -35,9 +35,17 @@ "use strict"; | ||
super({ | ||
type: 'string' | ||
type: 'string', | ||
check(value) { | ||
if (value instanceof String) value = value.valueOf(); | ||
return typeof value === 'string'; | ||
} | ||
}); | ||
this.withMutation(() => { | ||
this.transform(function (value) { | ||
if (this.isType(value)) return value; | ||
this.transform((value, _raw, ctx) => { | ||
if (!ctx.spec.coarce || ctx.isType(value)) return value; // don't ever convert arrays | ||
if (Array.isArray(value)) return value; | ||
const strValue = value != null && value.toString ? value.toString() : value; | ||
const strValue = value != null && value.toString ? value.toString() : value; // no one wants plain objects converted to [Object object] | ||
if (strValue === objStringTag) return value; | ||
@@ -49,7 +57,2 @@ return strValue; | ||
_typeCheck(value) { | ||
if (value instanceof String) value = value.valueOf(); | ||
return typeof value === 'string'; | ||
} | ||
_isPresent(value) { | ||
@@ -56,0 +59,0 @@ return super._isPresent(value) && !!value.length; |
@@ -15,2 +15,3 @@ import ValidationError from '../ValidationError'; | ||
options: ValidateOptions<TContext>; | ||
originalValue: any; | ||
parent: any; | ||
@@ -17,0 +18,0 @@ from?: Array<{ |
@@ -19,2 +19,5 @@ import type Reference from '../Reference'; | ||
} & U) | Optionals<T>; | ||
export declare type ConcatObjectTypes<T extends Maybe<AnyObject>, U extends Maybe<AnyObject>> = ({ | ||
[P in keyof T]: P extends keyof NonNullable<U> ? NonNullable<U>[P] : T[P]; | ||
} & U) | Optionals<U>; | ||
export declare type PartialDeep<T> = T extends string | number | bigint | boolean | null | undefined | symbol | Date ? T | undefined : T extends Array<infer ArrayType> ? Array<PartialDeep<ArrayType>> : T extends ReadonlyArray<infer ArrayType> ? ReadonlyArray<ArrayType> : { | ||
@@ -21,0 +24,0 @@ [K in keyof T]?: PartialDeep<T[K]>; |
@@ -9,3 +9,3 @@ import Reference from '../Reference'; | ||
toArray(): unknown[]; | ||
resolveAll(resolve: (v: unknown) => unknown): unknown; | ||
resolveAll(resolve: (v: unknown) => unknown): unknown[]; | ||
add(value: unknown): void; | ||
@@ -12,0 +12,0 @@ delete(value: unknown): void; |
import ValidationError from '../ValidationError'; | ||
export default function sortByKeyOrder(keys: string[]): (a: ValidationError, b: ValidationError) => number; | ||
export default function sortByKeyOrder(keys: readonly string[]): (a: ValidationError, b: ValidationError) => number; |
@@ -1,1 +0,1 @@ | ||
export default function toArray<T>(value?: null | T | T[]): T[]; | ||
export default function toArray<T>(value?: null | T | readonly T[]): T[]; |
@@ -11,4 +11,4 @@ declare type Params = Record<string, unknown>; | ||
static isError(err: any): err is ValidationError; | ||
constructor(errorOrErrors: string | ValidationError | ValidationError[], value?: any, field?: string, type?: string); | ||
constructor(errorOrErrors: string | ValidationError | readonly ValidationError[], value?: any, field?: string, type?: string); | ||
} | ||
export {}; |
{ | ||
"name": "yup", | ||
"version": "1.0.0-alpha.3", | ||
"version": "1.0.0-alpha.4", | ||
"description": "Dead simple Object schema validation", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
983
README.md
# Yup | ||
Yup is a JavaScript schema builder for value parsing and validation. Define a schema, transform a value to match, validate the shape of an existing value, or both. Yup schema are extremely expressive and allow modeling complex, interdependent validations, or value transformations. | ||
Yup is a schema builder for runtime value parsing and validation. Define a schema, transform a value to match, assert the shape of an existing value, or both. Yup schema are extremely expressive and allow modeling complex, interdependent validations, or value transformation. | ||
Yup's API is heavily inspired by [Joi](https://github.com/hapijs/joi), but leaner and built with client-side validation as its primary use-case. Yup separates the parsing and validating functions into separate steps. `cast()` transforms data while `validate` checks that the input is the correct shape. Each can be performed together (such as HTML form validation) or seperately (such as deserializing trusted data from APIs). | ||
**Killer Features**: | ||
## Docs | ||
- Concise yet expressive schema interface, equipped to model simple to complex data models | ||
- Powerful TypeScript support. Infer static types from schema, or ensure schema correctly implement a type | ||
- Built-in async validation support. Model server-side and client-side validation equally well | ||
- Extensible: add your own type-safe methods and schema | ||
- Rich error details, make debugging a breeze | ||
- [API](#api) | ||
- [Extending yup](docs/extending.md) | ||
- [TypeScript support](docs/typescript.md) | ||
- [Playground](https://runkit.com/jquense/yup#) | ||
## Getting Started | ||
## Install | ||
Schema are comprised of parsing actions (transforms) as well as assertions (tests) about the input value. | ||
Validate an input value to parse it and run the configured set of assertions. Chain together methods to build a schema. | ||
```sh | ||
npm install -S yup | ||
``` | ||
```ts | ||
import { object, string, string, date, InferType } from 'yup'; | ||
Yup always relies on the `Promise` global object to handle asynchronous values as well as `Set` and `Map`. | ||
For browsers that do not support these, you'll need to include a polyfill, such as core-js: | ||
let userSchema = object({ | ||
name: string().required(), | ||
age: number().required().positive().integer(), | ||
email: string().email(), | ||
website: string().url().nullable(), | ||
createdOn: date().default(() => new Date()), | ||
}); | ||
```js | ||
import 'core-js/es6/promise'; | ||
import 'core-js/es6/set'; | ||
import 'core-js/es6/map'; | ||
// parse and assert validity | ||
const user = await userSchema.validate(await fetchUser()); | ||
type User = InferType<typeof userSchema>; | ||
/* { | ||
name: string; | ||
age: number; | ||
email?: string | undefined | ||
website?: string | null | undefined | ||
createdOn: Date | ||
}*/ | ||
``` | ||
## Usage | ||
Use a schema to coerce or "cast" an input value into the correct type, and optionally | ||
transform that value into more concrete and specific values, without making further assertions. | ||
You define and create schema objects. Schema objects are immutable, so each call of a method returns a _new_ schema object. When using es module syntax, yup exports everything as a named export | ||
```js | ||
import * as yup from 'yup'; | ||
let schema = yup.object().shape({ | ||
name: yup.string().required(), | ||
age: yup.number().required().positive().integer(), | ||
email: yup.string().email(), | ||
website: yup.string().url(), | ||
createdOn: yup.date().default(function () { | ||
return new Date(); | ||
}), | ||
}); | ||
// check validity | ||
schema | ||
.isValid({ | ||
name: 'jimmy', | ||
age: 24, | ||
}) | ||
.then(function (valid) { | ||
valid; // => true | ||
}); | ||
// you can try and type cast objects to the defined schema | ||
schema.cast({ | ||
```ts | ||
// Attempts to coarce values to the correct type | ||
const parsedUser = userSchema.cast({ | ||
name: 'jimmy', | ||
@@ -62,6 +52,22 @@ age: '24', | ||
}); | ||
// => { name: 'jimmy', age: 24, createdOn: Date } | ||
// ✅ { name: 'jimmy', age: 24, createdOn: Date } | ||
``` | ||
The exported functions are factory methods for constructing schema instances, but without the `new` keyword. | ||
Know that your input value is already parsed? You can "strictly" validate an input, and avoid the overhead | ||
of running parsing logic. | ||
```ts | ||
// ❌ ValidationError "age is not a number" | ||
const parsedUser = await userSchema.validate( | ||
{ | ||
name: 'jimmy', | ||
age: '24', | ||
}, | ||
{ strict: true }, | ||
); | ||
``` | ||
## Table of Contents | ||
<!-- The exported functions are factory methods for constructing schema instances, but without the `new` keyword. | ||
If you need access to the actual schema classes, they are also exported: | ||
@@ -79,9 +85,298 @@ | ||
} from 'yup'; | ||
``` --> | ||
<!-- START doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> | ||
- [Schema basics](#schema-basics) | ||
- [Parsing: Transforms](#parsing-transforms) | ||
- [Validation: Tests](#validation-tests) | ||
- [Composition and Reuse](#composition-and-reuse) | ||
- [TypeScript integration](#typescript-integration) | ||
- [Schema defaults](#schema-defaults) | ||
- [Ensuring a schema matches an existing type](#ensuring-a-schema-matches-an-existing-type) | ||
- [Extending built-in schema with new methods](#extending-built-in-schema-with-new-methods) | ||
- [TypeScript configuration](#typescript-configuration) | ||
- [Error message customization](#error-message-customization) | ||
- [localization and i18n](#localization-and-i18n) | ||
- [API](#api) | ||
- [`yup`](#yup) | ||
- [`reach(schema: Schema, path: string, value?: object, context?: object): Schema`](#reachschema-schema-path-string-value-object-context-object-schema) | ||
- [`addMethod(schemaType: Schema, name: string, method: ()=> Schema): void`](#addmethodschematype-schema-name-string-method--schema-void) | ||
- [`ref(path: string, options: { contextPrefix: string }): Ref`](#refpath-string-options--contextprefix-string--ref) | ||
- [`lazy((value: any) => Schema): Lazy`](#lazyvalue-any--schema-lazy) | ||
- [`ValidationError(errors: string | Array<string>, value: any, path: string)`](#validationerrorerrors-string--arraystring-value-any-path-string) | ||
- [`Schema`](#schema) | ||
- [`Schema.clone(): Schema`](#schemaclone-schema) | ||
- [`Schema.label(label: string): Schema`](#schemalabellabel-string-schema) | ||
- [`Schema.meta(metadata: object): Schema`](#schemametametadata-object-schema) | ||
- [`Schema.describe(options?: ResolveOptions): SchemaDescription`](#schemadescribeoptions-resolveoptions-schemadescription) | ||
- [`Schema.concat(schema: Schema): Schema`](#schemaconcatschema-schema-schema) | ||
- [`Schema.validate(value: any, options?: object): Promise<InferType<Schema>, ValidationError>`](#schemavalidatevalue-any-options-object-promiseinfertypeschema-validationerror) | ||
- [`Schema.validateSync(value: any, options?: object): InferType<Schema>`](#schemavalidatesyncvalue-any-options-object-infertypeschema) | ||
- [`Schema.validateAt(path: string, value: any, options?: object): Promise<InferType<Schema>, ValidationError>`](#schemavalidateatpath-string-value-any-options-object-promiseinfertypeschema-validationerror) | ||
- [`Schema.validateSyncAt(path: string, value: any, options?: object): InferType<Schema>`](#schemavalidatesyncatpath-string-value-any-options-object-infertypeschema) | ||
- [`Schema.isValid(value: any, options?: object): Promise<boolean>`](#schemaisvalidvalue-any-options-object-promiseboolean) | ||
- [`Schema.isValidSync(value: any, options?: object): boolean`](#schemaisvalidsyncvalue-any-options-object-boolean) | ||
- [`Schema.cast(value: any, options = {}): InferType<Schema>`](#schemacastvalue-any-options---infertypeschema) | ||
- [`Schema.isType(value: any): value is InferType<Schema>`](#schemaistypevalue-any-value-is-infertypeschema) | ||
- [`Schema.strict(enabled: boolean = false): Schema`](#schemastrictenabled-boolean--false-schema) | ||
- [`Schema.strip(enabled: boolean = true): Schema`](#schemastripenabled-boolean--true-schema) | ||
- [`Schema.withMutation(builder: (current: Schema) => void): void`](#schemawithmutationbuilder-current-schema--void-void) | ||
- [`Schema.default(value: any): Schema`](#schemadefaultvalue-any-schema) | ||
- [`Schema.getDefault(options?: object): Any`](#schemagetdefaultoptions-object-any) | ||
- [`Schema.nullable(): Schema`](#schemanullable-schema) | ||
- [`Schema.nonNullable(): Schema`](#schemanonnullable-schema) | ||
- [`Schema.defined(): Schema`](#schemadefined-schema) | ||
- [`Schema.optional(): Schema`](#schemaoptional-schema) | ||
- [`Schema.required(message?: string | function): Schema`](#schemarequiredmessage-string--function-schema) | ||
- [`Schema.notRequired(): Schema` Alias: `optional()`](#schemanotrequired-schema-alias-optional) | ||
- [`Schema.typeError(message: string): Schema`](#schematypeerrormessage-string-schema) | ||
- [`Schema.oneOf(arrayOfValues: Array<any>, message?: string | function): Schema` Alias: `equals`](#schemaoneofarrayofvalues-arrayany-message-string--function-schema-alias-equals) | ||
- [`Schema.notOneOf(arrayOfValues: Array<any>, message?: string | function)`](#schemanotoneofarrayofvalues-arrayany-message-string--function) | ||
- [`Schema.when(keys: string | string[], builder: object | (values: any[], schema) => Schema): Schema`](#schemawhenkeys-string--string-builder-object--values-any-schema--schema-schema) | ||
- [`Schema.test(name: string, message: string | function | any, test: function): Schema`](#schematestname-string-message-string--function--any-test-function-schema) | ||
- [`Schema.test(options: object): Schema`](#schematestoptions-object-schema) | ||
- [`Schema.transform((currentValue: any, originalValue: any) => any): Schema`](#schematransformcurrentvalue-any-originalvalue-any--any-schema) | ||
- [mixed](#mixed) | ||
- [string](#string) | ||
- [`string.required(message?: string | function): Schema`](#stringrequiredmessage-string--function-schema) | ||
- [`string.length(limit: number | Ref, message?: string | function): Schema`](#stringlengthlimit-number--ref-message-string--function-schema) | ||
- [`string.min(limit: number | Ref, message?: string | function): Schema`](#stringminlimit-number--ref-message-string--function-schema) | ||
- [`string.max(limit: number | Ref, message?: string | function): Schema`](#stringmaxlimit-number--ref-message-string--function-schema) | ||
- [`string.matches(regex: Regex, message?: string | function): Schema`](#stringmatchesregex-regex-message-string--function-schema) | ||
- [`string.matches(regex: Regex, options: { message: string, excludeEmptyString: bool }): Schema`](#stringmatchesregex-regex-options--message-string-excludeemptystring-bool--schema) | ||
- [`string.email(message?: string | function): Schema`](#stringemailmessage-string--function-schema) | ||
- [`string.url(message?: string | function): Schema`](#stringurlmessage-string--function-schema) | ||
- [`string.uuid(message?: string | function): Schema`](#stringuuidmessage-string--function-schema) | ||
- [`string.ensure(): Schema`](#stringensure-schema) | ||
- [`string.trim(message?: string | function): Schema`](#stringtrimmessage-string--function-schema) | ||
- [`string.lowercase(message?: string | function): Schema`](#stringlowercasemessage-string--function-schema) | ||
- [`string.uppercase(message?: string | function): Schema`](#stringuppercasemessage-string--function-schema) | ||
- [number](#number) | ||
- [`number.min(limit: number | Ref, message?: string | function): Schema`](#numberminlimit-number--ref-message-string--function-schema) | ||
- [`number.max(limit: number | Ref, message?: string | function): Schema`](#numbermaxlimit-number--ref-message-string--function-schema) | ||
- [`number.lessThan(max: number | Ref, message?: string | function): Schema`](#numberlessthanmax-number--ref-message-string--function-schema) | ||
- [`number.moreThan(min: number | Ref, message?: string | function): Schema`](#numbermorethanmin-number--ref-message-string--function-schema) | ||
- [`number.positive(message?: string | function): Schema`](#numberpositivemessage-string--function-schema) | ||
- [`number.negative(message?: string | function): Schema`](#numbernegativemessage-string--function-schema) | ||
- [`number.integer(message?: string | function): Schema`](#numberintegermessage-string--function-schema) | ||
- [`number.truncate(): Schema`](#numbertruncate-schema) | ||
- [`number.round(type: 'floor' | 'ceil' | 'trunc' | 'round' = 'round'): Schema`](#numberroundtype-floor--ceil--trunc--round--round-schema) | ||
- [boolean](#boolean) | ||
- [date](#date) | ||
- [`date.min(limit: Date | string | Ref, message?: string | function): Schema`](#dateminlimit-date--string--ref-message-string--function-schema) | ||
- [`date.max(limit: Date | string | Ref, message?: string | function): Schema`](#datemaxlimit-date--string--ref-message-string--function-schema) | ||
- [array](#array) | ||
- [`array.of(type: Schema): Schema`](#arrayoftype-schema-schema) | ||
- [`array.length(length: number | Ref, message?: string | function): Schema`](#arraylengthlength-number--ref-message-string--function-schema) | ||
- [`array.min(limit: number | Ref, message?: string | function): Schema`](#arrayminlimit-number--ref-message-string--function-schema) | ||
- [`array.max(limit: number | Ref, message?: string | function): Schema`](#arraymaxlimit-number--ref-message-string--function-schema) | ||
- [`array.ensure(): Schema`](#arrayensure-schema) | ||
- [`array.compact(rejector: (value) => boolean): Schema`](#arraycompactrejector-value--boolean-schema) | ||
- [object](#object) | ||
- [Object schema defaults](#object-schema-defaults) | ||
- [`object.shape(fields: object, noSortEdges?: Array<[string, string]>): Schema`](#objectshapefields-object-nosortedges-arraystring-string-schema) | ||
- [`object.concat(schemaB: ObjectSchema): ObjectSchema`](#objectconcatschemab-objectschema-objectschema) | ||
- [`object.pick(keys: string[]): Schema`](#objectpickkeys-string-schema) | ||
- [`object.omit(keys: string[]): Schema`](#objectomitkeys-string-schema) | ||
- [`object.from(fromKey: string, toKey: string, alias: boolean = false): this`](#objectfromfromkey-string-tokey-string-alias-boolean--false-this) | ||
- [`object.noUnknown(onlyKnownKeys: boolean = true, message?: string | function): Schema`](#objectnounknownonlyknownkeys-boolean--true-message-string--function-schema) | ||
- [`object.camelCase(): Schema`](#objectcamelcase-schema) | ||
- [`object.constantCase(): Schema`](#objectconstantcase-schema) | ||
<!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
## Schema basics | ||
Schema definitions, are comprised of parsing "transforms" which manipulate inputs into the desired shape and type, "tests", which make assertions over parsed data. Schema also store a bunch of "metadata", details about the schema itself, which can be used to improve error messages, build tools that dynamically consume schema, or serialize schema into another format. | ||
In order to be maximally flexible yup allows running both parsing and assertions separately to match specific needs | ||
### Parsing: Transforms | ||
Each built-in type implements basic type parsing, which comes in handy when parsing serialized data, such as JSON. | ||
Additionally types implement type specific transforms that can be enabled. | ||
```ts | ||
const num = number().cast('1'); // 1 | ||
const obj = object({ | ||
firstName: string().lowercase().trim(), | ||
}) | ||
.camelCase() | ||
.cast('{"first_name": "jAnE "}'); // { firstName: 'jane' } | ||
``` | ||
> If you're looking for an easily serializable DSL for yup schema, check out [yup-ast](https://github.com/WASD-Team/yup-ast) | ||
Custom transforms can be added | ||
### Using a custom locale dictionary | ||
```ts | ||
const reversedString = string() | ||
.transform((currentValue) => currentValue.split('').reverse().join('')) | ||
.cast('dlrow olleh'); // "hello world" | ||
``` | ||
Allows you to customize the default messages used by Yup, when no message is provided with a validation test. | ||
Transforms form a "pipeline", where the value of a previous transform is piped into the next one. | ||
If the end value is `undefined` yup will apply the schema default if it's configured. | ||
> Watch out! values are not guaranteed to be valid types in tranform functions. Previous transforms | ||
> may have failed. For example a number transform may be receive the input value, `NaN`, or a number. | ||
### Validation: Tests | ||
yup has robust support for assertions, or "tests", over input values. Tests check that inputs conform to some | ||
criteria. Tests are distinct from transforms, in that they do not change or alter the input (or its type) | ||
and are usually reserved for checks that are hard, if not impossible, to represent in static types. | ||
```ts | ||
string() | ||
.min(3, 'must be at least 3 characters long') | ||
.email('must be a valid email') | ||
.validate('no'); // ValidationError | ||
``` | ||
As with transforms, tests can be customized on the fly | ||
```ts | ||
const jamesSchema = string().test( | ||
'is-james', | ||
(d) => `${d.path} is not James`, | ||
(value) => value == null || value === 'James', | ||
); | ||
jamesSchema.validateSync('James'); // "James" | ||
jamesSchema.validateSync('Jane'); // ValidationError "this is not James" | ||
``` | ||
> Heads up: unlike transforms, `value` in a custom test is guaranteed to be the correct type | ||
> (in this case an optional string). It still may be `undefined` or `null` depending on your schema | ||
> in those cases, you may want to return `true` for absent values unless your transform, makes presence | ||
> related assertions | ||
### Composition and Reuse | ||
Schema are immutable, each method call returns a new schema object. Reuse and pass them around without | ||
fear of mutating another instance. | ||
```ts | ||
const optionalString = string().optional(); | ||
const definedString = optionalString.defined(); | ||
const value = undefined; | ||
optionalString.isValid(value); // true | ||
definedString.isValid(value); // false | ||
``` | ||
## TypeScript integration | ||
Yup schema produce, static TypeScript interfaces. Use `InferType` to extract that interface: | ||
```ts | ||
import * as yup from 'yup'; | ||
const personSchema = yup.object({ | ||
firstName: yup.string().defined(), | ||
nickName: yup.string().default('').nullable(), | ||
sex: yup | ||
.mixed() | ||
.oneOf(['male', 'female', 'other'] as const) | ||
.defined(), | ||
email: yup.string().nullable().email(), | ||
birthDate: yup.date().nullable().min(new Date(1900, 0, 1)), | ||
}); | ||
interface Person extends yup.InferType<typeof personSchema> {} | ||
``` | ||
### Schema defaults | ||
a schema's default is used when casting produces an `undefined` putput value. Because of this, | ||
setting a default affects the output type of the schema, effectively marking it as "defined()". | ||
```ts | ||
import { string } from 'yup'; | ||
const value: string = string().default('hi').validate(undefined); | ||
// vs | ||
const value: string | undefined = string().validate(undefined); | ||
``` | ||
### Ensuring a schema matches an existing type | ||
In some cases, the TypeScript type already exists, and you want to ensure that | ||
your schema produces a compatible type: | ||
```ts | ||
import { object, number string, ObjectSchema } from 'yup'; | ||
interface Person { | ||
name: string; | ||
age?: number; | ||
sex: 'male' | 'female' | 'other' | null; | ||
} | ||
// will raise a compile-time type error if the schema does not produce a valid Person | ||
const schema: ObjectSchema<Person> = object({ | ||
name: string().defined(), | ||
age: number().optional(), | ||
sex: string<'male' | 'female' | 'other'>().nullable().defined(); | ||
}); | ||
// ❌ errors: | ||
// "Type 'number | undefined' is not assignable to type 'string'." | ||
const badSchema: ObjectSchema<Person> = object({ | ||
name: number(), | ||
}); | ||
``` | ||
### Extending built-in schema with new methods | ||
You can use TypeScript's interface merging behavior to extend the schema types | ||
if needed. Type extensions should go in an "ambient" type definition file such as your | ||
`globals.d.ts`. Remember to actually extend the yup type in your application code! | ||
> Watch out! merging only works if the type definition is _exactly_ the same, including | ||
> generics. Consult the yup source code for each type to ensure you are defining it correctly | ||
```ts | ||
// globals.d.ts | ||
declare module 'yup' { | ||
interface StringSchema<TType, TContext, TDefault, TFlags> { | ||
append(appendStr: string): this; | ||
} | ||
} | ||
// app.ts | ||
import { addMethod, string } from 'yup'; | ||
addMethod(string, 'append', function append(appendStr: string) { | ||
return this.transform((value) => `${value}${appendStr}`); | ||
}); | ||
string().append('~~~~').cast('hi'); // 'hi~~~~' | ||
``` | ||
### TypeScript configuration | ||
You **must** have the `strictNullChecks` compiler option enabled for type inference to work. | ||
We also recommend settings `strictFunctionTypes` to `false`, for functionally better types. Yes | ||
this reduces overall soundness, however TypeScript already disables this check | ||
anyway for methods and constructors (note from TS docs): | ||
> During development of this feature, we discovered a large number of inherently | ||
> unsafe class hierarchies, including some in the DOM. Because of this, | ||
> the setting only applies to functions written in function syntax, not to those in method syntax: | ||
Your mileage will vary, but we've found that this check doesn't prevent many of | ||
real bugs, while increasing the amount of onerous explicit type casting in apps. | ||
## Error message customization | ||
Default error messages can be customized for when no message is provided with a validation test. | ||
If any message is missing in the custom dictionary the error message will default to Yup's one. | ||
@@ -107,10 +402,14 @@ | ||
schema.validate({ name: 'jimmy', age: 11 }).catch(function (err) { | ||
try { | ||
await schema.validate({ name: 'jimmy', age: 11 }); | ||
} catch (err) { | ||
err.name; // => 'ValidationError' | ||
err.errors; // => ['Deve ser maior que 18'] | ||
}); | ||
} | ||
``` | ||
If you need multi-language support, Yup has got you covered. The function `setLocale` accepts functions that can be used to generate error objects with translation keys and values. Just get this output and feed it into your favorite i18n library. | ||
### localization and i18n | ||
If you need multi-language support, yup has got you covered. The function `setLocale` accepts functions that can be used to generate error objects with translation keys and values. These can be fed it into your favorite i18n library. | ||
```js | ||
@@ -131,3 +430,4 @@ import { setLocale } from 'yup'; | ||
// now use Yup schemas AFTER you defined your custom dictionary | ||
// ... | ||
let schema = yup.object().shape({ | ||
@@ -138,6 +438,7 @@ name: yup.string(), | ||
schema.validate({ name: 'jimmy', age: 11 }).catch(function (err) { | ||
err.name; // => 'ValidationError' | ||
err.errors; // => [{ key: 'field_too_short', values: { min: 18 } }] | ||
}); | ||
try { | ||
await schema.validate({ name: 'jimmy', age: 11 }); | ||
} catch (err) { | ||
messages = err.errors.map((err) => i18next.t(err.key)); | ||
} | ||
``` | ||
@@ -147,89 +448,2 @@ | ||
<!-- START doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> | ||
- [`yup`](#yup) | ||
- [`yup.reach(schema: Schema, path: string, value?: object, context?: object): Schema`](#yupreachschema-schema-path-string-value-object-context-object-schema) | ||
- [`yup.addMethod(schemaType: Schema, name: string, method: ()=> Schema): void`](#yupaddmethodschematype-schema-name-string-method--schema-void) | ||
- [`yup.ref(path: string, options: { contextPrefix: string }): Ref`](#yuprefpath-string-options--contextprefix-string--ref) | ||
- [`yup.lazy((value: any) => Schema): Lazy`](#yuplazyvalue-any--schema-lazy) | ||
- [`ValidationError(errors: string | Array<string>, value: any, path: string)`](#validationerrorerrors-string--arraystring-value-any-path-string) | ||
- [mixed](#mixed) | ||
- [`mixed.clone(): Schema`](#mixedclone-schema) | ||
- [`mixed.label(label: string): Schema`](#mixedlabellabel-string-schema) | ||
- [`mixed.meta(metadata: object): Schema`](#mixedmetametadata-object-schema) | ||
- [`mixed.describe(): SchemaDescription`](#mixeddescribe-schemadescription) | ||
- [`mixed.concat(schema: Schema): Schema`](#mixedconcatschema-schema-schema) | ||
- [`mixed.validate(value: any, options?: object): Promise<any, ValidationError>`](#mixedvalidatevalue-any-options-object-promiseany-validationerror) | ||
- [`mixed.validateSync(value: any, options?: object): any`](#mixedvalidatesyncvalue-any-options-object-any) | ||
- [`mixed.validateAt(path: string, value: any, options?: object): Promise<any, ValidationError>`](#mixedvalidateatpath-string-value-any-options-object-promiseany-validationerror) | ||
- [`mixed.validateSyncAt(path: string, value: any, options?: object): any`](#mixedvalidatesyncatpath-string-value-any-options-object-any) | ||
- [`mixed.isValid(value: any, options?: object): Promise<boolean>`](#mixedisvalidvalue-any-options-object-promiseboolean) | ||
- [`mixed.isValidSync(value: any, options?: object): boolean`](#mixedisvalidsyncvalue-any-options-object-boolean) | ||
- [`mixed.cast(value: any, options = {}): any`](#mixedcastvalue-any-options---any) | ||
- [`mixed.isType(value: any): boolean`](#mixedistypevalue-any-boolean) | ||
- [`mixed.strict(isStrict: boolean = false): Schema`](#mixedstrictisstrict-boolean--false-schema) | ||
- [`mixed.strip(stripField: boolean = true): Schema`](#mixedstripstripfield-boolean--true-schema) | ||
- [`mixed.withMutation(builder: (current: Schema) => void): void`](#mixedwithmutationbuilder-current-schema--void-void) | ||
- [`mixed.default(value: any): Schema`](#mixeddefaultvalue-any-schema) | ||
- [`mixed.getDefault(options?: object): Any`](#mixedgetdefaultoptions-object-any) | ||
- [`mixed.nullable(isNullable: boolean = true): Schema`](#mixednullableisnullable-boolean--true-schema) | ||
- [`mixed.required(message?: string | function): Schema`](#mixedrequiredmessage-string--function-schema) | ||
- [`mixed.notRequired(): Schema` Alias: `optional()`](#mixednotrequired-schema-alias-optional) | ||
- [`mixed.defined(): Schema`](#mixeddefined-schema) | ||
- [`mixed.typeError(message: string): Schema`](#mixedtypeerrormessage-string-schema) | ||
- [`mixed.oneOf(arrayOfValues: Array<any>, message?: string | function): Schema` Alias: `equals`](#mixedoneofarrayofvalues-arrayany-message-string--function-schema-alias-equals) | ||
- [`mixed.notOneOf(arrayOfValues: Array<any>, message?: string | function)`](#mixednotoneofarrayofvalues-arrayany-message-string--function) | ||
- [`mixed.when(keys: string | Array<string>, builder: object | (value, schema)=> Schema): Schema`](#mixedwhenkeys-string--arraystring-builder-object--value-schema-schema-schema) | ||
- [`mixed.test(name: string, message: string | function, test: function): Schema`](#mixedtestname-string-message-string--function-test-function-schema) | ||
- [`mixed.test(options: object): Schema`](#mixedtestoptions-object-schema) | ||
- [`mixed.transform((currentValue: any, originalValue: any) => any): Schema`](#mixedtransformcurrentvalue-any-originalvalue-any--any-schema) | ||
- [string](#string) | ||
- [`string.required(message?: string | function): Schema`](#stringrequiredmessage-string--function-schema) | ||
- [`string.length(limit: number | Ref, message?: string | function): Schema`](#stringlengthlimit-number--ref-message-string--function-schema) | ||
- [`string.min(limit: number | Ref, message?: string | function): Schema`](#stringminlimit-number--ref-message-string--function-schema) | ||
- [`string.max(limit: number | Ref, message?: string | function): Schema`](#stringmaxlimit-number--ref-message-string--function-schema) | ||
- [`string.matches(regex: Regex, message?: string | function): Schema`](#stringmatchesregex-regex-message-string--function-schema) | ||
- [`string.matches(regex: Regex, options: { message: string, excludeEmptyString: bool }): Schema`](#stringmatchesregex-regex-options--message-string-excludeemptystring-bool--schema) | ||
- [`string.email(message?: string | function): Schema`](#stringemailmessage-string--function-schema) | ||
- [`string.url(message?: string | function): Schema`](#stringurlmessage-string--function-schema) | ||
- [`string.uuid(message?: string | function): Schema`](#stringuuidmessage-string--function-schema) | ||
- [`string.ensure(): Schema`](#stringensure-schema) | ||
- [`string.trim(message?: string | function): Schema`](#stringtrimmessage-string--function-schema) | ||
- [`string.lowercase(message?: string | function): Schema`](#stringlowercasemessage-string--function-schema) | ||
- [`string.uppercase(message?: string | function): Schema`](#stringuppercasemessage-string--function-schema) | ||
- [number](#number) | ||
- [`number.min(limit: number | Ref, message?: string | function): Schema`](#numberminlimit-number--ref-message-string--function-schema) | ||
- [`number.max(limit: number | Ref, message?: string | function): Schema`](#numbermaxlimit-number--ref-message-string--function-schema) | ||
- [`number.lessThan(max: number | Ref, message?: string | function): Schema`](#numberlessthanmax-number--ref-message-string--function-schema) | ||
- [`number.moreThan(min: number | Ref, message?: string | function): Schema`](#numbermorethanmin-number--ref-message-string--function-schema) | ||
- [`number.positive(message?: string | function): Schema`](#numberpositivemessage-string--function-schema) | ||
- [`number.negative(message?: string | function): Schema`](#numbernegativemessage-string--function-schema) | ||
- [`number.integer(message?: string | function): Schema`](#numberintegermessage-string--function-schema) | ||
- [`number.truncate(): Schema`](#numbertruncate-schema) | ||
- [`number.round(type: 'floor' | 'ceil' | 'trunc' | 'round' = 'round'): Schema`](#numberroundtype-floor--ceil--trunc--round--round-schema) | ||
- [boolean](#boolean) | ||
- [date](#date) | ||
- [`date.min(limit: Date | string | Ref, message?: string | function): Schema`](#dateminlimit-date--string--ref-message-string--function-schema) | ||
- [`date.max(limit: Date | string | Ref, message?: string | function): Schema`](#datemaxlimit-date--string--ref-message-string--function-schema) | ||
- [array](#array) | ||
- [`array.of(type: Schema): Schema`](#arrayoftype-schema-schema) | ||
- [`array.length(length: number | Ref, message?: string | function): Schema`](#arraylengthlength-number--ref-message-string--function-schema) | ||
- [`array.min(limit: number | Ref, message?: string | function): Schema`](#arrayminlimit-number--ref-message-string--function-schema) | ||
- [`array.max(limit: number | Ref, message?: string | function): Schema`](#arraymaxlimit-number--ref-message-string--function-schema) | ||
- [`array.ensure(): Schema`](#arrayensure-schema) | ||
- [`array.compact(rejector: (value) => boolean): Schema`](#arraycompactrejector-value--boolean-schema) | ||
- [object](#object) | ||
- [Object schema defaults](#object-schema-defaults) | ||
- [`object.shape(fields: object, noSortEdges?: Array<[string, string]>): Schema`](#objectshapefields-object-nosortedges-arraystring-string-schema) | ||
- [`object.pick(keys: string[]): Schema`](#objectpickkeys-string-schema) | ||
- [`object.omit(keys: string[]): Schema`](#objectomitkeys-string-schema) | ||
- [`object.getDefaultFromShape(): Record<string, unknown>`](#objectgetdefaultfromshape-recordstring-unknown) | ||
- [`object.from(fromKey: string, toKey: string, alias: boolean = false): this`](#objectfromfromkey-string-tokey-string-alias-boolean--false-this) | ||
- [`object.noUnknown(onlyKnownKeys: boolean = true, message?: string | function): Schema`](#objectnounknownonlyknownkeys-boolean--true-message-string--function-schema) | ||
- [`object.camelCase(): Schema`](#objectcamelcase-schema) | ||
- [`object.constantCase(): Schema`](#objectconstantcase-schema) | ||
<!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
### `yup` | ||
@@ -239,24 +453,36 @@ | ||
```js | ||
let yup = require('yup'); | ||
```ts | ||
// core schema | ||
import { | ||
mixed, | ||
string, | ||
number, | ||
boolean, | ||
bool, | ||
date, | ||
object, | ||
array, | ||
ref, | ||
lazy, | ||
} from 'yup'; | ||
yup.mixed; | ||
yup.string; | ||
yup.number; | ||
yup.boolean; // also aliased as yup.bool | ||
yup.date; | ||
yup.object; | ||
yup.array; | ||
// Classes | ||
import { | ||
Schema, | ||
MixedSchema, | ||
StringSchema, | ||
NumberSchema, | ||
BooleanSchema, | ||
DateSchema, | ||
ArraySchema, | ||
ObjectSchema, | ||
} from 'yup'; | ||
yup.reach; | ||
yup.addMethod; | ||
yup.ref; | ||
yup.lazy; | ||
yup.setLocale; | ||
yup.ValidationError; | ||
// Types | ||
import type { InferType, ISchema, AnySchema, AnyObjectSchema } from 'yup'; | ||
``` | ||
#### `yup.reach(schema: Schema, path: string, value?: object, context?: object): Schema` | ||
#### `reach(schema: Schema, path: string, value?: object, context?: object): Schema` | ||
For nested schemas `yup.reach` will retrieve a nested schema based on the provided path. | ||
For nested schemas, `reach` will retrieve an inner schema based on the provided path. | ||
@@ -267,5 +493,7 @@ For nested schemas that need to resolve dynamically, you can provide a `value` and optionally | ||
```js | ||
let schema = object().shape({ | ||
nested: object().shape({ | ||
arr: array().of(object().shape({ num: number().max(4) })), | ||
import { reach } from 'yup'; | ||
let schema = object({ | ||
nested: object({ | ||
arr: array(object({ num: number().max(4) })), | ||
}), | ||
@@ -280,11 +508,13 @@ }); | ||
#### `yup.addMethod(schemaType: Schema, name: string, method: ()=> Schema): void` | ||
#### `addMethod(schemaType: Schema, name: string, method: ()=> Schema): void` | ||
Adds a new method to the core schema types. A friendlier convenience method for `schemaType.prototype[name] = method`. | ||
```js | ||
yup.addMethod(yup.date, 'format', function (formats, parseStrict) { | ||
return this.transform(function (value, originalValue) { | ||
if (this.isType(value)) return value; | ||
```ts | ||
import { addMethod, date } from 'yup'; | ||
addMethod(date, 'format', function format(formats, parseStrict) { | ||
return this.transform((value, originalValue, ctx) => { | ||
if (ctx.isType(value)) return value; | ||
value = Moment(originalValue, formats, parseStrict); | ||
@@ -297,4 +527,12 @@ | ||
#### `yup.ref(path: string, options: { contextPrefix: string }): Ref` | ||
If you want to add a method to ALL schema types, extend the abstract base class: `Schema` | ||
```ts | ||
import { addMethod, Schema } from 'yup'; | ||
addMethod(Schema, 'myMethod', ...) | ||
``` | ||
#### `ref(path: string, options: { contextPrefix: string }): Ref` | ||
Creates a reference to another sibling or sibling descendant field. Refs are resolved | ||
@@ -305,2 +543,4 @@ at _validation/cast time_ and supported where specified. Refs are evaluated in the proper order so that | ||
```js | ||
import { ref, object, string } from 'yup'; | ||
let schema = object({ | ||
@@ -318,3 +558,3 @@ baz: ref('foo.bar'), | ||
#### `yup.lazy((value: any) => Schema): Lazy` | ||
#### `lazy((value: any) => Schema): Lazy` | ||
@@ -325,3 +565,3 @@ Creates a schema that is evaluated at validation/cast time. Useful for creating | ||
**CAUTION!** When defining parent-child recursive object schema, you want to reset the `default()` | ||
to `undefined` on the child—otherwise the object will infinitely nest itself when you cast it! | ||
to `null` on the child—otherwise the object will infinitely nest itself when you cast it! | ||
@@ -359,23 +599,18 @@ ```js | ||
### mixed | ||
### `Schema` | ||
Creates a schema that matches all types. All types inherit from this base type | ||
`Schema` is the abstract base class that all schema type inherit from. It provides a number of base methods and properties | ||
to all other schema types. | ||
```js | ||
let schema = yup.mixed(); | ||
> Note: unless you are creating a custom schema type, Schema should never be used directly. For unknown/any types use [`mixed()`](#mixed) | ||
schema.isValid(undefined, function (valid) { | ||
valid; // => true | ||
}); | ||
``` | ||
#### `Schema.clone(): Schema` | ||
#### `mixed.clone(): Schema` | ||
Creates a deep copy of the schema. Clone is used internally to return a new schema with every schema state change. | ||
#### `mixed.label(label: string): Schema` | ||
#### `Schema.label(label: string): Schema` | ||
Overrides the key name which is used in error messages. | ||
#### `mixed.meta(metadata: object): Schema` | ||
#### `Schema.meta(metadata: object): Schema` | ||
@@ -385,3 +620,3 @@ Adds to a metadata object, useful for storing data with a schema, that doesn't belong | ||
#### `mixed.describe(): SchemaDescription` | ||
#### `Schema.describe(options?: ResolveOptions): SchemaDescription` | ||
@@ -391,30 +626,101 @@ Collects schema details (like meta, labels, and active tests) into a serializable | ||
```ts | ||
const schema = object({ | ||
name: string().required(), | ||
}); | ||
const description = schema.describe(); | ||
``` | ||
SchemaDescription { | ||
type: string, | ||
label: string, | ||
meta: object, | ||
tests: Array<{ name: string, params: object }> | ||
For schema with dynamic components (references, lazy, or conditions), describe requires | ||
more context to accurately return the schema description. In these cases provide `options` | ||
```ts | ||
import { ref, object, string, boolean } from 'yup'; | ||
let schema = object({ | ||
isBig: boolean(), | ||
count: number().when('isBig', { | ||
is: true, | ||
then: (schema) => schema.min(5), | ||
otherwise: (schema) => schema.min(0), | ||
}), | ||
}); | ||
schema.describe({ value: { isBig: true } }); | ||
``` | ||
And below is are the description types, which differ a bit depending on the schema type. | ||
```ts | ||
interface SchemaDescription { | ||
type: string; | ||
label?: string; | ||
meta: object | undefined; | ||
oneOf: unknown[]; | ||
notOneOf: unknown[]; | ||
nullable: boolean; | ||
optional: boolean; | ||
tests: Array<{ name?: string; params: ExtraParams | undefined }>; | ||
// Present on object schema descriptions | ||
fields: Record<string, SchemaFieldDescription>; | ||
// Present on array schema descriptions | ||
innerType?: SchemaFieldDescription; | ||
} | ||
type SchemaFieldDescription = | ||
| SchemaDescription | ||
| SchemaRefDescription | ||
| SchemaLazyDescription; | ||
interface SchemaRefDescription { | ||
type: 'ref'; | ||
key: string; | ||
} | ||
interface SchemaLazyDescription { | ||
type: string; | ||
label?: string; | ||
meta: object | undefined; | ||
} | ||
``` | ||
#### `mixed.concat(schema: Schema): Schema` | ||
#### `Schema.concat(schema: Schema): Schema` | ||
Creates a new instance of the schema by combining two schemas. Only schemas of the same type can be concatenated. | ||
`concat` is not a "merge" function in the sense that all settings from the provided schema, override ones in the | ||
base, including type, presence and nullability. | ||
#### `mixed.validate(value: any, options?: object): Promise<any, ValidationError>` | ||
```ts | ||
mixed<string>().defined().concat(mixed<number>().nullable()); | ||
Returns the value (a cast value if `isStrict` is `false`) if the value is valid, and returns the errors otherwise. | ||
This method is **asynchronous** and returns a Promise object, that is fulfilled with the value, or rejected | ||
// produces the equivalent to: | ||
mixed<number>().defined().nullable(); | ||
``` | ||
#### `Schema.validate(value: any, options?: object): Promise<InferType<Schema>, ValidationError>` | ||
Returns the parses and validates an input value, returning the parsed value or throwing an error. This method is **asynchronous** and returns a Promise object, that is fulfilled with the value, or rejected | ||
with a `ValidationError`. | ||
The `options` argument is an object hash containing any schema options you may want to override | ||
(or specify for the first time). | ||
```js | ||
value = await schema.validate({ name: 'jimmy', age: 24 }); | ||
``` | ||
Provide `options` to more specifically control the behavior of `validate`. | ||
```js | ||
Options = { | ||
interface Options { | ||
// when true, parsing is skipped an the input is validated "as-is" | ||
strict: boolean = false; | ||
// Throw on the first error or collect and return all | ||
abortEarly: boolean = true; | ||
// Remove unspecified keys from objects | ||
stripUnknown: boolean = false; | ||
// when `false` validations will be preformed shallowly | ||
recursive: boolean = true; | ||
// External values that can be provided to validations and conditionals | ||
context?: object; | ||
@@ -424,23 +730,4 @@ } | ||
- `strict`: only validate the input, and skip any coercion or transformation | ||
- `abortEarly`: return from validation methods on the first error rather | ||
than after all validations run. | ||
- `stripUnknown`: remove unspecified keys from objects. | ||
- `recursive`: when `false` validations will not descend into nested schema | ||
(relevant for objects or arrays). | ||
- `context`: any context needed for validating schema conditions (see: [`when()`](#mixedwhenkeys-string--arraystring-builder-object--value-schema-schema-schema)) | ||
#### `Schema.validateSync(value: any, options?: object): InferType<Schema>` | ||
```js | ||
schema.validate({ name: 'jimmy', age: 24 }).then(function (value) { | ||
value; // => { name: 'jimmy',age: 24 } | ||
}); | ||
schema.validate({ name: 'jimmy', age: 'hi' }).catch(function (err) { | ||
err.name; // => 'ValidationError' | ||
err.errors; // => ['age must be a number'] | ||
}); | ||
``` | ||
#### `mixed.validateSync(value: any, options?: object): any` | ||
Runs validatations synchronously _if possible_ and returns the resulting value, | ||
@@ -472,3 +759,3 @@ or throws a ValidationError. Accepts all the same options as `validate`. | ||
#### `mixed.validateAt(path: string, value: any, options?: object): Promise<any, ValidationError>` | ||
#### `Schema.validateAt(path: string, value: any, options?: object): Promise<InferType<Schema>, ValidationError>` | ||
@@ -487,3 +774,3 @@ Validate a deeply nested path within the schema. Similar to how `reach` works, | ||
is: true, | ||
otherwise: (s) => s.strict(), | ||
otherwise: (schema) => schema.strict(), | ||
}), | ||
@@ -503,7 +790,7 @@ }), | ||
#### `mixed.validateSyncAt(path: string, value: any, options?: object): any` | ||
#### `Schema.validateSyncAt(path: string, value: any, options?: object): InferType<Schema>` | ||
Same as `validateAt` but synchronous. | ||
#### `mixed.isValid(value: any, options?: object): Promise<boolean>` | ||
#### `Schema.isValid(value: any, options?: object): Promise<boolean>` | ||
@@ -515,3 +802,3 @@ Returns `true` when the passed in value matches the schema. `isValid` | ||
#### `mixed.isValidSync(value: any, options?: object): boolean` | ||
#### `Schema.isValidSync(value: any, options?: object): boolean` | ||
@@ -522,3 +809,3 @@ Synchronously returns `true` when the passed in value matches the schema. | ||
#### `mixed.cast(value: any, options = {}): any` | ||
#### `Schema.cast(value: any, options = {}): InferType<Schema>` | ||
@@ -529,6 +816,20 @@ Attempts to coerce the passed in value to a value that matches the schema. For example: `'5'` will | ||
`options` parameter can be an object containing `context`. (For more info on `context` see `mixed.validate`) | ||
Provide `options` to more specifically control the behavior of `validate`. | ||
#### `mixed.isType(value: any): boolean` | ||
```js | ||
interface CastOptions<TContext extends {}> { | ||
// Remove undefined properties from objects | ||
stripUnknown: boolean = false; | ||
// Throws a TypeError if casting doesn't produce a valid type | ||
// note that the TS return type is inaccurate when this is `false`, use with caution | ||
assert?: boolean = true; | ||
// External values that used to resolve conditions and references | ||
context?: TContext; | ||
} | ||
``` | ||
#### `Schema.isType(value: any): value is InferType<Schema>` | ||
Runs a type check against the passed in `value`. It returns true if it matches, | ||
@@ -538,3 +839,3 @@ it does not cast the value. When `nullable()` is set `null` is considered a valid value of the type. | ||
#### `mixed.strict(isStrict: boolean = false): Schema` | ||
#### `Schema.strict(enabled: boolean = false): Schema` | ||
@@ -544,3 +845,3 @@ Sets the `strict` option to `true`. Strict schemas skip coercion and transformation attempts, | ||
#### `mixed.strip(stripField: boolean = true): Schema` | ||
#### `Schema.strip(enabled: boolean = true): Schema` | ||
@@ -558,4 +859,21 @@ Marks a schema to be removed from an output object. Only works as a nested schema. | ||
#### `mixed.withMutation(builder: (current: Schema) => void): void` | ||
Schema with `strip` enabled have an inferred type of `never`, allowing them to be | ||
removed from the overall type: | ||
```ts | ||
let schema = object({ | ||
useThis: number(), | ||
notThis: string().strip(), | ||
}); | ||
InferType<typeof schema>; /* | ||
{ | ||
useThis?: number | undefined | ||
} | ||
*/ | ||
``` | ||
#### `Schema.withMutation(builder: (current: Schema) => void): void` | ||
First the legally required Rich Hickey quote: | ||
@@ -567,6 +885,5 @@ | ||
`withMutation` allows you to mutate the schema in place, instead of the default behavior which clones before each change. | ||
Generally this isn't necessary since the vast majority of schema changes happen during the initial | ||
`withMutation` allows you to mutate the schema in place, instead of the default behavior which clones before each change. Generally this isn't necessary since the vast majority of schema changes happen during the initial | ||
declaration, and only happen once over the lifetime of the schema, so performance isn't an issue. | ||
However certain mutations _do_ occur at cast/validation time, (such as conditional schema using [`when()`](#mixedwhenkeys-string--arraystring-builder-object--value-schema-schema-schema)), or | ||
However certain mutations _do_ occur at cast/validation time, (such as conditional schema using [`when()`](#Schemawhenkeys-string--arraystring-builder-object--value-schema-schema-schema)), or | ||
when instantiating a schema object. | ||
@@ -584,3 +901,3 @@ | ||
#### `mixed.default(value: any): Schema` | ||
#### `Schema.default(value: any): Schema` | ||
@@ -603,33 +920,74 @@ Sets a default value to use when the value is `undefined`. | ||
#### `mixed.getDefault(options?: object): Any` | ||
#### `Schema.getDefault(options?: object): Any` | ||
Retrieve a previously set default value. `getDefault` will resolve any conditions that may alter the default. Optionally pass `options` with `context` (for more info on `context` see `mixed.validate`). | ||
Retrieve a previously set default value. `getDefault` will resolve any conditions that may alter the default. Optionally pass `options` with `context` (for more info on `context` see `Schema.validate`). | ||
#### `mixed.nullable(isNullable: boolean = true): Schema` | ||
#### `Schema.nullable(): Schema` | ||
Indicates that `null` is a valid value for the schema. Without `nullable()` | ||
`null` is treated as a different type and will fail `isType()` checks. | ||
`null` is treated as a different type and will fail `Schema.isType()` checks. | ||
#### `mixed.required(message?: string | function): Schema` | ||
```ts | ||
const schema = number().nullable() | ||
Mark the schema as required, which will not allow `undefined` or `null` as a value. | ||
Note that unless a schema is marked as `nullable()` a `null` value is treated as a type error, not a missing value. Mark a schema as `mixed().nullable().required()` treat `null` as missing. | ||
schema.cast(null); // null | ||
> Watch out! [`string().required`](#stringrequiredmessage-string--function-schema)) works a little | ||
> different and additionally prevents empty string values (`''`) when required. | ||
InferType<typeof schema> // number | null | ||
``` | ||
#### `mixed.notRequired(): Schema` Alias: `optional()` | ||
#### `Schema.nonNullable(): Schema` | ||
Mark the schema as not required. Passing `undefined` (or `null` for nullable schema) as value will not fail validation. | ||
The opposite of `nullable`, removes `null` from valid type values for the schema. | ||
**Schema are non nullable by default**. | ||
#### `mixed.defined(): Schema` | ||
```ts | ||
const schema = number().nonNullable() | ||
schema.cast(null); // TypeError | ||
InferType<typeof schema> // number | ||
``` | ||
#### `Schema.defined(): Schema` | ||
Require a value for the schema. All field values apart from `undefined` meet this requirement. | ||
#### `mixed.typeError(message: string): Schema` | ||
```ts | ||
const schema = string().defined() | ||
schema.cast(undefined); // TypeError | ||
InferType<typeof schema> // string | ||
``` | ||
#### `Schema.optional(): Schema` | ||
The opposite of `defined()` allows `undefined` values for the given type. | ||
```ts | ||
const schema = string().optional() | ||
schema.cast(undefined); // undefined | ||
InferType<typeof schema> // string | undefined | ||
``` | ||
#### `Schema.required(message?: string | function): Schema` | ||
Mark the schema as required, which will not allow `undefined` or `null` as a value. `required` | ||
negates the effects of calling `optional()` and `nullable()` | ||
> Watch out! [`string().required`](#stringrequiredmessage-string--function-schema)) works a little | ||
> different and additionally prevents empty string values (`''`) when required. | ||
#### `Schema.notRequired(): Schema` Alias: `optional()` | ||
Mark the schema as not required. This is a shortcut for `schema.nonNullable().defined()`; | ||
#### `Schema.typeError(message: string): Schema` | ||
Define an error message for failed type checks. The `${value}` and `${type}` interpolation can | ||
be used in the `message` argument. | ||
#### `mixed.oneOf(arrayOfValues: Array<any>, message?: string | function): Schema` Alias: `equals` | ||
#### `Schema.oneOf(arrayOfValues: Array<any>, message?: string | function): Schema` Alias: `equals` | ||
@@ -642,3 +1000,3 @@ Only allow values from set of values. Values added are removed from any `notOneOf` values if present. | ||
Note that `undefined` does not fail this validator, even when `undefined` is not included in `arrayOfValues`. | ||
If you don't want `undefined` to be a valid value, you can use `mixed.required`. | ||
If you don't want `undefined` to be a valid value, you can use `Schema.required`. | ||
@@ -653,3 +1011,3 @@ ```js | ||
#### `mixed.notOneOf(arrayOfValues: Array<any>, message?: string | function)` | ||
#### `Schema.notOneOf(arrayOfValues: Array<any>, message?: string | function)` | ||
@@ -668,3 +1026,3 @@ Disallow values from a set of values. Values added are removed from `oneOf` values if present. | ||
#### `mixed.when(keys: string | Array<string>, builder: object | (value, schema)=> Schema): Schema` | ||
#### `Schema.when(keys: string | string[], builder: object | (values: any[], schema) => Schema): Schema` | ||
@@ -678,5 +1036,7 @@ Adjust the schema based on a sibling or sibling children fields. You can provide an object | ||
Like joi you can also prefix properties with `$` to specify a property that is dependent | ||
on `context` passed in by `validate()` or `isValid`. `when` conditions are additive. | ||
You can also prefix properties with `$` to specify a property that is dependent | ||
on `context` passed in by `validate()` or `cast` instead of the input value. | ||
`when` conditions are additive. | ||
```js | ||
@@ -688,6 +1048,8 @@ let schema = object({ | ||
is: true, // alternatively: (val) => val == true | ||
then: yup.number().min(5), | ||
otherwise: yup.number().min(0), | ||
then: (schema) => schema.min(5), | ||
otherwise: (schema) => schema.min(0), | ||
}) | ||
.when('$other', (other, schema) => (other === 4 ? schema.max(6) : schema)), | ||
.when('$other', ([other], schema) => | ||
other === 4 ? schema.max(6) : schema, | ||
), | ||
}); | ||
@@ -706,4 +1068,4 @@ | ||
is: true, // alternatively: (isBig, isSpecial) => isBig && isSpecial | ||
then: yup.number().min(5), | ||
otherwise: yup.number().min(0), | ||
then: (schema) => schema..min(5), | ||
otherwise: (schema) => schema..min(0), | ||
}), | ||
@@ -719,4 +1081,3 @@ }); | ||
Alternatively you can provide a function that returns a schema | ||
(called with the value of the key and the current schema). | ||
Alternatively you can provide a function that returns a schema, called with an array of values for each provided key the current schema. | ||
@@ -726,3 +1087,3 @@ ```js | ||
isBig: yup.boolean(), | ||
count: yup.number().when('isBig', (isBig, schema) => { | ||
count: yup.number().when('isBig', ([isBig], schema) => { | ||
return isBig ? schema.min(5) : schema.min(0); | ||
@@ -735,3 +1096,3 @@ }), | ||
#### `mixed.test(name: string, message: string | function, test: function): Schema` | ||
#### `Schema.test(name: string, message: string | function | any, test: function): Schema` | ||
@@ -785,3 +1146,3 @@ Adds a test function to the validation chain. Tests are run after any object is cast. | ||
#### `mixed.test(options: object): Schema` | ||
#### `Schema.test(options: object): Schema` | ||
@@ -800,3 +1161,3 @@ Alternative `test(..)` signature. `options` is an object containing some of the following options: | ||
params: ?object; | ||
// mark the test as exclusive, meaning only one of the same can be active at once | ||
// mark the test as exclusive, meaning only one test of the same name can be active at once | ||
exclusive: boolean = false; | ||
@@ -815,3 +1176,3 @@ } | ||
let max = 64; | ||
let schema = yup.mixed().test({ | ||
let schema = yup.string().test({ | ||
name: 'max', | ||
@@ -825,6 +1186,6 @@ exclusive: true, | ||
#### `mixed.transform((currentValue: any, originalValue: any) => any): Schema` | ||
#### `Schema.transform((currentValue: any, originalValue: any) => any): Schema` | ||
Adds a transformation to the transform chain. Transformations are central to the casting process, | ||
default transforms for each type coerce values to the specific type (as verified by [`isType()`](#mixedistypevalue-any-boolean)). transforms are run before validations and only applied when the schema is not marked as `strict` (the default). Some types have built in transformations. | ||
default transforms for each type coerce values to the specific type (as verified by [`isType()`](#Schemaistypevalue-any-boolean)). transforms are run before validations and only applied when the schema is not marked as `strict` (the default). Some types have built in transformations. | ||
@@ -836,3 +1197,3 @@ Transformations are useful for arbitrarily altering how the object is cast, **however, you should take care | ||
```js | ||
let schema = string().transform(function (value, originalvalue) { | ||
let schema = string().transform((value, originalvalue) => { | ||
return this.isType(value) && value !== null ? value.toUpperCase() : value; | ||
@@ -850,5 +1211,5 @@ }); | ||
module.exports = function (formats = 'MMM dd, yyyy') { | ||
return date().transform(function (value, originalValue) { | ||
return date().transform((value, originalValue, context) => { | ||
// check to see if the previous transform already parsed the date | ||
if (this.isType(value)) return value; | ||
if (context.isType(value)) return value; | ||
@@ -864,5 +1225,43 @@ // the default coercion failed so let's try it with Moment.js instead | ||
### mixed | ||
Creates a schema that matches all types, or just the ones you configure. Inherits from [`Schema`](#Schema). | ||
```ts | ||
import { mixed, InferType } from 'yup'; | ||
let schema = mixed(); | ||
schema.validateSync('string'); // 'string'; | ||
schema.validateSync(1); // 1; | ||
schema.validateSync(new Date()); // Date; | ||
InferType<typeof schema> // any | ||
``` | ||
Custom types can be implemented by passing a type check function: | ||
```ts | ||
import { mixed, InferType } from 'yup'; | ||
let objectIdSchema = yup | ||
.mixed((input): input is ObjectId => input instanceof ObjectId) | ||
.transform((value: any, input, ctx) => { | ||
if (ctx.typeCheck(value)) return value; | ||
return new ObjectId(value); | ||
}); | ||
await objectIdSchema.validate(ObjectId('507f1f77bcf86cd799439011')); // ObjectId("507f1f77bcf86cd799439011") | ||
await objectIdSchema.validate('507f1f77bcf86cd799439011'); // ObjectId("507f1f77bcf86cd799439011") | ||
InferType<typeof objectIdSchema> // ObjectId | ||
``` | ||
### string | ||
Define a string schema. Supports all the same methods as [`mixed`](#mixed). | ||
Define a string schema. Inherits from [`Schema`](#Schema). | ||
@@ -952,3 +1351,3 @@ ```js | ||
Define a number schema. Supports all the same methods as [`mixed`](#mixed). | ||
Define a number schema. Inherits from [`Schema`](#Schema). | ||
@@ -1008,3 +1407,3 @@ ```js | ||
Define a boolean schema. Supports all the same methods as [`mixed`](#mixed). | ||
Define a boolean schema. Inherits from [`Schema`](#Schema). | ||
@@ -1021,3 +1420,3 @@ ```js | ||
for more robust parsing options see the extending schema types at the end of the readme. | ||
Supports all the same methods as [`mixed`](#mixed). | ||
Inherits from [`Schema`](#Schema). | ||
@@ -1049,3 +1448,3 @@ ```js | ||
will apply to the elements as well. Options passed into `isValid` are passed also passed to child schemas. | ||
Supports all the same methods as [`mixed`](#mixed). | ||
Inherits from [`Schema`](#Schema). | ||
@@ -1118,6 +1517,6 @@ ```js | ||
Define an object schema. Options passed into `isValid` are also passed to child schemas. | ||
Supports all the same methods as [`mixed`](#mixed). | ||
Inherits from [`Schema`](#Schema). | ||
```js | ||
yup.object().shape({ | ||
yup.object({ | ||
name: string().required(), | ||
@@ -1130,14 +1529,2 @@ age: number().required().positive().integer(), | ||
You can also pass a shape to the object constructor as a convenience. | ||
```js | ||
object().shape({ | ||
num: number(), | ||
}); | ||
// or | ||
object({ | ||
num: number(), | ||
}); | ||
``` | ||
The default `cast` behavior for `object` is: [`JSON.parse`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse) | ||
@@ -1160,3 +1547,3 @@ | ||
This may be a bit suprising, but is generally very helpful since it allows large, nested | ||
This may be a bit suprising, but is usually helpful since it allows large, nested | ||
schema to create default values that fill out the whole shape and not just the root object. There is | ||
@@ -1192,5 +1579,5 @@ one gotcha! though. For nested object schema that are optional but include non optional fields | ||
Note that you can chain `shape` method, which acts like object extends, for example: | ||
Note that you can chain `shape` method, which acts like `Object.assign`. | ||
```js | ||
```ts | ||
object({ | ||
@@ -1207,3 +1594,3 @@ a: string(), | ||
```js | ||
```ts | ||
object({ | ||
@@ -1216,2 +1603,8 @@ a: string(), | ||
#### `object.concat(schemaB: ObjectSchema): ObjectSchema` | ||
Creates a object schema, by applying all settings and fields from `schemaB` to the base, producing a new schema. | ||
The object shape is shallowly merged with common fields from `schemaB` taking precedence over the base | ||
fields. | ||
#### `object.pick(keys: string[]): Schema` | ||
@@ -1247,8 +1640,2 @@ | ||
#### `object.getDefaultFromShape(): Record<string, unknown>` | ||
Produces a default object value by walking the object shape and calling `default()` | ||
on each field. This is the default behavior of `getDefault()` but allows for | ||
building out an object skeleton regardless of the default(). | ||
#### `object.from(fromKey: string, toKey: string, alias: boolean = false): this` | ||
@@ -1255,0 +1642,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
330328
6225
1612