Website : rimsha.abasa.com
backdoor
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
var
/
canvas
/
node_modules
/
superstruct
/
lib
/
Filename :
index.es.js
back
Copy
/** * A `StructFailure` represents a single specific failure in validation. */ /** * `StructError` objects are thrown (or returned) when validation fails. * * Validation logic is design to exit early for maximum performance. The error * represents the first error encountered during validation. For more detail, * the `error.failures` property is a generator function that can be run to * continue validation and receive all the failures in the data. */ class StructError extends TypeError { constructor(failure, moreFailures) { const { message, ...rest } = failure; const { path } = failure; let failures; const msg = path.length === 0 ? message : "At path: " + path.join('.') + " -- " + message; super(msg); Object.assign(this, rest); this.name = this.constructor.name; this.failures = () => { if (!failures) { failures = [failure, ...moreFailures]; } return failures; }; } } /** * Check if a value is a plain object. */ function isPlainObject(value) { if (Object.prototype.toString.call(value) !== '[object Object]') { return false; } const prototype = Object.getPrototypeOf(value); return prototype === null || prototype === Object.prototype; } /** * Return a value as a printable string. */ function print(value) { return typeof value === 'string' ? JSON.stringify(value) : "" + value; } /** * Shifts (removes and returns) the first value from the `input` iterator. * Like `Array.prototype.shift()` but for an `Iterator`. */ function shiftIterator(input) { const { done, value } = input.next(); return done ? undefined : value; } /** * Convert a validation result to an iterable of failures. */ function* toFailures(result, context) { if (typeof result === 'string') { yield context.fail({ message: result }); } else if (result === true) { return; } else if (result === false) { yield context.fail(); } else { yield* result; } } function assign(...Structs) { const schemas = Structs.map(s => s.schema); const schema = Object.assign({}, ...schemas); return object(schema); } /** * Define a new struct type with a custom validation function. */ function define(name, validator) { return new Struct({ type: name, schema: null, validator }); } /** * Create a struct with dynamic, runtime validation. * * The callback will receive the value currently being validated, and must * return a struct object to validate it with. This can be useful to model * validation logic that changes based on its input. */ function dynamic(fn) { return define('dynamic', (value, ctx) => { return ctx.check(value, fn(value, ctx)); }); } /** * Create a struct with lazily evaluated validation. * * The first time validation is run with the struct, the callback will be called * and must return a struct object to use. This is useful for cases where you * want to have self-referential structs for nested data structures to avoid a * circular definition problem. */ function lazy(fn) { let s; return define('lazy', (value, ctx) => { if (!s) { s = fn(); } return ctx.check(value, s); }); } /** * Create a new struct based on an existing object struct, but excluding * specific properties. * * Like TypeScript's `Omit` utility. */ function omit(struct, keys) { const { schema } = struct; const subschema = { ...schema }; for (const key of keys) { delete subschema[key]; } return object(subschema); } /** * Create a new struct based on an existing object struct, but with all of its * properties allowed to be `undefined`. * * Like TypeScript's `Partial` utility. */ function partial(struct) { const schema = struct instanceof Struct ? { ...struct.schema } : { ...struct }; for (const key in schema) { schema[key] = optional(schema[key]); } return object(schema); } /** * Create a new struct based on an existing object struct, but only including * specific properties. * * Like TypeScript's `Pick` utility. */ function pick(struct, keys) { const { schema } = struct; const subschema = {}; for (const key of keys) { subschema[key] = schema[key]; } return object(subschema); } /** * Define a new struct type with a custom validation function. * * @deprecated This function has been renamed to `define`. */ function struct(name, validator) { console.warn('superstruct@0.11 - The `struct` helper has been renamed to `define`.'); return define(name, validator); } /** * Ensure that any value passes validation. */ function any() { return define('any', () => true); } function array(Element) { return new Struct({ type: 'array', schema: Element, coercer: value => { return Element && Array.isArray(value) ? value.map(v => Element.coercer(v)) : value; }, *validator(value, ctx) { if (!Array.isArray(value)) { yield ctx.fail("Expected an array value, but received: " + print(value)); } else if (Element) { for (const [i, v] of value.entries()) { yield* ctx.check(v, Element, value, i); } } } }); } /** * Ensure that a value is a boolean. */ function boolean() { return define('boolean', value => { return typeof value === 'boolean'; }); } /** * Ensure that a value is a valid `Date`. * * Note: this also ensures that the value is *not* an invalid `Date` object, * which can occur when parsing a date fails but still returns a `Date`. */ function date() { return define('date', value => { return value instanceof Date && !isNaN(value.getTime()) || "Expected a valid `Date` object, but received: " + print(value); }); } function enums(values) { const schema = {}; const description = values.map(v => print(v)).join(); for (const key of values) { schema[key] = key; } return new Struct({ type: 'enums', schema, validator: value => { return values.includes(value) || "Expected one of `" + description + "`, but received: " + print(value); } }); } /** * Ensure that a value is a function. */ function func() { return define('func', value => { return typeof value === 'function' || "Expected a function, but received: " + print(value); }); } /** * Ensure that a value is an instance of a specific class. */ function instance(Class) { return define('instance', value => { return value instanceof Class || "Expected a `" + Class.name + "` instance, but received: " + print(value); }); } /** * Ensure that a value is an integer. */ function integer() { return define('integer', value => { return typeof value === 'number' && !isNaN(value) && Number.isInteger(value) || "Expected an integer, but received: " + print(value); }); } function intersection(Structs) { return define('intersection', function* (value, ctx) { for (const S of Structs) { yield* ctx.check(value, S); } }); } function literal(constant) { const description = print(constant); return define('literal', value => { return value === constant || "Expected the literal `" + description + "`, but received: " + print(value); }); } function map(Key, Value) { return define('map', function* (value, ctx) { if (!(value instanceof Map)) { yield ctx.fail("Expected a `Map` object, but received: " + print(value)); } else if (Key && Value) { for (const [k, v] of value.entries()) { yield* ctx.check(k, Key, value, k); yield* ctx.check(v, Value, value, k); } } }); } /** * Ensure that no value ever passes validation. */ function never() { return define('never', () => false); } /** * Augment an existing struct to allow `null` values. */ function nullable(struct) { const { refiner } = struct; return new Struct({ ...struct, validator: (value, ctx) => { return value === null || ctx.check(value, struct); }, refiner: function* (value, ctx) { if (value != null) { const c = { ...ctx, struct }; yield* toFailures(refiner(value, c), c); } } }); } /** * Ensure that a value is a number. */ function number() { return define('number', value => { return typeof value === 'number' && !isNaN(value) || "Expected a number, but received: " + print(value); }); } function object(schema) { const knowns = schema ? Object.keys(schema) : []; const Never = never(); return new Struct({ type: 'object', schema: schema ? schema : null, *validator(value, ctx) { if (typeof value !== 'object' || value == null) { yield ctx.fail("Expected an object, but received: " + print(value)); } else if (schema) { const unknowns = new Set(Object.keys(value)); for (const key of knowns) { unknowns.delete(key); const Value = schema[key]; const v = value[key]; yield* ctx.check(v, Value, value, key); } for (const key of unknowns) { const v = value[key]; yield* ctx.check(v, Never, value, key); } } }, coercer: value => { if (!schema || typeof value !== 'object' || value == null) { return value; } const ret = {}; const unknowns = new Set(Object.keys(value)); for (const key of knowns) { unknowns.delete(key); const Value = schema[key]; const v = value[key]; ret[key] = Value.coercer(v); } for (const key of unknowns) { ret[key] = value[key]; } return ret; } }); } /** * Augment a struct to allow `undefined` values. */ function optional(struct) { const { refiner } = struct; return new Struct({ ...struct, validator: (value, ctx) => { return value === undefined || ctx.check(value, struct); }, refiner: function* (value, ctx) { if (value != null) { const c = { ...ctx, struct }; yield* toFailures(refiner(value, c), c); } } }); } /** * Ensure that a value is an object with keys and values of specific types, but * without ensuring any specific shape of properties. * * Like TypeScript's `Record` utility. */ function record(Key, Value) { return define('record', function* (value, ctx) { if (typeof value !== 'object' || value == null) { yield ctx.fail("Expected an object, but received: " + print(value)); } else { for (const k in value) { const v = value[k]; yield* ctx.check(k, Key, value, k); yield* ctx.check(v, Value, value, k); } } }); } /** * Ensure that a value is a `RegExp`. * * Note: this does not test the value against the regular expression! For that * you need to use the `pattern()` refinement. */ function regexp() { return define('regexp', value => { return value instanceof RegExp; }); } function set(Element) { return define('set', function* (value, ctx) { if (!(value instanceof Set)) { yield ctx.fail("Expected a `Set` object, but received: " + print(value)); } else if (Element) { for (const val of value) { yield* ctx.check(val, Element, value, val); } } }); } /** * Ensure that a value is a string. */ function string() { return define('string', value => { return typeof value === 'string' || "Expected a string, but received: " + print(value); }); } function tuple(Elements) { const Never = never(); return define('tuple', function* (value, ctx) { if (!Array.isArray(value)) { yield ctx.fail("Expected an array, but received: " + print(value)); } else { for (const [index, Element] of Elements.entries()) { const v = value[index]; yield* ctx.check(v, Element, value, index); } if (value.length > Elements.length) { const index = Elements.length; const v = value[index]; yield* ctx.check(v, Never, value, index); } } }); } /** * Ensure that a value has a set of known properties of specific types. * * Note: Unrecognized properties are allowed and untouched. This is similar to * how TypeScript's structural typing works. */ function type(schema) { const keys = Object.keys(schema); return new Struct({ type: 'type', schema, validator: function* (value, ctx) { if (typeof value !== 'object' || value == null) { yield ctx.fail("Expected an object, but received: " + print(value)); } else { for (const key of keys) { const Value = schema[key]; const v = value[key]; yield* ctx.check(v, Value, value, key); } } } }); } function union(Structs) { const description = Structs.map(s => s.type).join(' | '); return define('union', function* (value, ctx) { const failures = []; for (const S of Structs) { const [...array] = ctx.check(value, S); if (array.length === 0) { return; } else { failures.push(...array); } } yield ctx.fail("Expected the value to satisfy a union of `" + description + "`, but received: " + print(value)); yield* failures; }); } /** * Ensure that any value passes validation, without widening its type to `any`. */ function unknown() { return define('unknown', () => true); } /** * Augment a `Struct` to add an additional coercion step to its input. * * This allows you to transform input data before validating it, to increase the * likelihood that it passes validation—for example for default values, parsing * different formats, etc. * * Note: You must use `create(value, Struct)` on the value to have the coercion * take effect! Using simply `assert()` or `is()` will not use coercion. */ function coerce(struct, condition, coercer) { const fn = struct.coercer; return new Struct({ ...struct, coercer: value => { if (is(value, condition)) { return fn(coercer(value)); } else { return fn(value); } } }); } /** * Augment a struct to replace `undefined` values with a default. * * Note: You must use `create(value, Struct)` on the value to have the coercion * take effect! Using simply `assert()` or `is()` will not use coercion. */ function defaulted(S, fallback, options = {}) { const { strict } = options; return coerce(S, unknown(), x => { const f = typeof fallback === 'function' ? fallback() : fallback; if (x === undefined) { return f; } if (!strict && isPlainObject(x) && isPlainObject(f)) { const ret = { ...x }; let changed = false; for (const key in f) { if (ret[key] === undefined) { ret[key] = f[key]; changed = true; } } if (changed) { return ret; } } return x; }); } /** * Augment a struct to mask its input to only properties defined in the struct. * * Note: You must use `create(value, Struct)` on the value to have the coercion * take effect! Using simply `assert()` or `is()` will not use coercion. */ function masked(struct) { return coerce(struct, unknown(), x => { if (typeof struct.schema !== 'object' || struct.schema == null || typeof x !== 'object' || x == null) { return x; } else { const ret = {}; for (const key in struct.schema) { if (key in x) { ret[key] = x[key]; } } return ret; } }); } /** * Augment a struct to trim string inputs. * * Note: You must use `create(value, Struct)` on the value to have the coercion * take effect! Using simply `assert()` or `is()` will not use coercion. */ function trimmed(struct) { return coerce(struct, string(), x => x.trim()); } /** * `Struct` objects encapsulate the validation logic for a specific type of * values. Once constructed, you use the `assert`, `is` or `validate` helpers to * validate unknown input data against the struct. */ class Struct { constructor(props) { this.type = props.type; this.schema = props.schema; this.coercer = props.coercer || (value => value); this.validator = props.validator || (() => []); this.refiner = props.refiner || (() => []); } /** * Assert that a value passes the struct's validation, throwing if it doesn't. */ assert(value) { return assert(value, this); } /** * Create a value with the struct's coercion logic, then validate it. */ create(value) { return create(value, this); } /** * Check if a value passes the struct's validation. */ is(value) { return is(value, this); } /** * Mask a value, coercing and validating it, but returning only the subset of * properties defined by the struct's schema. */ mask(value) { return mask(value, this); } /** * Validate a value with the struct's validation logic, returning a tuple * representing the result. * * You may optionally pass `true` for the `withCoercion` argument to coerce * the value before attempting to validate it. If you do, the result will * contain the coerced result when successful. */ validate(value, options = {}) { return validate(value, this, options); } } /** * Assert that a value passes a `Struct`, throwing if it doesn't. */ function assert(value, struct) { const result = validate(value, struct); if (result[0]) { throw result[0]; } } /** * Create a value with the coercion logic of `Struct` and validate it. */ function create(value, struct) { const ret = struct.coercer(value); assert(ret, struct); return ret; } /** * Mask a value, returning only the subset of properties defined by a Struct. */ function mask(value, struct) { const M = masked(struct); const ret = create(value, M); return ret; } /** * Check if a value passes a `Struct`. */ function is(value, struct) { const result = validate(value, struct); return !result[0]; } /** * Validate a value against a `Struct`, returning an error if invalid. */ function validate(value, struct, options = {}) { if (options.coerce) { value = struct.coercer(value); } const failures = check(value, struct); const failure = shiftIterator(failures); if (failure) { const error = new StructError(failure, failures); return [error, undefined]; } else { return [undefined, value]; } } /** * Check a value against a `Struct`, returning an iterable of failures. */ function* check(value, struct, path = [], branch = []) { const ctx = { value, struct, branch, path, check(v, s, parent, key) { const p = parent !== undefined ? [...path, key] : path; const b = parent !== undefined ? [...branch, parent] : branch; return check(v, s, p, b); }, fail(props = {}) { if (typeof props === 'string') { props = { message: props }; } const { type } = struct; let { message, refinement } = props; if (!message) { message = "Expected a value of type `" + type + "`" + (refinement ? " with refinement `" + refinement + "`" : '') + (path.length ? " for `" + path.join('.') + "`" : '') + ", but received: `" + print(value) + "`"; } return { ...props, value, type, refinement, message, key: path[path.length - 1], path, branch: [...branch, value] }; } }; const failures = toFailures(struct.validator(value, ctx), ctx); const failure = shiftIterator(failures); if (failure) { yield failure; yield* failures; } else { yield* toFailures(struct.refiner(value, ctx), ctx); } } /** * Ensure that a string, array, map, or set is empty. */ function empty(struct) { const expected = "Expected an empty " + struct.type; return refine(struct, 'empty', value => { if (value instanceof Map || value instanceof Set) { const { size } = value; return size === 0 || expected + " but received one with a size of `" + size + "`"; } else { const { length } = value; return length === 0 || expected + " but received one with a length of `" + length + "`"; } }); } /** * Ensure that a number or date is below a threshold. */ function max(struct, threshold, options = {}) { const { exclusive } = options; return refine(struct, 'max', value => { return exclusive ? value < threshold : value <= threshold || "Expected a " + struct.type + " greater than " + (exclusive ? '' : 'or equal to ') + threshold + " but received `" + value + "`"; }); } /** * Ensure that a number or date is above a threshold. */ function min(struct, threshold, options = {}) { const { exclusive } = options; return refine(struct, 'min', value => { return exclusive ? value > threshold : value >= threshold || "Expected a " + struct.type + " greater than " + (exclusive ? '' : 'or equal to ') + threshold + " but received `" + value + "`"; }); } /** * Ensure that a string matches a regular expression. */ function pattern(struct, regexp) { return refine(struct, 'pattern', value => { return regexp.test(value) || "Expected a " + struct.type + " matching `/" + regexp.source + "/` but received \"" + value + "\""; }); } /** * Ensure that a string, array, number, date, map, or set has a size (or length, or time) between `min` and `max`. */ function size(struct, min, max = min) { const expected = "Expected a " + struct.type; const of = min === max ? "of `" + min + "`" : "between `" + min + "` and `" + max + "`"; return refine(struct, 'size', value => { if (typeof value === 'number' || value instanceof Date) { return min <= value && value <= max || expected + " " + of + " but received `" + value + "`"; } else if (value instanceof Map || value instanceof Set) { const { size } = value; return min <= size && size <= max || expected + " with a size " + of + " but received one with a size of `" + size + "`"; } else { const { length } = value; return min <= length && length <= max || expected + " with a length " + of + " but received one with a length of `" + length + "`"; } }); } /** * Augment a `Struct` to add an additional refinement to the validation. * * The refiner function is guaranteed to receive a value of the struct's type, * because the struct's existing validation will already have passed. This * allows you to layer additional validation on top of existing structs. */ function refine(struct, name, refiner) { const fn = struct.refiner; return new Struct({ ...struct, *refiner(value, ctx) { yield* toFailures(fn(value, ctx), ctx); for (const failure of toFailures(refiner(value, ctx), ctx)) { yield { ...failure, refinement: name }; } } }); } export { Struct, StructError, any, array, assert, assign, boolean, coerce, create, date, defaulted, define, dynamic, empty, enums, func, instance, integer, intersection, is, lazy, literal, map, mask, masked, max, min, never, nullable, number, object, omit, optional, partial, pattern, pick, record, refine, regexp, set, size, string, struct, trimmed, tuple, type, union, unknown, validate }; //# sourceMappingURL=index.es.js.map