UNPKG

synctos

Version:

The Syncmaker. A tool to build comprehensive sync functions for Couchbase Sync Gateway.

1,704 lines (1,289 loc) 292 kB
module.exports = /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /******/ } /******/ }; /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ /******/ // create a fake namespace object /******/ // mode & 1: value is a module id, require it /******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 4: return value when already ns object /******/ // mode & 8|1: behave like require /******/ __webpack_require__.t = function(value, mode) { /******/ if(mode & 1) value = __webpack_require__(value); /******/ if(mode & 8) return value; /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; /******/ var ns = Object.create(null); /******/ __webpack_require__.r(ns); /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ return ns; /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 6); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; // Load modules const Assert = __webpack_require__(15); const Crypto = __webpack_require__(16); const Path = __webpack_require__(17); const DeepEqual = __webpack_require__(18); const Escape = __webpack_require__(19); // Declare internals const internals = {}; // Deep object or array comparison exports.deepEqual = DeepEqual; // Clone object or array exports.clone = function (obj, options = {}, _seen = null) { if (typeof obj !== 'object' || obj === null) { return obj; } const seen = _seen || new Map(); const lookup = seen.get(obj); if (lookup) { return lookup; } let newObj; let cloneDeep = false; const isArray = Array.isArray(obj); if (!isArray) { if (Buffer.isBuffer(obj)) { newObj = Buffer.from(obj); } else if (obj instanceof Date) { newObj = new Date(obj.getTime()); } else if (obj instanceof RegExp) { newObj = new RegExp(obj); } else { const proto = Object.getPrototypeOf(obj); if (proto && proto.isImmutable) { newObj = obj; } else { newObj = Object.create(proto); cloneDeep = true; } } } else { newObj = []; cloneDeep = true; } seen.set(obj, newObj); if (cloneDeep) { const keys = internals.keys(obj, options); for (let i = 0; i < keys.length; ++i) { const key = keys[i]; if (isArray && key === 'length') { continue; } const descriptor = Object.getOwnPropertyDescriptor(obj, key); if (descriptor && (descriptor.get || descriptor.set)) { Object.defineProperty(newObj, key, descriptor); } else { Object.defineProperty(newObj, key, { enumerable: descriptor ? descriptor.enumerable : true, writable: true, configurable: true, value: exports.clone(obj[key], options, seen) }); } } if (isArray) { newObj.length = obj.length; } } return newObj; }; internals.keys = function (obj, options = {}) { return options.symbols ? Reflect.ownKeys(obj) : Object.getOwnPropertyNames(obj); }; // Merge all the properties of source into target, source wins in conflict, and by default null and undefined from source are applied exports.merge = function (target, source, isNullOverride /* = true */, isMergeArrays /* = true */) { exports.assert(target && typeof target === 'object', 'Invalid target value: must be an object'); exports.assert(source === null || source === undefined || typeof source === 'object', 'Invalid source value: must be null, undefined, or an object'); if (!source) { return target; } if (Array.isArray(source)) { exports.assert(Array.isArray(target), 'Cannot merge array onto an object'); if (isMergeArrays === false) { // isMergeArrays defaults to true target.length = 0; // Must not change target assignment } for (let i = 0; i < source.length; ++i) { target.push(exports.clone(source[i])); } return target; } const keys = internals.keys(source); for (let i = 0; i < keys.length; ++i) { const key = keys[i]; if (key === '__proto__' || !Object.prototype.propertyIsEnumerable.call(source, key)) { continue; } const value = source[key]; if (value && typeof value === 'object') { if (!target[key] || typeof target[key] !== 'object' || (Array.isArray(target[key]) !== Array.isArray(value)) || value instanceof Date || Buffer.isBuffer(value) || value instanceof RegExp) { target[key] = exports.clone(value); } else { exports.merge(target[key], value, isNullOverride, isMergeArrays); } } else { if (value !== null && value !== undefined) { // Explicit to preserve empty strings target[key] = value; } else if (isNullOverride !== false) { // Defaults to true target[key] = value; } } } return target; }; // Apply options to a copy of the defaults exports.applyToDefaults = function (defaults, options, isNullOverride) { exports.assert(defaults && typeof defaults === 'object', 'Invalid defaults value: must be an object'); exports.assert(!options || options === true || typeof options === 'object', 'Invalid options value: must be true, falsy or an object'); if (!options) { // If no options, return null return null; } const copy = exports.clone(defaults); if (options === true) { // If options is set to true, use defaults return copy; } return exports.merge(copy, options, isNullOverride === true, false); }; // Clone an object except for the listed keys which are shallow copied exports.cloneWithShallow = function (source, keys, options) { if (!source || typeof source !== 'object') { return source; } const storage = internals.store(source, keys); // Move shallow copy items to storage const copy = exports.clone(source, options); // Deep copy the rest internals.restore(copy, source, storage); // Shallow copy the stored items and restore return copy; }; internals.store = function (source, keys) { const storage = new Map(); for (let i = 0; i < keys.length; ++i) { const key = keys[i]; const value = exports.reach(source, key); if (typeof value === 'object' || typeof value === 'function') { storage.set(key, value); internals.reachSet(source, key, undefined); } } return storage; }; internals.restore = function (copy, source, storage) { for (const [key, value] of storage) { internals.reachSet(copy, key, value); internals.reachSet(source, key, value); } }; internals.reachSet = function (obj, key, value) { const path = Array.isArray(key) ? key : key.split('.'); let ref = obj; for (let i = 0; i < path.length; ++i) { const segment = path[i]; if (i + 1 === path.length) { ref[segment] = value; } ref = ref[segment]; } }; // Apply options to defaults except for the listed keys which are shallow copied from option without merging exports.applyToDefaultsWithShallow = function (defaults, options, keys) { exports.assert(defaults && typeof defaults === 'object', 'Invalid defaults value: must be an object'); exports.assert(!options || options === true || typeof options === 'object', 'Invalid options value: must be true, falsy or an object'); exports.assert(keys && Array.isArray(keys), 'Invalid keys'); if (!options) { // If no options, return null return null; } const copy = exports.cloneWithShallow(defaults, keys); if (options === true) { // If options is set to true, use defaults return copy; } const storage = internals.store(options, keys); // Move shallow copy items to storage exports.merge(copy, options, false, false); // Deep copy the rest internals.restore(copy, options, storage); // Shallow copy the stored items and restore return copy; }; // Find the common unique items in two arrays exports.intersect = function (array1, array2, justFirst) { if (!array1 || !array2) { return (justFirst ? null : []); } const common = []; const hash = (Array.isArray(array1) ? new Set(array1) : array1); const found = new Set(); for (const value of array2) { if (internals.has(hash, value) && !found.has(value)) { if (justFirst) { return value; } common.push(value); found.add(value); } } return (justFirst ? null : common); }; internals.has = function (ref, key) { if (typeof ref.has === 'function') { return ref.has(key); } return ref[key] !== undefined; }; // Test if the reference contains the values exports.contain = function (ref, values, options = {}) { // options: { deep, once, only, part, symbols } /* string -> string(s) array -> item(s) object -> key(s) object -> object (key:value) */ let valuePairs = null; if (typeof ref === 'object' && typeof values === 'object' && !Array.isArray(ref) && !Array.isArray(values)) { valuePairs = values; const symbols = Object.getOwnPropertySymbols(values).filter(Object.prototype.propertyIsEnumerable.bind(values)); values = [...Object.keys(values), ...symbols]; } else { values = [].concat(values); } exports.assert(typeof ref === 'string' || typeof ref === 'object', 'Reference must be string or an object'); exports.assert(values.length, 'Values array cannot be empty'); let compare; let compareFlags; if (options.deep) { compare = exports.deepEqual; const hasOnly = options.hasOwnProperty('only'); const hasPart = options.hasOwnProperty('part'); compareFlags = { prototype: hasOnly ? options.only : hasPart ? !options.part : false, part: hasOnly ? !options.only : hasPart ? options.part : false }; } else { compare = (a, b) => a === b; } let misses = false; const matches = new Array(values.length); for (let i = 0; i < matches.length; ++i) { matches[i] = 0; } if (typeof ref === 'string') { let pattern = '('; for (let i = 0; i < values.length; ++i) { const value = values[i]; exports.assert(typeof value === 'string', 'Cannot compare string reference to non-string value'); pattern += (i ? '|' : '') + exports.escapeRegex(value); } const regex = new RegExp(pattern + ')', 'g'); const leftovers = ref.replace(regex, ($0, $1) => { const index = values.indexOf($1); ++matches[index]; return ''; // Remove from string }); misses = !!leftovers; } else if (Array.isArray(ref)) { const onlyOnce = !!(options.only && options.once); if (onlyOnce && ref.length !== values.length) { return false; } for (let i = 0; i < ref.length; ++i) { let matched = false; for (let j = 0; j < values.length && matched === false; ++j) { if (!onlyOnce || matches[j] === 0) { matched = compare(values[j], ref[i], compareFlags) && j; } } if (matched !== false) { ++matches[matched]; } else { misses = true; } } } else { const keys = internals.keys(ref, options); for (let i = 0; i < keys.length; ++i) { const key = keys[i]; const pos = values.indexOf(key); if (pos !== -1) { if (valuePairs && !compare(valuePairs[key], ref[key], compareFlags)) { return false; } ++matches[pos]; } else { misses = true; } } } if (options.only) { if (misses || !options.once) { return !misses; } } let result = false; for (let i = 0; i < matches.length; ++i) { result = result || !!matches[i]; if ((options.once && matches[i] > 1) || (!options.part && !matches[i])) { return false; } } return result; }; // Flatten array exports.flatten = function (array, target) { const result = target || []; for (let i = 0; i < array.length; ++i) { if (Array.isArray(array[i])) { exports.flatten(array[i], result); } else { result.push(array[i]); } } return result; }; // Convert an object key chain string ('a.b.c') to reference (object[a][b][c]) exports.reach = function (obj, chain, options) { if (chain === false || chain === null || typeof chain === 'undefined') { return obj; } options = options || {}; if (typeof options === 'string') { options = { separator: options }; } const isChainArray = Array.isArray(chain); exports.assert(!isChainArray || !options.separator, 'Separator option no valid for array-based chain'); const path = isChainArray ? chain : chain.split(options.separator || '.'); let ref = obj; for (let i = 0; i < path.length; ++i) { let key = path[i]; if (Array.isArray(ref)) { const number = Number(key); if (Number.isInteger(number) && number < 0) { key = ref.length + number; } } if (!ref || !((typeof ref === 'object' || typeof ref === 'function') && key in ref) || (typeof ref !== 'object' && options.functions === false)) { // Only object and function can have properties exports.assert(!options.strict || i + 1 === path.length, 'Missing segment', key, 'in reach path ', chain); exports.assert(typeof ref === 'object' || options.functions === true || typeof ref !== 'function', 'Invalid segment', key, 'in reach path ', chain); ref = options.default; break; } ref = ref[key]; } return ref; }; exports.reachTemplate = function (obj, template, options) { return template.replace(/{([^}]+)}/g, ($0, chain) => { const value = exports.reach(obj, chain, options); return (value === undefined || value === null ? '' : value); }); }; exports.assert = function (condition, ...args) { if (condition) { return; } if (args.length === 1 && args[0] instanceof Error) { throw args[0]; } const msgs = args .filter((arg) => arg !== '') .map((arg) => { return typeof arg === 'string' ? arg : arg instanceof Error ? arg.message : exports.stringify(arg); }); throw new Assert.AssertionError({ message: msgs.join(' ') || 'Unknown error', actual: false, expected: true, operator: '==', stackStartFunction: exports.assert }); }; exports.Bench = function () { this.ts = 0; this.reset(); }; exports.Bench.prototype.reset = function () { this.ts = exports.Bench.now(); }; exports.Bench.prototype.elapsed = function () { return exports.Bench.now() - this.ts; }; exports.Bench.now = function () { const ts = process.hrtime(); return (ts[0] * 1e3) + (ts[1] / 1e6); }; // Escape string for Regex construction exports.escapeRegex = function (string) { // Escape ^$.*+-?=!:|\/()[]{}, return string.replace(/[\^\$\.\*\+\-\?\=\!\:\|\\\/\(\)\[\]\{\}\,]/g, '\\$&'); }; // Escape attribute value for use in HTTP header exports.escapeHeaderAttribute = function (attribute) { // Allowed value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9, \, " exports.assert(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~\"\\]*$/.test(attribute), 'Bad attribute value (' + attribute + ')'); return attribute.replace(/\\/g, '\\\\').replace(/\"/g, '\\"'); // Escape quotes and slash }; exports.escapeHtml = function (string) { return Escape.escapeHtml(string); }; exports.escapeJson = function (string) { return Escape.escapeJson(string); }; exports.once = function (method) { if (method._hoekOnce) { return method; } let once = false; const wrapped = function (...args) { if (!once) { once = true; method(...args); } }; wrapped._hoekOnce = true; return wrapped; }; exports.ignore = function () { }; exports.uniqueFilename = function (path, extension) { if (extension) { extension = extension[0] !== '.' ? '.' + extension : extension; } else { extension = ''; } path = Path.resolve(path); const name = [Date.now(), process.pid, Crypto.randomBytes(8).toString('hex')].join('-') + extension; return Path.join(path, name); }; exports.stringify = function (...args) { try { return JSON.stringify.apply(null, args); } catch (err) { return '[Cannot display object: ' + err.message + ']'; } }; exports.wait = function (timeout) { return new Promise((resolve) => setTimeout(resolve, timeout)); }; exports.block = function () { return new Promise(exports.ignore); }; /***/ }), /* 1 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; // Load modules const Hoek = __webpack_require__(0); const Settings = __webpack_require__(7); const Ref = __webpack_require__(2); const Errors = __webpack_require__(4); const State = __webpack_require__(5); const Symbols = __webpack_require__(8); // Delay-loaded to prevent circular dependencies let Alternatives = null; let Cast = null; let Schemas = null; // Declare internals const internals = { Set: __webpack_require__(9) }; internals.defaults = { abortEarly: true, convert: true, allowUnknown: false, skipFunctions: false, stripUnknown: false, language: {}, presence: 'optional', strip: false, noDefaults: false, escapeHtml: false // context: null }; module.exports = internals.Any = class { constructor() { Cast = Cast || __webpack_require__(3); this.isJoi = true; this._type = 'any'; this._settings = null; this._valids = new internals.Set(); this._invalids = new internals.Set(); this._tests = []; this._refs = []; this._flags = { /* presence: 'optional', // optional, required, forbidden, ignore allowOnly: false, allowUnknown: undefined, default: undefined, forbidden: false, encoding: undefined, insensitive: false, trim: false, normalize: undefined, // NFC, NFD, NFKC, NFKD case: undefined, // upper, lower empty: undefined, func: false, raw: false */ }; this._description = null; this._unit = null; this._notes = []; this._tags = []; this._examples = []; this._meta = []; this._inner = {}; // Hash of arrays of immutable objects } _init() { return this; } get schemaType() { return this._type; } createError(type, context, state, options, flags = this._flags) { return Errors.create(type, context, state, options, flags); } createOverrideError(type, context, state, options, message, template) { return Errors.create(type, context, state, options, this._flags, message, template); } checkOptions(options) { Schemas = Schemas || __webpack_require__(21); const result = Schemas.options.validate(options); if (result.error) { throw new Error(result.error.details[0].message); } } clone() { const obj = Object.create(Object.getPrototypeOf(this)); obj.isJoi = true; obj._currentJoi = this._currentJoi; obj._type = this._type; obj._settings = this._settings; obj._baseType = this._baseType; obj._valids = this._valids.slice(); obj._invalids = this._invalids.slice(); obj._tests = this._tests.slice(); obj._refs = this._refs.slice(); obj._flags = Hoek.clone(this._flags); obj._description = this._description; obj._unit = this._unit; obj._notes = this._notes.slice(); obj._tags = this._tags.slice(); obj._examples = this._examples.slice(); obj._meta = this._meta.slice(); obj._inner = {}; const inners = Object.keys(this._inner); for (let i = 0; i < inners.length; ++i) { const key = inners[i]; obj._inner[key] = this._inner[key] ? this._inner[key].slice() : null; } return obj; } concat(schema) { Hoek.assert(schema instanceof internals.Any, 'Invalid schema object'); Hoek.assert(this._type === 'any' || schema._type === 'any' || schema._type === this._type, 'Cannot merge type', this._type, 'with another type:', schema._type); let obj = this.clone(); if (this._type === 'any' && schema._type !== 'any') { // Reset values as if we were "this" const tmpObj = schema.clone(); const keysToRestore = ['_settings', '_valids', '_invalids', '_tests', '_refs', '_flags', '_description', '_unit', '_notes', '_tags', '_examples', '_meta', '_inner']; for (let i = 0; i < keysToRestore.length; ++i) { tmpObj[keysToRestore[i]] = obj[keysToRestore[i]]; } obj = tmpObj; } obj._settings = obj._settings ? Settings.concat(obj._settings, schema._settings) : schema._settings; obj._valids.merge(schema._valids, schema._invalids); obj._invalids.merge(schema._invalids, schema._valids); obj._tests.push(...schema._tests); obj._refs.push(...schema._refs); if (obj._flags.empty && schema._flags.empty) { obj._flags.empty = obj._flags.empty.concat(schema._flags.empty); const flags = Object.assign({}, schema._flags); delete flags.empty; Hoek.merge(obj._flags, flags); } else if (schema._flags.empty) { obj._flags.empty = schema._flags.empty; const flags = Object.assign({}, schema._flags); delete flags.empty; Hoek.merge(obj._flags, flags); } else { Hoek.merge(obj._flags, schema._flags); } obj._description = schema._description || obj._description; obj._unit = schema._unit || obj._unit; obj._notes.push(...schema._notes); obj._tags.push(...schema._tags); obj._examples.push(...schema._examples); obj._meta.push(...schema._meta); const inners = Object.keys(schema._inner); const isObject = obj._type === 'object'; for (let i = 0; i < inners.length; ++i) { const key = inners[i]; const source = schema._inner[key]; if (source) { const target = obj._inner[key]; if (target) { if (isObject && key === 'children') { const keys = {}; for (let j = 0; j < target.length; ++j) { keys[target[j].key] = j; } for (let j = 0; j < source.length; ++j) { const sourceKey = source[j].key; if (keys[sourceKey] >= 0) { target[keys[sourceKey]] = { key: sourceKey, schema: target[keys[sourceKey]].schema.concat(source[j].schema) }; } else { target.push(source[j]); } } } else { obj._inner[key] = obj._inner[key].concat(source); } } else { obj._inner[key] = source.slice(); } } } return obj; } _test(name, arg, func, options) { const obj = this.clone(); obj._tests.push({ func, name, arg, options }); return obj; } _testUnique(name, arg, func, options) { const obj = this.clone(); obj._tests = obj._tests.filter((test) => test.name !== name); obj._tests.push({ func, name, arg, options }); return obj; } options(options) { Hoek.assert(!options.context, 'Cannot override context'); this.checkOptions(options); const obj = this.clone(); obj._settings = Settings.concat(obj._settings, options); return obj; } strict(isStrict) { const obj = this.clone(); const convert = isStrict === undefined ? false : !isStrict; obj._settings = Settings.concat(obj._settings, { convert }); return obj; } raw(isRaw) { const value = isRaw === undefined ? true : isRaw; if (this._flags.raw === value) { return this; } const obj = this.clone(); obj._flags.raw = value; return obj; } error(err, options = { self: false }) { Hoek.assert(err && (err instanceof Error || typeof err === 'function'), 'Must provide a valid Error object or a function'); const unknownKeys = Object.keys(options).filter((k) => !['self'].includes(k)); Hoek.assert(unknownKeys.length === 0, `Options ${unknownKeys} are unknown`); const obj = this.clone(); obj._flags.error = err; if (options.self) { obj._flags.selfError = true; } return obj; } allow(...values) { const obj = this.clone(); values = Hoek.flatten(values); for (let i = 0; i < values.length; ++i) { const value = values[i]; Hoek.assert(value !== undefined, 'Cannot call allow/valid/invalid with undefined'); obj._invalids.remove(value); obj._valids.add(value, obj._refs); } return obj; } valid(...values) { const obj = this.allow(...values); obj._flags.allowOnly = true; return obj; } invalid(...values) { const obj = this.clone(); values = Hoek.flatten(values); for (let i = 0; i < values.length; ++i) { const value = values[i]; Hoek.assert(value !== undefined, 'Cannot call allow/valid/invalid with undefined'); obj._valids.remove(value); obj._invalids.add(value, obj._refs); } return obj; } required() { if (this._flags.presence === 'required') { return this; } const obj = this.clone(); obj._flags.presence = 'required'; return obj; } optional() { if (this._flags.presence === 'optional') { return this; } const obj = this.clone(); obj._flags.presence = 'optional'; return obj; } forbidden() { if (this._flags.presence === 'forbidden') { return this; } const obj = this.clone(); obj._flags.presence = 'forbidden'; return obj; } strip() { if (this._flags.strip) { return this; } const obj = this.clone(); obj._flags.strip = true; return obj; } applyFunctionToChildren(children, fn, args = [], root) { children = [].concat(children); if (children.length !== 1 || children[0] !== '') { root = root ? (root + '.') : ''; const extraChildren = (children[0] === '' ? children.slice(1) : children).map((child) => { return root + child; }); throw new Error('unknown key(s) ' + extraChildren.join(', ')); } return this[fn](...args); } default(value, description) { if (typeof value === 'function' && !Ref.isRef(value)) { if (!value.description && description) { value.description = description; } if (!this._flags.func) { Hoek.assert(typeof value.description === 'string' && value.description.length > 0, 'description must be provided when default value is a function'); } } const obj = this.clone(); obj._flags.default = value; Ref.push(obj._refs, value); return obj; } empty(schema) { const obj = this.clone(); if (schema === undefined) { delete obj._flags.empty; } else { obj._flags.empty = Cast.schema(this._currentJoi, schema); } return obj; } when(condition, options) { Hoek.assert(options && typeof options === 'object', 'Invalid options'); Hoek.assert(options.then !== undefined || options.otherwise !== undefined, 'options must have at least one of "then" or "otherwise"'); const then = options.hasOwnProperty('then') ? this.concat(Cast.schema(this._currentJoi, options.then)) : undefined; const otherwise = options.hasOwnProperty('otherwise') ? this.concat(Cast.schema(this._currentJoi, options.otherwise)) : undefined; Alternatives = Alternatives || __webpack_require__(10); const alternativeOptions = { then, otherwise }; if (Object.prototype.hasOwnProperty.call(options, 'is')) { alternativeOptions.is = options.is; } const obj = Alternatives.when(condition, alternativeOptions); obj._flags.presence = 'ignore'; obj._baseType = this; return obj; } description(desc) { Hoek.assert(desc && typeof desc === 'string', 'Description must be a non-empty string'); const obj = this.clone(); obj._description = desc; return obj; } notes(notes) { Hoek.assert(notes && (typeof notes === 'string' || Array.isArray(notes)), 'Notes must be a non-empty string or array'); const obj = this.clone(); obj._notes = obj._notes.concat(notes); return obj; } tags(tags) { Hoek.assert(tags && (typeof tags === 'string' || Array.isArray(tags)), 'Tags must be a non-empty string or array'); const obj = this.clone(); obj._tags = obj._tags.concat(tags); return obj; } meta(meta) { Hoek.assert(meta !== undefined, 'Meta cannot be undefined'); const obj = this.clone(); obj._meta = obj._meta.concat(meta); return obj; } example(...examples) { Hoek.assert(examples.length > 0, 'Missing examples'); const processed = []; for (let i = 0; i < examples.length; ++i) { const example = [].concat(examples[i]); Hoek.assert(example.length <= 2, `Bad example format at index ${i}`); const value = example[0]; let options = example[1]; if (options !== undefined) { Hoek.assert(options && typeof options === 'object', `Options for example at index ${i} must be an object`); const unknownOptions = Object.keys(options).filter((option) => !['parent', 'context'].includes(option)); Hoek.assert(unknownOptions.length === 0, `Unknown example options ${unknownOptions} at index ${i}`); } else { options = {}; } const localState = new State('', [], options.parent || null); const result = this._validate(value, localState, Settings.concat(internals.defaults, options.context ? { context: options.context } : null)); Hoek.assert(!result.errors, `Bad example at index ${i}:`, result.errors && Errors.process(result.errors, value)); const ex = { value }; if (Object.keys(options).length) { ex.options = options; } processed.push(ex); } const obj = this.clone(); obj._examples = processed; return obj; } unit(name) { Hoek.assert(name && typeof name === 'string', 'Unit name must be a non-empty string'); const obj = this.clone(); obj._unit = name; return obj; } _prepareEmptyValue(value) { if (typeof value === 'string' && this._flags.trim) { return value.trim(); } return value; } _validate(value, state, options, reference) { const originalValue = value; // Setup state and settings state = state || new State('', [], null, reference); if (this._settings) { const isDefaultOptions = options === internals.defaults; if (isDefaultOptions && this._settings[Symbols.settingsCache]) { options = this._settings[Symbols.settingsCache]; } else { options = Settings.concat(options, this._settings); if (isDefaultOptions) { this._settings[Symbols.settingsCache] = options; } } } let errors = []; if (this._coerce) { const coerced = this._coerce(value, state, options); if (coerced.errors) { value = coerced.value; errors = errors.concat(coerced.errors); return this._finalizeValue(value, originalValue, errors, state, options); // Coerced error always aborts early } value = coerced.value; } if (this._flags.empty && !this._flags.empty._validate(this._prepareEmptyValue(value), null, internals.defaults).errors) { value = undefined; } // Check presence requirements const presence = this._flags.presence || options.presence; if (presence === 'optional') { if (value === undefined) { const isDeepDefault = this._flags.hasOwnProperty('default') && this._flags.default === undefined; if (isDeepDefault && this._type === 'object') { value = {}; } else { return this._finalizeValue(value, originalValue, errors, state, options); } } } else if (presence === 'required' && value === undefined) { errors.push(this.createError('any.required', null, state, options)); return this._finalizeValue(value, originalValue, errors, state, options); } else if (presence === 'forbidden') { if (value === undefined) { return this._finalizeValue(value, originalValue, errors, state, options); } errors.push(this.createError('any.unknown', null, state, options)); return this._finalizeValue(value, originalValue, errors, state, options); } // Check allowed and denied values using the original value let match = this._valids.get(value, state, options, this._flags.insensitive); if (match) { if (options.convert) { value = match.value; } return this._finalizeValue(value, originalValue, errors, state, options); } if (this._invalids.has(value, state, options, this._flags.insensitive)) { errors.push(this.createError(value === '' ? 'any.empty' : 'any.invalid', { value, invalids: this._invalids.values({ stripUndefined: true }) }, state, options)); if (options.abortEarly) { return this._finalizeValue(value, originalValue, errors, state, options); } } // Convert value and validate type if (this._base) { const base = this._base(value, state, options); if (base.errors) { value = base.value; errors = errors.concat(base.errors); return this._finalizeValue(value, originalValue, errors, state, options); // Base error always aborts early } if (base.value !== value) { value = base.value; // Check allowed and denied values using the converted value match = this._valids.get(value, state, options, this._flags.insensitive); if (match) { value = match.value; return this._finalizeValue(value, originalValue, errors, state, options); } if (this._invalids.has(value, state, options, this._flags.insensitive)) { errors.push(this.createError(value === '' ? 'any.empty' : 'any.invalid', { value, invalids: this._invalids.values({ stripUndefined: true }) }, state, options)); if (options.abortEarly) { return this._finalizeValue(value, originalValue, errors, state, options); } } } } // Required values did not match if (this._flags.allowOnly) { errors.push(this.createError('any.allowOnly', { value, valids: this._valids.values({ stripUndefined: true }) }, state, options)); if (options.abortEarly) { return this._finalizeValue(value, originalValue, errors, state, options); } } // Validate tests for (let i = 0; i < this._tests.length; ++i) { const test = this._tests[i]; const ret = test.func.call(this, value, state, options); if (ret instanceof Errors.Err) { errors.push(ret); if (options.abortEarly) { return this._finalizeValue(value, originalValue, errors, state, options); } } else { value = ret; } } return this._finalizeValue(value, originalValue, errors, state, options); } _finalizeValue(value, originalValue, errors, state, options) { let finalValue; if (value !== undefined) { finalValue = this._flags.raw ? originalValue : value; } else if (options.noDefaults) { finalValue = value; } else if (Ref.isRef(this._flags.default)) { finalValue = this._flags.default(state.parent, options); } else if (typeof this._flags.default === 'function' && !(this._flags.func && !this._flags.default.description)) { let args; if (state.parent !== null && this._flags.default.length > 0) { args = [Hoek.clone(state.parent), options]; } const defaultValue = internals._try(this._flags.default, args); finalValue = defaultValue.value; if (defaultValue.error) { errors.push(this.createError('any.default', { error: defaultValue.error }, state, options)); } } else { finalValue = Hoek.clone(this._flags.default); } if (errors.length && typeof this._flags.error === 'function' && ( !this._flags.selfError || errors.some((e) => state.path.length === e.path.length) ) ) { const change = this._flags.error.call(this, errors); if (typeof change === 'string') { errors = [this.createOverrideError('override', { reason: errors }, state, options, change)]; } else { errors = [].concat(change) .map((err) => { return err instanceof Error ? err : this.createOverrideError(err.type || 'override', err.context, state, options, err.message, err.template); }); } } return { value: this._flags.strip ? undefined : finalValue, finalValue, errors: errors.length ? errors : null }; } _validateWithOptions(value, options, callback) { if (options) { this.checkOptions(options); } const settings = Settings.concat(internals.defaults, options); const result = this._validate(value, null, settings); const errors = Errors.process(result.errors, value); if (callback) { return callback(errors, result.value); } return { error: errors, value: result.value, then(resolve, reject) { if (errors) { return Promise.reject(errors).catch(reject); } return Promise.resolve(result.value).then(resolve); }, catch(reject) { if (errors) { return Promise.reject(errors).catch(reject); } return Promise.resolve(result.value); } }; } validate(value, options, callback) { if (typeof options === 'function') { return this._validateWithOptions(value, null, options); } return this._validateWithOptions(value, options, callback); } describe() { const description = { type: this._type }; const flags = Object.keys(this._flags); if (flags.length) { if (['empty', 'default', 'lazy', 'label'].some((flag) => this._flags.hasOwnProperty(flag))) { description.flags = {}; for (let i = 0; i < flags.length; ++i) { const flag = flags[i]; if (flag === 'empty') { description.flags[flag] = this._flags[flag].describe(); } else if (flag === 'default') { if (Ref.isRef(this._flags[flag])) { description.flags[flag] = this._flags[flag].toString(); } else if (typeof this._flags[flag] === 'function') { description.flags[flag] = { description: this._flags[flag].description, function : this._flags[flag] }; } else { description.flags[flag] = this._flags[flag]; } } else if (flag === 'lazy' || flag === 'label') { // We don't want it in the description } else { description.flags[flag] = this._flags[flag]; } } } else { description.flags = this._flags; } } if (this._settings) { description.options = Hoek.clone(this._settings); } if (this._baseType) { description.base = this._baseType.describe(); } if (this._description) { description.description = this._description; } if (this._notes.length) { description.notes = this._notes; } if (this._tags.length) { description.tags = this._tags; } if (this._meta.length) { description.meta = this._meta; } if (this._examples.length) { description.examples = this._examples; } if (this._unit) { description.unit = this._unit; } const valids = this._valids.values(); if (valids.length) { description.valids = valids.map((v) => { return Ref.isRef(v) ? v.toString() : v; }); } const invalids = this._invalids.values(); if (invalids.length) { description.invalids = invalids.map((v) => { return Ref.isRef(v) ? v.toString() : v; }); } description.rules = []; for (let i = 0; i < this._tests.length; ++i) { const validator = this._tests[i]; const item = { name: validator.name }; if (validator.arg !== void 0) { item.arg = Ref.isRef(validator.arg) ? validator.arg.toString() : validator.arg; } const options = validator.options; if (options) { if (options.hasRef) { item.arg = {}; const keys = Object.keys(validator.arg); for (let j = 0; j < keys.length; ++j) { const key = keys[j]; const value = validator.arg[key]; item.arg[key] = Ref.isRef(value) ? value.toString() : value; } } if (typeof options.description === 'string') { item.description = options.description; } else if (typeof options.description === 'function') { item.description = options.description(item.arg); } } description.rules.push(item); } if (!description.rules.length) { delete d