'use strict'; 
 | 
  
 | 
const Hoek = require('@hapi/hoek'); 
 | 
  
 | 
const Cast = require('../../cast'); 
 | 
const Settings = require('./settings'); 
 | 
const Ref = require('../../ref'); 
 | 
const Errors = require('../../errors'); 
 | 
const State = require('../state'); 
 | 
const Symbols = require('../symbols'); 
 | 
  
 | 
const Pkg = require('../../../package.json'); 
 | 
  
 | 
let Alternatives = null;                            // Delay-loaded to prevent circular dependencies 
 | 
let Schemas = null; 
 | 
  
 | 
  
 | 
const internals = { 
 | 
    Set: require('../../set'), 
 | 
    symbol: Symbol.for('@hapi/joi/schema') 
 | 
}; 
 | 
  
 | 
  
 | 
internals.defaults = { 
 | 
    abortEarly: true, 
 | 
    convert: true, 
 | 
    allowUnknown: false, 
 | 
    skipFunctions: false, 
 | 
    stripUnknown: false, 
 | 
    language: {}, 
 | 
    presence: 'optional', 
 | 
    noDefaults: false, 
 | 
    escapeHtml: false 
 | 
  
 | 
    // context: null 
 | 
}; 
 | 
  
 | 
  
 | 
module.exports = internals.Any = class { 
 | 
  
 | 
    constructor() { 
 | 
  
 | 
        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 || require('../../schemas'); 
 | 
  
 | 
        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 || require('../alternatives'); 
 | 
  
 | 
        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(this._language ? Settings.concat({ language: this._language }, options) : options, this._settings); 
 | 
                if (isDefaultOptions) { 
 | 
                    this._settings[Symbols.settingsCache] = options; 
 | 
                } 
 | 
            } 
 | 
        } 
 | 
        else if (this._language) { 
 | 
            options = Settings.concat({ language: this._language }, 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 description.rules; 
 | 
        } 
 | 
  
 | 
        const label = this._getLabel(); 
 | 
        if (label) { 
 | 
            description.label = label; 
 | 
        } 
 | 
  
 | 
        return description; 
 | 
    } 
 | 
  
 | 
    label(name) { 
 | 
  
 | 
        Hoek.assert(name && typeof name === 'string', 'Label name must be a non-empty string'); 
 | 
  
 | 
        const obj = this.clone(); 
 | 
        obj._flags.label = name; 
 | 
        return obj; 
 | 
    } 
 | 
  
 | 
    _getLabel(def) { 
 | 
  
 | 
        return this._flags.label || def; 
 | 
    } 
 | 
  
 | 
}; 
 | 
  
 | 
  
 | 
internals.Any.prototype.isImmutable = true;     // Prevents Hoek from deep cloning schema objects 
 | 
  
 | 
// Aliases 
 | 
  
 | 
internals.Any.prototype.only = internals.Any.prototype.equal = internals.Any.prototype.valid; 
 | 
internals.Any.prototype.disallow = internals.Any.prototype.not = internals.Any.prototype.invalid; 
 | 
internals.Any.prototype.exist = internals.Any.prototype.required; 
 | 
  
 | 
  
 | 
internals.Any.prototype[internals.symbol] = { 
 | 
    version: Pkg.version, 
 | 
    compile: Cast.schema, 
 | 
    root: '_currentJoi' 
 | 
}; 
 | 
  
 | 
  
 | 
internals._try = function (fn, args = []) { 
 | 
  
 | 
    let err; 
 | 
    let result; 
 | 
  
 | 
    try { 
 | 
        result = fn(...args); 
 | 
    } 
 | 
    catch (e) { 
 | 
        err = e; 
 | 
    } 
 | 
  
 | 
    return { 
 | 
        value: result, 
 | 
        error: err 
 | 
    }; 
 | 
}; 
 |