We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The example from the README is throwing an error. It is saying message: '"name" is required',.
const Joi = require('joi'); const Enjoi = require('enjoi'); const schema = Enjoi.schema({ type: 'object', properties: { firstName: { description: 'First name.', type: 'string' }, lastName: { description: 'Last name.', type: 'string' }, age: { description: 'Age in years', type: 'integer', minimum: 1 } }, 'required': ['firstName', 'lastName'] }); const { error, value } = schema.validate({firstName: 'John', lastName: 'Doe', age: 45});
Logs
/tmp/node_modules/@hapi/joi/lib/index.js:183 throw error; ^ Error [ValidationError]: { "type": "object", "base": { "isJoi": true, "_type": "object", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [], "_refs": [], "_flags": {}, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "children": null, "renames": [], "dependencies": [], "patterns": [] }, "_currentJoi": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "any", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [], "_refs": [], "_flags": {}, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": {}, "_binds": {}, "any": function (...args) {\n\n Hoek.assert(args.length === 0, 'Joi.any() does not allow arguments.');\n\n return internals.callWithDefaults.call(this, any, args);\n }, "alt": function (...args) {\n\n return internals.callWithDefaults.call(this, internals.alternatives, args);\n }, "alternatives": function (...args) {\n\n return internals.callWithDefaults.call(this, internals.alternatives, args);\n }, "array": function (...args) {\n\n Hoek.assert(args.length === 0, 'Joi.array() does not allow arguments.');\n\n return internals.callWithDefaults.call(this, internals.array, args);\n }, "bool": function (...args) {\n\n Hoek.assert(args.length === 0, 'Joi.boolean() does not allow arguments.');\n\n return internals.callWithDefaults.call(this, internals.boolean, args);\n }, "boolean": function (...args) {\n\n Hoek.assert(args.length === 0, 'Joi.boolean() does not allow arguments.');\n\n return internals.callWithDefaults.call(this, internals.boolean, args);\n }, "binary": function (...args) {\n\n Hoek.assert(args.length === 0, 'Joi.binary() does not allow arguments.');\n\n return internals.callWithDefaults.call(this, internals.binary, args);\n }, "date": function (...args) {\n\n Hoek.assert(args.length === 0, 'Joi.date() does not allow arguments.');\n\n return internals.callWithDefaults.call(this, internals.date, args);\n }, "func": function (...args) {\n\n Hoek.assert(args.length === 0, 'Joi.func() does not allow arguments.');\n\n return internals.callWithDefaults.call(this, internals.func, args);\n }, "number": function (...args) {\n\n Hoek.assert(args.length === 0, 'Joi.number() does not allow arguments.');\n\n return internals.callWithDefaults.call(this, internals.number, args);\n }, "object": function (...args) {\n\n return internals.callWithDefaults.call(this, internals.object, args);\n }, "string": function (...args) {\n\n Hoek.assert(args.length === 0, 'Joi.string() does not allow arguments.');\n\n return internals.callWithDefaults.call(this, internals.string, args);\n }, "symbol": function (...args) {\n\n Hoek.assert(args.length === 0, 'Joi.symbol() does not allow arguments.');\n\n return internals.callWithDefaults.call(this, internals.symbol, args);\n }, "ref": function (...args) {\n\n return Ref.create(...args);\n }, "isRef": function (ref) {\n\n return Ref.isRef(ref);\n }, "validate": function (value, ...args /*, [schema], [options], callback */) {\n\n const last = args[args.length - 1];\n const callback = typeof last === 'function' ? last : null;\n\n const count = args.length - (callback ? 1 : 0);\n if (count === 0) {\n return any.validate(value, callback);\n }\n\n const options = count === 2 ? args[1] : undefined;\n const schema = this.compile(args[0]);\n\n return schema._validateWithOptions(value, options, callback);\n }, "describe": function (...args) {\n\n const schema = args.length ? this.compile(args[0]) : any;\n return schema.describe();\n }, "compile": function (schema) {\n\n try {\n return Cast.schema(this, schema);\n }\n catch (err) {\n if (err.hasOwnProperty('path')) {\n err.message = err.message + '(' + err.path + ')';\n }\n\n throw err;\n }\n }, "assert": function (value, schema, message) {\n\n this.attempt(value, schema, message);\n }, "attempt": function (value, schema, message) {\n\n const result = this.validate(value, schema);\n const error = result.error;\n if (error) {\n if (!message) {\n if (typeof error.annotate === 'function') {\n error.message = error.annotate();\n }\n\n throw error;\n }\n\n if (!(message instanceof Error)) {\n if (typeof error.annotate === 'function') {\n error.message = `${message} ${error.annotate()}`;\n }\n\n throw error;\n }\n\n throw message;\n }\n\n return result.value;\n }, "reach": function (schema, path) {\n\n Hoek.assert(schema && schema instanceof Any, 'you must provide a joi schema');\n Hoek.assert(Array.isArray(path) || typeof path === 'string', 'path must be a string or an array of strings');\n\n const reach = (sourceSchema, schemaPath) => {\n\n if (!schemaPath.length) {\n return sourceSchema;\n }\n\n const children = sourceSchema._inner.children;\n if (!children) {\n return;\n }\n\n const key = schemaPath.shift();\n for (let i = 0; i < children.length; ++i) {\n const child = children[i];\n if (child.key === key) {\n return reach(child.schema, schemaPath);\n }\n }\n };\n\n const schemaPath = typeof path === 'string' ? (path ? path.split('.') : []) : path.slice();\n\n return reach(schema, schemaPath);\n }, "lazy": function (...args) {\n\n return internals.callWithDefaults.call(this, Lazy, args);\n }, "defaults": function (fn) {\n\n Hoek.assert(typeof fn === 'function', 'Defaults must be a function');\n\n let joi = Object.create(this.any());\n joi = fn(joi);\n\n Hoek.assert(joi && joi instanceof this.constructor, 'defaults() must return a schema');\n\n Object.assign(joi, this, joi.clone()); // Re-add the types from `this` but also keep the settings from joi's potential new defaults\n\n joi._defaults = (schema) => {\n\n if (this._defaults) {\n schema = this._defaults(schema);\n Hoek.assert(schema instanceof this.constructor, 'defaults() must return a schema');\n }\n\n schema = fn(schema);\n Hoek.assert(schema instanceof this.constructor, 'defaults() must return a schema');\n return schema;\n };\n\n return joi;\n }, "bind": function () {\n\n const joi = Object.create(this);\n\n joi._binds.forEach((bind) => {\n\n joi[bind] = joi[bind].bind(joi);\n });\n\n return joi;\n }, "extend": function (...args) {\n\n const extensions = Hoek.flatten(args);\n Hoek.assert(extensions.length > 0, 'You need to provide at least one extension');\n\n this.assert(extensions, root.extensionsSchema);\n\n const joi = Object.create(this.any());\n Object.assign(joi, this);\n joi._currentJoi = joi;\n joi._binds = new Set(joi._binds);\n\n for (let i = 0; i < extensions.length; ++i) {\n let extension = extensions[i];\n\n if (typeof extension === 'function') {\n extension = extension(joi);\n }\n\n this.assert(extension, root.extensionSchema);\n\n const base = (extension.base || this.any()).clone(); // Cloning because we're going to override language afterwards\n const ctor = base.constructor;\n const type = class extends ctor { // eslint-disable-line no-loop-func\n\n constructor() {\n\n super();\n if (extension.base) {\n Object.assign(this, base);\n }\n\n this._type = extension.name;\n }\n\n };\n\n if (extension.language) {\n const lang = {\n [extension.name]: extension.language\n };\n type.prototype._language = Hoek.applyToDefaults(type.prototype._language || (base._settings && base._settings.language) || {}, lang);\n }\n\n\n if (extension.coerce) {\n type.prototype._coerce = function (value, state, options) {\n\n if (ctor.prototype._coerce) {\n const baseRet = ctor.prototype._coerce.call(this, value, state, options);\n\n if (baseRet.errors) {\n return baseRet;\n }\n\n value = baseRet.value;\n }\n\n const ret = extension.coerce.call(this, value, state, options);\n if (ret instanceof Errors.Err) {\n return { value, errors: ret };\n }\n\n return { value: ret };\n };\n }\n\n if (extension.pre) {\n type.prototype._base = function (value, state, options) {\n\n if (ctor.prototype._base) {\n const baseRet = ctor.prototype._base.call(this, value, state, options);\n\n if (baseRet.errors) {\n return baseRet;\n }\n\n value = baseRet.value;\n }\n\n const ret = extension.pre.call(this, value, state, options);\n if (ret instanceof Errors.Err) {\n return { value, errors: ret };\n }\n\n return { value: ret };\n };\n }\n\n if (extension.rules) {\n for (let j = 0; j < extension.rules.length; ++j) {\n const rule = extension.rules[j];\n const ruleArgs = rule.params ?\n (rule.params instanceof Any ? rule.params._inner.children.map((k) => k.key) : Object.keys(rule.params)) :\n [];\n const validateArgs = rule.params ? Cast.schema(this, rule.params) : null;\n\n type.prototype[rule.name] = function (...rArgs) { // eslint-disable-line no-loop-func\n\n if (rArgs.length > ruleArgs.length) {\n throw new Error('Unexpected number of arguments');\n }\n\n let hasRef = false;\n let arg = {};\n\n for (let k = 0; k < ruleArgs.length; ++k) {\n arg[ruleArgs[k]] = rArgs[k];\n if (!hasRef && Ref.isRef(rArgs[k])) {\n hasRef = true;\n }\n }\n\n if (validateArgs) {\n arg = joi.attempt(arg, validateArgs);\n }\n\n let schema;\n if (rule.validate && !rule.setup) {\n const validate = function (value, state, options) {\n\n return rule.validate.call(this, arg, value, state, options);\n };\n\n schema = this._test(rule.name, arg, validate, {\n description: rule.description,\n hasRef\n });\n }\n else {\n schema = this.clone();\n }\n\n if (rule.setup) {\n const newSchema = rule.setup.call(schema, arg);\n if (newSchema !== undefined) {\n Hoek.assert(newSchema instanceof Any, `Setup of extension Joi.${this._type}().${rule.name}() must return undefined or a Joi object`);\n schema = newSchema;\n }\n\n if (rule.validate) {\n const validate = function (value, state, options) {\n\n return rule.validate.call(this, arg, value, state, options);\n };\n\n schema = schema._test(rule.name, arg, validate, {\n description: rule.description,\n hasRef\n });\n }\n }\n\n return schema;\n };\n }\n }\n\n if (extension.describe) {\n type.prototype.describe = function () {\n\n const description = ctor.prototype.describe.call(this);\n return extension.describe.call(this, description);\n };\n }\n\n const instance = new type();\n joi[extension.name] = function (...extArgs) {\n\n return internals.callWithDefaults.call(this, instance, extArgs);\n };\n\n joi._binds.add(extension.name);\n }\n\n return joi;\n }, "extensionSchema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "object", "_settings": { "convert": false }, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [], "_refs": [], "_flags": {}, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "children": [ { "key": "base", "schema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "object", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [ { "func": function (value, state, options) {\n\n if (value instanceof constructor) {\n return value;\n }\n\n return this.createError('object.type', { type: typeData.name, value }, state, options);\n }, "name": "type", "arg": { "name": "Joi object", "ctor": "[class {\n\n constructor() {\n\n this.isJoi = true;\n this._type = 'any';\n this._settings = null;\n this._valids = new internals.Set();\n this._invalids = new internals.Set();\n this._tests = [];\n this._refs = [];\n this._flags = {\n /*\n presence: 'optional', // optional, required, forbidden, ignore\n allowOnly: false,\n allowUnknown: undefined,\n default: undefined,\n forbidden: false,\n encoding: undefined,\n insensitive: false,\n trim: false,\n normalize: undefined, // NFC, NFD, NFKC, NFKD\n case: undefined, // upper, lower\n empty: undefined,\n func: false,\n raw: false\n */\n };\n\n this._description = null;\n this._unit = null;\n this._notes = [];\n this._tags = [];\n this._examples = [];\n this._meta = [];\n\n this._inner = {}; // Hash of arrays of immutable objects\n }\n\n _init() {\n\n return this;\n }\n\n get schemaType() {\n\n return this._type;\n }\n\n createError(type, context, state, options, flags = this._flags) {\n\n return Errors.create(type, context, state, options, flags);\n }\n\n createOverrideError(type, context, state, options, message, template) {\n\n return Errors.create(type, context, state, options, this._flags, message, template);\n }\n\n checkOptions(options) {\n\n Schemas = Schemas || require('../../schemas');\n\n const result = Schemas.options.validate(options);\n\n if (result.error) {\n throw new Error(result.error.details[0].message);\n }\n }\n\n clone() {\n\n const obj = Object.create(Object.getPrototypeOf(this));\n\n obj.isJoi = true;\n obj._currentJoi = this._currentJoi;\n obj._type = this._type;\n obj._settings = this._settings;\n obj._baseType = this._baseType;\n obj._valids = this._valids.slice();\n obj._invalids = this._invalids.slice();\n obj._tests = this._tests.slice();\n obj._refs = this._refs.slice();\n obj._flags = Hoek.clone(this._flags);\n\n obj._description = this._description;\n obj._unit = this._unit;\n obj._notes = this._notes.slice();\n obj._tags = this._tags.slice();\n obj._examples = this._examples.slice();\n obj._meta = this._meta.slice();\n\n obj._inner = {};\n const inners = Object.keys(this._inner);\n for (let i = 0; i < inners.length; ++i) {\n const key = inners[i];\n obj._inner[key] = this._inner[key] ? this._inner[key].slice() : null;\n }\n\n return obj;\n }\n\n concat(schema) {\n\n Hoek.assert(schema instanceof internals.Any, 'Invalid schema object');\n Hoek.assert(this._type === 'any' || schema._type === 'any' || schema._type === this._type, 'Cannot merge type', this._type, 'with another type:', schema._type);\n\n let obj = this.clone();\n\n if (this._type === 'any' && schema._type !== 'any') {\n\n // Reset values as if we were \"this\"\n const tmpObj = schema.clone();\n const keysToRestore = ['_settings', '_valids', '_invalids', '_tests', '_refs', '_flags', '_description', '_unit',\n '_notes', '_tags', '_examples', '_meta', '_inner'];\n\n for (let i = 0; i < keysToRestore.length; ++i) {\n tmpObj[keysToRestore[i]] = obj[keysToRestore[i]];\n }\n\n obj = tmpObj;\n }\n\n obj._settings = obj._settings ? Settings.concat(obj._settings, schema._settings) : schema._settings;\n obj._valids.merge(schema._valids, schema._invalids);\n obj._invalids.merge(schema._invalids, schema._valids);\n obj._tests.push(...schema._tests);\n obj._refs.push(...schema._refs);\n if (obj._flags.empty && schema._flags.empty) {\n obj._flags.empty = obj._flags.empty.concat(schema._flags.empty);\n const flags = Object.assign({}, schema._flags);\n delete flags.empty;\n Hoek.merge(obj._flags, flags);\n }\n else if (schema._flags.empty) {\n obj._flags.empty = schema._flags.empty;\n const flags = Object.assign({}, schema._flags);\n delete flags.empty;\n Hoek.merge(obj._flags, flags);\n }\n else {\n Hoek.merge(obj._flags, schema._flags);\n }\n\n obj._description = schema._description || obj._description;\n obj._unit = schema._unit || obj._unit;\n obj._notes.push(...schema._notes);\n obj._tags.push(...schema._tags);\n obj._examples.push(...schema._examples);\n obj._meta.push(...schema._meta);\n\n const inners = Object.keys(schema._inner);\n const isObject = obj._type === 'object';\n for (let i = 0; i < inners.length; ++i) {\n const key = inners[i];\n const source = schema._inner[key];\n if (source) {\n const target = obj._inner[key];\n if (target) {\n if (isObject && key === 'children') {\n const keys = {};\n\n for (let j = 0; j < target.length; ++j) {\n keys[target[j].key] = j;\n }\n\n for (let j = 0; j < source.length; ++j) {\n const sourceKey = source[j].key;\n if (keys[sourceKey] >= 0) {\n target[keys[sourceKey]] = {\n key: sourceKey,\n schema: target[keys[sourceKey]].schema.concat(source[j].schema)\n };\n }\n else {\n target.push(source[j]);\n }\n }\n }\n else {\n obj._inner[key] = obj._inner[key].concat(source);\n }\n }\n else {\n obj._inner[key] = source.slice();\n }\n }\n }\n\n return obj;\n }\n\n _test(name, arg, func, options) {\n\n const obj = this.clone();\n obj._tests.push({ func, name, arg, options });\n return obj;\n }\n\n _testUnique(name, arg, func, options) {\n\n const obj = this.clone();\n obj._tests = obj._tests.filter((test) => test.name !== name);\n obj._tests.push({ func, name, arg, options });\n return obj;\n }\n\n options(options) {\n\n Hoek.assert(!options.context, 'Cannot override context');\n this.checkOptions(options);\n\n const obj = this.clone();\n obj._settings = Settings.concat(obj._settings, options);\n return obj;\n }\n\n strict(isStrict) {\n\n const obj = this.clone();\n\n const convert = isStrict === undefined ? false : !isStrict;\n obj._settings = Settings.concat(obj._settings, { convert });\n return obj;\n }\n\n raw(isRaw) {\n\n const value = isRaw === undefined ? true : isRaw;\n\n if (this._flags.raw === value) {\n return this;\n }\n\n const obj = this.clone();\n obj._flags.raw = value;\n return obj;\n }\n\n error(err, options = { self: false }) {\n\n Hoek.assert(err && (err instanceof Error || typeof err === 'function'), 'Must provide a valid Error object or a function');\n\n const unknownKeys = Object.keys(options).filter((k) => !['self'].includes(k));\n Hoek.assert(unknownKeys.length === 0, `Options ${unknownKeys} are unknown`);\n\n const obj = this.clone();\n obj._flags.error = err;\n\n if (options.self) {\n obj._flags.selfError = true;\n }\n\n return obj;\n }\n\n allow(...values) {\n\n const obj = this.clone();\n values = Hoek.flatten(values);\n for (let i = 0; i < values.length; ++i) {\n const value = values[i];\n\n Hoek.assert(value !== undefined, 'Cannot call allow/valid/invalid with undefined');\n obj._invalids.remove(value);\n obj._valids.add(value, obj._refs);\n }\n\n return obj;\n }\n\n valid(...values) {\n\n const obj = this.allow(...values);\n obj._flags.allowOnly = true;\n return obj;\n }\n\n invalid(...values) {\n\n const obj = this.clone();\n values = Hoek.flatten(values);\n for (let i = 0; i < values.length; ++i) {\n const value = values[i];\n\n Hoek.assert(value !== undefined, 'Cannot call allow/valid/invalid with undefined');\n obj._valids.remove(value);\n obj._invalids.add(value, obj._refs);\n }\n\n return obj;\n }\n\n required() {\n\n if (this._flags.presence === 'required') {\n return this;\n }\n\n const obj = this.clone();\n obj._flags.presence = 'required';\n return obj;\n }\n\n optional() {\n\n if (this._flags.presence === 'optional') {\n return this;\n }\n\n const obj = this.clone();\n obj._flags.presence = 'optional';\n return obj;\n }\n\n\n forbidden() {\n\n if (this._flags.presence === 'forbidden') {\n return this;\n }\n\n const obj = this.clone();\n obj._flags.presence = 'forbidden';\n return obj;\n }\n\n\n strip() {\n\n if (this._flags.strip) {\n return this;\n }\n\n const obj = this.clone();\n obj._flags.strip = true;\n return obj;\n }\n\n applyFunctionToChildren(children, fn, args = [], root) {\n\n children = [].concat(children);\n\n if (children.length !== 1 || children[0] !== '') {\n root = root ? (root + '.') : '';\n\n const extraChildren = (children[0] === '' ? children.slice(1) : children).map((child) => {\n\n return root + child;\n });\n\n throw new Error('unknown key(s) ' + extraChildren.join(', '));\n }\n\n return this[fn](...args);\n }\n\n default(value, description) {\n\n if (typeof value === 'function' &&\n !Ref.isRef(value)) {\n\n if (!value.description &&\n description) {\n\n value.description = description;\n }\n\n if (!this._flags.func) {\n Hoek.assert(typeof value.description === 'string' && value.description.length > 0, 'description must be provided when default value is a function');\n }\n }\n\n const obj = this.clone();\n obj._flags.default = value;\n Ref.push(obj._refs, value);\n return obj;\n }\n\n empty(schema) {\n\n const obj = this.clone();\n if (schema === undefined) {\n delete obj._flags.empty;\n }\n else {\n obj._flags.empty = Cast.schema(this._currentJoi, schema);\n }\n\n return obj;\n }\n\n when(condition, options) {\n\n Hoek.assert(options && typeof options === 'object', 'Invalid options');\n Hoek.assert(options.then !== undefined || options.otherwise !== undefined, 'options must have at least one of \"then\" or \"otherwise\"');\n\n const then = options.hasOwnProperty('then') ? this.concat(Cast.schema(this._currentJoi, options.then)) : undefined;\n const otherwise = options.hasOwnProperty('otherwise') ? this.concat(Cast.schema(this._currentJoi, options.otherwise)) : undefined;\n\n Alternatives = Alternatives || require('../alternatives');\n\n const alternativeOptions = { then, otherwise };\n if (Object.prototype.hasOwnProperty.call(options, 'is')) {\n alternativeOptions.is = options.is;\n }\n\n const obj = Alternatives.when(condition, alternativeOptions);\n obj._flags.presence = 'ignore';\n obj._baseType = this;\n\n return obj;\n }\n\n description(desc) {\n\n Hoek.assert(desc && typeof desc === 'string', 'Description must be a non-empty string');\n\n const obj = this.clone();\n obj._description = desc;\n return obj;\n }\n\n notes(notes) {\n\n Hoek.assert(notes && (typeof notes === 'string' || Array.isArray(notes)), 'Notes must be a non-empty string or array');\n\n const obj = this.clone();\n obj._notes = obj._notes.concat(notes);\n return obj;\n }\n\n tags(tags) {\n\n Hoek.assert(tags && (typeof tags === 'string' || Array.isArray(tags)), 'Tags must be a non-empty string or array');\n\n const obj = this.clone();\n obj._tags = obj._tags.concat(tags);\n return obj;\n }\n\n meta(meta) {\n\n Hoek.assert(meta !== undefined, 'Meta cannot be undefined');\n\n const obj = this.clone();\n obj._meta = obj._meta.concat(meta);\n return obj;\n }\n\n example(...examples) {\n\n Hoek.assert(examples.length > 0, 'Missing examples');\n\n const processed = [];\n for (let i = 0; i < examples.length; ++i) {\n const example = [].concat(examples[i]);\n Hoek.assert(example.length <= 2, `Bad example format at index ${i}`);\n\n const value = example[0];\n let options = example[1];\n if (options !== undefined) {\n Hoek.assert(options && typeof options === 'object', `Options for example at index ${i} must be an object`);\n const unknownOptions = Object.keys(options).filter((option) => !['parent', 'context'].includes(option));\n Hoek.assert(unknownOptions.length === 0, `Unknown example options ${unknownOptions} at index ${i}`);\n }\n else {\n options = {};\n }\n\n const localState = new State('', [], options.parent || null);\n const result = this._validate(value, localState, Settings.concat(internals.defaults, options.context ? { context: options.context } : null));\n Hoek.assert(!result.errors, `Bad example at index ${i}:`, result.errors && Errors.process(result.errors, value));\n\n const ex = { value };\n if (Object.keys(options).length) {\n ex.options = options;\n }\n\n processed.push(ex);\n }\n\n const obj = this.clone();\n obj._examples = processed;\n return obj;\n }\n\n unit(name) {\n\n Hoek.assert(name && typeof name === 'string', 'Unit name must be a non-empty string');\n\n const obj = this.clone();\n obj._unit = name;\n return obj;\n }\n\n _prepareEmptyValue(value) {\n\n if (typeof value === 'string' && this._flags.trim) {\n return value.trim();\n }\n\n return value;\n }\n\n _validate(value, state, options, reference) {\n\n const originalValue = value;\n\n // Setup state and settings\n\n state = state || new State('', [], null, reference);\n\n if (this._settings) {\n const isDefaultOptions = options === internals.defaults;\n if (isDefaultOptions && this._settings[Symbols.settingsCache]) {\n options = this._settings[Symbols.settingsCache];\n }\n else {\n options = Settings.concat(this._language ? Settings.concat({ language: this._language }, options) : options, this._settings);\n if (isDefaultOptions) {\n this._settings[Symbols.settingsCache] = options;\n }\n }\n }\n else if (this._language) {\n options = Settings.concat({ language: this._language }, options);\n }\n\n let errors = [];\n\n if (this._coerce) {\n const coerced = this._coerce(value, state, options);\n if (coerced.errors) {\n value = coerced.value;\n errors = errors.concat(coerced.errors);\n return this._finalizeValue(value, originalValue, errors, state, options); // Coerced error always aborts early\n }\n\n value = coerced.value;\n }\n\n if (this._flags.empty && !this._flags.empty._validate(this._prepareEmptyValue(value), null, internals.defaults).errors) {\n value = undefined;\n }\n\n // Check presence requirements\n\n const presence = this._flags.presence || options.presence;\n if (presence === 'optional') {\n if (value === undefined) {\n const isDeepDefault = this._flags.hasOwnProperty('default') && this._flags.default === undefined;\n if (isDeepDefault && this._type === 'object') {\n value = {};\n }\n else {\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n }\n }\n else if (presence === 'required' &&\n value === undefined) {\n\n errors.push(this.createError('any.required', null, state, options));\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n else if (presence === 'forbidden') {\n if (value === undefined) {\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n\n errors.push(this.createError('any.unknown', null, state, options));\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n\n // Check allowed and denied values using the original value\n\n let match = this._valids.get(value, state, options, this._flags.insensitive);\n if (match) {\n if (options.convert) {\n value = match.value;\n }\n\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n\n if (this._invalids.has(value, state, options, this._flags.insensitive)) {\n errors.push(this.createError(value === '' ? 'any.empty' : 'any.invalid', { value, invalids: this._invalids.values({ stripUndefined: true }) }, state, options));\n if (options.abortEarly) {\n\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n }\n\n // Convert value and validate type\n\n if (this._base) {\n const base = this._base(value, state, options);\n if (base.errors) {\n value = base.value;\n errors = errors.concat(base.errors);\n return this._finalizeValue(value, originalValue, errors, state, options); // Base error always aborts early\n }\n\n if (base.value !== value) {\n value = base.value;\n\n // Check allowed and denied values using the converted value\n\n match = this._valids.get(value, state, options, this._flags.insensitive);\n if (match) {\n value = match.value;\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n\n if (this._invalids.has(value, state, options, this._flags.insensitive)) {\n errors.push(this.createError(value === '' ? 'any.empty' : 'any.invalid', { value, invalids: this._invalids.values({ stripUndefined: true }) }, state, options));\n if (options.abortEarly) {\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n }\n }\n }\n\n // Required values did not match\n\n if (this._flags.allowOnly) {\n errors.push(this.createError('any.allowOnly', { value, valids: this._valids.values({ stripUndefined: true }) }, state, options));\n if (options.abortEarly) {\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n }\n\n // Validate tests\n\n for (let i = 0; i < this._tests.length; ++i) {\n const test = this._tests[i];\n const ret = test.func.call(this, value, state, options);\n if (ret instanceof Errors.Err) {\n errors.push(ret);\n if (options.abortEarly) {\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n }\n else {\n value = ret;\n }\n }\n\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n\n _finalizeValue(value, originalValue, errors, state, options) {\n\n let finalValue;\n\n if (value !== undefined) {\n finalValue = this._flags.raw ? originalValue : value;\n }\n else if (options.noDefaults) {\n finalValue = value;\n }\n else if (Ref.isRef(this._flags.default)) {\n finalValue = this._flags.default(state.parent, options);\n }\n else if (typeof this._flags.default === 'function' &&\n !(this._flags.func && !this._flags.default.description)) {\n\n let args;\n\n if (state.parent !== null &&\n this._flags.default.length > 0) {\n\n args = [Hoek.clone(state.parent), options];\n }\n\n const defaultValue = internals._try(this._flags.default, args);\n finalValue = defaultValue.value;\n if (defaultValue.error) {\n errors.push(this.createError('any.default', { error: defaultValue.error }, state, options));\n }\n }\n else {\n finalValue = Hoek.clone(this._flags.default);\n }\n\n if (errors.length &&\n typeof this._flags.error === 'function' &&\n (\n !this._flags.selfError ||\n errors.some((e) => state.path.length === e.path.length)\n )\n ) {\n const change = this._flags.error.call(this, errors);\n\n if (typeof change === 'string') {\n errors = [this.createOverrideError('override', { reason: errors }, state, options, change)];\n }\n else {\n errors = [].concat(change)\n .map((err) => {\n\n return err instanceof Error ?\n err :\n this.createOverrideError(err.type || 'override', err.context, state, options, err.message, err.template);\n });\n }\n }\n\n return {\n value: this._flags.strip ? undefined : finalValue,\n finalValue,\n errors: errors.length ? errors : null\n };\n }\n\n _validateWithOptions(value, options, callback) {\n\n if (options) {\n this.checkOptions(options);\n }\n\n const settings = Settings.concat(internals.defaults, options);\n const result = this._validate(value, null, settings);\n const errors = Errors.process(result.errors, value);\n\n if (callback) {\n return callback(errors, result.value);\n }\n\n return {\n error: errors,\n value: result.value,\n then(resolve, reject) {\n\n if (errors) {\n return Promise.reject(errors).catch(reject);\n }\n\n return Promise.resolve(result.value).then(resolve);\n },\n catch(reject) {\n\n if (errors) {\n return Promise.reject(errors).catch(reject);\n }\n\n return Promise.resolve(result.value);\n }\n };\n }\n\n validate(value, options, callback) {\n\n if (typeof options === 'function') {\n return this._validateWithOptions(value, null, options);\n }\n\n return this._validateWithOptions(value, options, callback);\n }\n\n describe() {\n\n const description = {\n type: this._type\n };\n\n const flags = Object.keys(this._flags);\n if (flags.length) {\n if (['empty', 'default', 'lazy', 'label'].some((flag) => this._flags.hasOwnProperty(flag))) {\n description.flags = {};\n for (let i = 0; i < flags.length; ++i) {\n const flag = flags[i];\n if (flag === 'empty') {\n description.flags[flag] = this._flags[flag].describe();\n }\n else if (flag === 'default') {\n if (Ref.isRef(this._flags[flag])) {\n description.flags[flag] = this._flags[flag].toString();\n }\n else if (typeof this._flags[flag] === 'function') {\n description.flags[flag] = {\n description: this._flags[flag].description,\n function : this._flags[flag]\n };\n }\n else {\n description.flags[flag] = this._flags[flag];\n }\n }\n else if (flag === 'lazy' || flag === 'label') {\n // We don't want it in the description\n }\n else {\n description.flags[flag] = this._flags[flag];\n }\n }\n }\n else {\n description.flags = this._flags;\n }\n }\n\n if (this._settings) {\n description.options = Hoek.clone(this._settings);\n }\n\n if (this._baseType) {\n description.base = this._baseType.describe();\n }\n\n if (this._description) {\n description.description = this._description;\n }\n\n if (this._notes.length) {\n description.notes = this._notes;\n }\n\n if (this._tags.length) {\n description.tags = this._tags;\n }\n\n if (this._meta.length) {\n description.meta = this._meta;\n }\n\n if (this._examples.length) {\n description.examples = this._examples;\n }\n\n if (this._unit) {\n description.unit = this._unit;\n }\n\n const valids = this._valids.values();\n if (valids.length) {\n description.valids = valids.map((v) => {\n\n return Ref.isRef(v) ? v.toString() : v;\n });\n }\n\n const invalids = this._invalids.values();\n if (invalids.length) {\n description.invalids = invalids.map((v) => {\n\n return Ref.isRef(v) ? v.toString() : v;\n });\n }\n\n description.rules = [];\n\n for (let i = 0; i < this._tests.length; ++i) {\n const validator = this._tests[i];\n const item = { name: validator.name };\n\n if (validator.arg !== void 0) {\n item.arg = Ref.isRef(validator.arg) ? validator.arg.toString() : validator.arg;\n }\n\n const options = validator.options;\n if (options) {\n if (options.hasRef) {\n item.arg = {};\n const keys = Object.keys(validator.arg);\n for (let j = 0; j < keys.length; ++j) {\n const key = keys[j];\n const value = validator.arg[key];\n item.arg[key] = Ref.isRef(value) ? value.toString() : value;\n }\n }\n\n if (typeof options.description === 'string') {\n item.description = options.description;\n }\n else if (typeof options.description === 'function') {\n item.description = options.description(item.arg);\n }\n }\n\n description.rules.push(item);\n }\n\n if (!description.rules.length) {\n delete description.rules;\n }\n\n const label = this._getLabel();\n if (label) {\n description.label = label;\n }\n\n return description;\n }\n\n label(name) {\n\n Hoek.assert(name && typeof name === 'string', 'Label name must be a non-empty string');\n\n const obj = this.clone();\n obj._flags.label = name;\n return obj;\n }\n\n _getLabel(def) {\n\n return this._flags.label || def;\n }\n\n}]" } } ], "_refs": [], "_flags": {}, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "children": null, "renames": [], "dependencies": [], "patterns": [] } } }, { "key": "name", "schema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "string", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": 0 }, "_tests": [], "_refs": [], "_flags": { "presence": "required" }, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": {} } }, { "key": "coerce", "schema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "object", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [ { "func": function (value, state, options) {\n\n if (value.length === n) {\n return value;\n }\n\n return this.createError('function.arity', { n }, state, options);\n }, "name": "arity", "arg": 3 } ], "_refs": [], "_flags": { "func": true }, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "children": null, "renames": [], "dependencies": [], "patterns": [] } } }, { "key": "pre", "schema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "object", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [ { "func": function (value, state, options) {\n\n if (value.length === n) {\n return value;\n }\n\n return this.createError('function.arity', { n }, state, options);\n }, "name": "arity", "arg": 3 } ], "_refs": [], "_flags": { "func": true }, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "children": null, "renames": [], "dependencies": [], "patterns": [] } } }, { "key": "language", "schema": "[Circular ~.base]" }, { "key": "describe", "schema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "object", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [ { "func": function (value, state, options) {\n\n if (value.length === n) {\n return value;\n }\n\n return this.createError('function.arity', { n }, state, options);\n }, "name": "arity", "arg": 1 } ], "_refs": [], "_flags": { "func": true }, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "children": null, "renames": [], "dependencies": [], "patterns": [] } } }, { "key": "rules", "schema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "array", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [], "_refs": [], "_flags": { "sparse": false }, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "items": [ { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "object", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [], "_refs": [], "_flags": {}, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "children": [ { "key": "name", "schema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "string", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": 0 }, "_tests": [], "_refs": [], "_flags": { "presence": "required" }, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": {} } }, { "key": "setup", "schema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "object", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [ { "func": function (value, state, options) {\n\n if (value.length === n) {\n return value;\n }\n\n return this.createError('function.arity', { n }, state, options);\n }, "name": "arity", "arg": 1 } ], "_refs": [], "_flags": { "func": true }, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "children": null, "renames": [], "dependencies": [], "patterns": [] } } }, { "key": "validate", "schema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "object", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [ { "func": function (value, state, options) {\n\n if (value.length === n) {\n return value;\n }\n\n return this.createError('function.arity', { n }, state, options);\n }, "name": "arity", "arg": 4 } ], "_refs": [], "_flags": { "func": true }, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "children": null, "renames": [], "dependencies": [], "patterns": [] } } }, { "key": "params", "schema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "alternatives", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [], "_refs": [], "_flags": {}, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "matches": [ { "schema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "object", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [], "_refs": [], "_flags": {}, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "children": null, "renames": [], "dependencies": [], "patterns": [ { "regex": {}, "rule": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "object", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [ { "func": function (value, state, options) {\n\n if (value instanceof constructor) {\n return value;\n }\n\n return this.createError('object.type', { type: typeData.name, value }, state, options);\n }, "name": "type", "arg": { "name": "Joi object", "ctor": "[class {\n\n constructor() {\n\n this.isJoi = true;\n this._type = 'any';\n this._settings = null;\n this._valids = new internals.Set();\n this._invalids = new internals.Set();\n this._tests = [];\n this._refs = [];\n this._flags = {\n /*\n presence: 'optional', // optional, required, forbidden, ignore\n allowOnly: false,\n allowUnknown: undefined,\n default: undefined,\n forbidden: false,\n encoding: undefined,\n insensitive: false,\n trim: false,\n normalize: undefined, // NFC, NFD, NFKC, NFKD\n case: undefined, // upper, lower\n empty: undefined,\n func: false,\n raw: false\n */\n };\n\n this._description = null;\n this._unit = null;\n this._notes = [];\n this._tags = [];\n this._examples = [];\n this._meta = [];\n\n this._inner = {}; // Hash of arrays of immutable objects\n }\n\n _init() {\n\n return this;\n }\n\n get schemaType() {\n\n return this._type;\n }\n\n createError(type, context, state, options, flags = this._flags) {\n\n return Errors.create(type, context, state, options, flags);\n }\n\n createOverrideError(type, context, state, options, message, template) {\n\n return Errors.create(type, context, state, options, this._flags, message, template);\n }\n\n checkOptions(options) {\n\n Schemas = Schemas || require('../../schemas');\n\n const result = Schemas.options.validate(options);\n\n if (result.error) {\n throw new Error(result.error.details[0].message);\n }\n }\n\n clone() {\n\n const obj = Object.create(Object.getPrototypeOf(this));\n\n obj.isJoi = true;\n obj._currentJoi = this._currentJoi;\n obj._type = this._type;\n obj._settings = this._settings;\n obj._baseType = this._baseType;\n obj._valids = this._valids.slice();\n obj._invalids = this._invalids.slice();\n obj._tests = this._tests.slice();\n obj._refs = this._refs.slice();\n obj._flags = Hoek.clone(this._flags);\n\n obj._description = this._description;\n obj._unit = this._unit;\n obj._notes = this._notes.slice();\n obj._tags = this._tags.slice();\n obj._examples = this._examples.slice();\n obj._meta = this._meta.slice();\n\n obj._inner = {};\n const inners = Object.keys(this._inner);\n for (let i = 0; i < inners.length; ++i) {\n const key = inners[i];\n obj._inner[key] = this._inner[key] ? this._inner[key].slice() : null;\n }\n\n return obj;\n }\n\n concat(schema) {\n\n Hoek.assert(schema instanceof internals.Any, 'Invalid schema object');\n Hoek.assert(this._type === 'any' || schema._type === 'any' || schema._type === this._type, 'Cannot merge type', this._type, 'with another type:', schema._type);\n\n let obj = this.clone();\n\n if (this._type === 'any' && schema._type !== 'any') {\n\n // Reset values as if we were \"this\"\n const tmpObj = schema.clone();\n const keysToRestore = ['_settings', '_valids', '_invalids', '_tests', '_refs', '_flags', '_description', '_unit',\n '_notes', '_tags', '_examples', '_meta', '_inner'];\n\n for (let i = 0; i < keysToRestore.length; ++i) {\n tmpObj[keysToRestore[i]] = obj[keysToRestore[i]];\n }\n\n obj = tmpObj;\n }\n\n obj._settings = obj._settings ? Settings.concat(obj._settings, schema._settings) : schema._settings;\n obj._valids.merge(schema._valids, schema._invalids);\n obj._invalids.merge(schema._invalids, schema._valids);\n obj._tests.push(...schema._tests);\n obj._refs.push(...schema._refs);\n if (obj._flags.empty && schema._flags.empty) {\n obj._flags.empty = obj._flags.empty.concat(schema._flags.empty);\n const flags = Object.assign({}, schema._flags);\n delete flags.empty;\n Hoek.merge(obj._flags, flags);\n }\n else if (schema._flags.empty) {\n obj._flags.empty = schema._flags.empty;\n const flags = Object.assign({}, schema._flags);\n delete flags.empty;\n Hoek.merge(obj._flags, flags);\n }\n else {\n Hoek.merge(obj._flags, schema._flags);\n }\n\n obj._description = schema._description || obj._description;\n obj._unit = schema._unit || obj._unit;\n obj._notes.push(...schema._notes);\n obj._tags.push(...schema._tags);\n obj._examples.push(...schema._examples);\n obj._meta.push(...schema._meta);\n\n const inners = Object.keys(schema._inner);\n const isObject = obj._type === 'object';\n for (let i = 0; i < inners.length; ++i) {\n const key = inners[i];\n const source = schema._inner[key];\n if (source) {\n const target = obj._inner[key];\n if (target) {\n if (isObject && key === 'children') {\n const keys = {};\n\n for (let j = 0; j < target.length; ++j) {\n keys[target[j].key] = j;\n }\n\n for (let j = 0; j < source.length; ++j) {\n const sourceKey = source[j].key;\n if (keys[sourceKey] >= 0) {\n target[keys[sourceKey]] = {\n key: sourceKey,\n schema: target[keys[sourceKey]].schema.concat(source[j].schema)\n };\n }\n else {\n target.push(source[j]);\n }\n }\n }\n else {\n obj._inner[key] = obj._inner[key].concat(source);\n }\n }\n else {\n obj._inner[key] = source.slice();\n }\n }\n }\n\n return obj;\n }\n\n _test(name, arg, func, options) {\n\n const obj = this.clone();\n obj._tests.push({ func, name, arg, options });\n return obj;\n }\n\n _testUnique(name, arg, func, options) {\n\n const obj = this.clone();\n obj._tests = obj._tests.filter((test) => test.name !== name);\n obj._tests.push({ func, name, arg, options });\n return obj;\n }\n\n options(options) {\n\n Hoek.assert(!options.context, 'Cannot override context');\n this.checkOptions(options);\n\n const obj = this.clone();\n obj._settings = Settings.concat(obj._settings, options);\n return obj;\n }\n\n strict(isStrict) {\n\n const obj = this.clone();\n\n const convert = isStrict === undefined ? false : !isStrict;\n obj._settings = Settings.concat(obj._settings, { convert });\n return obj;\n }\n\n raw(isRaw) {\n\n const value = isRaw === undefined ? true : isRaw;\n\n if (this._flags.raw === value) {\n return this;\n }\n\n const obj = this.clone();\n obj._flags.raw = value;\n return obj;\n }\n\n error(err, options = { self: false }) {\n\n Hoek.assert(err && (err instanceof Error || typeof err === 'function'), 'Must provide a valid Error object or a function');\n\n const unknownKeys = Object.keys(options).filter((k) => !['self'].includes(k));\n Hoek.assert(unknownKeys.length === 0, `Options ${unknownKeys} are unknown`);\n\n const obj = this.clone();\n obj._flags.error = err;\n\n if (options.self) {\n obj._flags.selfError = true;\n }\n\n return obj;\n }\n\n allow(...values) {\n\n const obj = this.clone();\n values = Hoek.flatten(values);\n for (let i = 0; i < values.length; ++i) {\n const value = values[i];\n\n Hoek.assert(value !== undefined, 'Cannot call allow/valid/invalid with undefined');\n obj._invalids.remove(value);\n obj._valids.add(value, obj._refs);\n }\n\n return obj;\n }\n\n valid(...values) {\n\n const obj = this.allow(...values);\n obj._flags.allowOnly = true;\n return obj;\n }\n\n invalid(...values) {\n\n const obj = this.clone();\n values = Hoek.flatten(values);\n for (let i = 0; i < values.length; ++i) {\n const value = values[i];\n\n Hoek.assert(value !== undefined, 'Cannot call allow/valid/invalid with undefined');\n obj._valids.remove(value);\n obj._invalids.add(value, obj._refs);\n }\n\n return obj;\n }\n\n required() {\n\n if (this._flags.presence === 'required') {\n return this;\n }\n\n const obj = this.clone();\n obj._flags.presence = 'required';\n return obj;\n }\n\n optional() {\n\n if (this._flags.presence === 'optional') {\n return this;\n }\n\n const obj = this.clone();\n obj._flags.presence = 'optional';\n return obj;\n }\n\n\n forbidden() {\n\n if (this._flags.presence === 'forbidden') {\n return this;\n }\n\n const obj = this.clone();\n obj._flags.presence = 'forbidden';\n return obj;\n }\n\n\n strip() {\n\n if (this._flags.strip) {\n return this;\n }\n\n const obj = this.clone();\n obj._flags.strip = true;\n return obj;\n }\n\n applyFunctionToChildren(children, fn, args = [], root) {\n\n children = [].concat(children);\n\n if (children.length !== 1 || children[0] !== '') {\n root = root ? (root + '.') : '';\n\n const extraChildren = (children[0] === '' ? children.slice(1) : children).map((child) => {\n\n return root + child;\n });\n\n throw new Error('unknown key(s) ' + extraChildren.join(', '));\n }\n\n return this[fn](...args);\n }\n\n default(value, description) {\n\n if (typeof value === 'function' &&\n !Ref.isRef(value)) {\n\n if (!value.description &&\n description) {\n\n value.description = description;\n }\n\n if (!this._flags.func) {\n Hoek.assert(typeof value.description === 'string' && value.description.length > 0, 'description must be provided when default value is a function');\n }\n }\n\n const obj = this.clone();\n obj._flags.default = value;\n Ref.push(obj._refs, value);\n return obj;\n }\n\n empty(schema) {\n\n const obj = this.clone();\n if (schema === undefined) {\n delete obj._flags.empty;\n }\n else {\n obj._flags.empty = Cast.schema(this._currentJoi, schema);\n }\n\n return obj;\n }\n\n when(condition, options) {\n\n Hoek.assert(options && typeof options === 'object', 'Invalid options');\n Hoek.assert(options.then !== undefined || options.otherwise !== undefined, 'options must have at least one of \"then\" or \"otherwise\"');\n\n const then = options.hasOwnProperty('then') ? this.concat(Cast.schema(this._currentJoi, options.then)) : undefined;\n const otherwise = options.hasOwnProperty('otherwise') ? this.concat(Cast.schema(this._currentJoi, options.otherwise)) : undefined;\n\n Alternatives = Alternatives || require('../alternatives');\n\n const alternativeOptions = { then, otherwise };\n if (Object.prototype.hasOwnProperty.call(options, 'is')) {\n alternativeOptions.is = options.is;\n }\n\n const obj = Alternatives.when(condition, alternativeOptions);\n obj._flags.presence = 'ignore';\n obj._baseType = this;\n\n return obj;\n }\n\n description(desc) {\n\n Hoek.assert(desc && typeof desc === 'string', 'Description must be a non-empty string');\n\n const obj = this.clone();\n obj._description = desc;\n return obj;\n }\n\n notes(notes) {\n\n Hoek.assert(notes && (typeof notes === 'string' || Array.isArray(notes)), 'Notes must be a non-empty string or array');\n\n const obj = this.clone();\n obj._notes = obj._notes.concat(notes);\n return obj;\n }\n\n tags(tags) {\n\n Hoek.assert(tags && (typeof tags === 'string' || Array.isArray(tags)), 'Tags must be a non-empty string or array');\n\n const obj = this.clone();\n obj._tags = obj._tags.concat(tags);\n return obj;\n }\n\n meta(meta) {\n\n Hoek.assert(meta !== undefined, 'Meta cannot be undefined');\n\n const obj = this.clone();\n obj._meta = obj._meta.concat(meta);\n return obj;\n }\n\n example(...examples) {\n\n Hoek.assert(examples.length > 0, 'Missing examples');\n\n const processed = [];\n for (let i = 0; i < examples.length; ++i) {\n const example = [].concat(examples[i]);\n Hoek.assert(example.length <= 2, `Bad example format at index ${i}`);\n\n const value = example[0];\n let options = example[1];\n if (options !== undefined) {\n Hoek.assert(options && typeof options === 'object', `Options for example at index ${i} must be an object`);\n const unknownOptions = Object.keys(options).filter((option) => !['parent', 'context'].includes(option));\n Hoek.assert(unknownOptions.length === 0, `Unknown example options ${unknownOptions} at index ${i}`);\n }\n else {\n options = {};\n }\n\n const localState = new State('', [], options.parent || null);\n const result = this._validate(value, localState, Settings.concat(internals.defaults, options.context ? { context: options.context } : null));\n Hoek.assert(!result.errors, `Bad example at index ${i}:`, result.errors && Errors.process(result.errors, value));\n\n const ex = { value };\n if (Object.keys(options).length) {\n ex.options = options;\n }\n\n processed.push(ex);\n }\n\n const obj = this.clone();\n obj._examples = processed;\n return obj;\n }\n\n unit(name) {\n\n Hoek.assert(name && typeof name === 'string', 'Unit name must be a non-empty string');\n\n const obj = this.clone();\n obj._unit = name;\n return obj;\n }\n\n _prepareEmptyValue(value) {\n\n if (typeof value === 'string' && this._flags.trim) {\n return value.trim();\n }\n\n return value;\n }\n\n _validate(value, state, options, reference) {\n\n const originalValue = value;\n\n // Setup state and settings\n\n state = state || new State('', [], null, reference);\n\n if (this._settings) {\n const isDefaultOptions = options === internals.defaults;\n if (isDefaultOptions && this._settings[Symbols.settingsCache]) {\n options = this._settings[Symbols.settingsCache];\n }\n else {\n options = Settings.concat(this._language ? Settings.concat({ language: this._language }, options) : options, this._settings);\n if (isDefaultOptions) {\n this._settings[Symbols.settingsCache] = options;\n }\n }\n }\n else if (this._language) {\n options = Settings.concat({ language: this._language }, options);\n }\n\n let errors = [];\n\n if (this._coerce) {\n const coerced = this._coerce(value, state, options);\n if (coerced.errors) {\n value = coerced.value;\n errors = errors.concat(coerced.errors);\n return this._finalizeValue(value, originalValue, errors, state, options); // Coerced error always aborts early\n }\n\n value = coerced.value;\n }\n\n if (this._flags.empty && !this._flags.empty._validate(this._prepareEmptyValue(value), null, internals.defaults).errors) {\n value = undefined;\n }\n\n // Check presence requirements\n\n const presence = this._flags.presence || options.presence;\n if (presence === 'optional') {\n if (value === undefined) {\n const isDeepDefault = this._flags.hasOwnProperty('default') && this._flags.default === undefined;\n if (isDeepDefault && this._type === 'object') {\n value = {};\n }\n else {\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n }\n }\n else if (presence === 'required' &&\n value === undefined) {\n\n errors.push(this.createError('any.required', null, state, options));\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n else if (presence === 'forbidden') {\n if (value === undefined) {\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n\n errors.push(this.createError('any.unknown', null, state, options));\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n\n // Check allowed and denied values using the original value\n\n let match = this._valids.get(value, state, options, this._flags.insensitive);\n if (match) {\n if (options.convert) {\n value = match.value;\n }\n\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n\n if (this._invalids.has(value, state, options, this._flags.insensitive)) {\n errors.push(this.createError(value === '' ? 'any.empty' : 'any.invalid', { value, invalids: this._invalids.values({ stripUndefined: true }) }, state, options));\n if (options.abortEarly) {\n\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n }\n\n // Convert value and validate type\n\n if (this._base) {\n const base = this._base(value, state, options);\n if (base.errors) {\n value = base.value;\n errors = errors.concat(base.errors);\n return this._finalizeValue(value, originalValue, errors, state, options); // Base error always aborts early\n }\n\n if (base.value !== value) {\n value = base.value;\n\n // Check allowed and denied values using the converted value\n\n match = this._valids.get(value, state, options, this._flags.insensitive);\n if (match) {\n value = match.value;\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n\n if (this._invalids.has(value, state, options, this._flags.insensitive)) {\n errors.push(this.createError(value === '' ? 'any.empty' : 'any.invalid', { value, invalids: this._invalids.values({ stripUndefined: true }) }, state, options));\n if (options.abortEarly) {\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n }\n }\n }\n\n // Required values did not match\n\n if (this._flags.allowOnly) {\n errors.push(this.createError('any.allowOnly', { value, valids: this._valids.values({ stripUndefined: true }) }, state, options));\n if (options.abortEarly) {\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n }\n\n // Validate tests\n\n for (let i = 0; i < this._tests.length; ++i) {\n const test = this._tests[i];\n const ret = test.func.call(this, value, state, options);\n if (ret instanceof Errors.Err) {\n errors.push(ret);\n if (options.abortEarly) {\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n }\n else {\n value = ret;\n }\n }\n\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n\n _finalizeValue(value, originalValue, errors, state, options) {\n\n let finalValue;\n\n if (value !== undefined) {\n finalValue = this._flags.raw ? originalValue : value;\n }\n else if (options.noDefaults) {\n finalValue = value;\n }\n else if (Ref.isRef(this._flags.default)) {\n finalValue = this._flags.default(state.parent, options);\n }\n else if (typeof this._flags.default === 'function' &&\n !(this._flags.func && !this._flags.default.description)) {\n\n let args;\n\n if (state.parent !== null &&\n this._flags.default.length > 0) {\n\n args = [Hoek.clone(state.parent), options];\n }\n\n const defaultValue = internals._try(this._flags.default, args);\n finalValue = defaultValue.value;\n if (defaultValue.error) {\n errors.push(this.createError('any.default', { error: defaultValue.error }, state, options));\n }\n }\n else {\n finalValue = Hoek.clone(this._flags.default);\n }\n\n if (errors.length &&\n typeof this._flags.error === 'function' &&\n (\n !this._flags.selfError ||\n errors.some((e) => state.path.length === e.path.length)\n )\n ) {\n const change = this._flags.error.call(this, errors);\n\n if (typeof change === 'string') {\n errors = [this.createOverrideError('override', { reason: errors }, state, options, change)];\n }\n else {\n errors = [].concat(change)\n .map((err) => {\n\n return err instanceof Error ?\n err :\n this.createOverrideError(err.type || 'override', err.context, state, options, err.message, err.template);\n });\n }\n }\n\n return {\n value: this._flags.strip ? undefined : finalValue,\n finalValue,\n errors: errors.length ? errors : null\n };\n }\n\n _validateWithOptions(value, options, callback) {\n\n if (options) {\n this.checkOptions(options);\n }\n\n const settings = Settings.concat(internals.defaults, options);\n const result = this._validate(value, null, settings);\n const errors = Errors.process(result.errors, value);\n\n if (callback) {\n return callback(errors, result.value);\n }\n\n return {\n error: errors,\n value: result.value,\n then(resolve, reject) {\n\n if (errors) {\n return Promise.reject(errors).catch(reject);\n }\n\n return Promise.resolve(result.value).then(resolve);\n },\n catch(reject) {\n\n if (errors) {\n return Promise.reject(errors).catch(reject);\n }\n\n return Promise.resolve(result.value);\n }\n };\n }\n\n validate(value, options, callback) {\n\n if (typeof options === 'function') {\n return this._validateWithOptions(value, null, options);\n }\n\n return this._validateWithOptions(value, options, callback);\n }\n\n describe() {\n\n const description = {\n type: this._type\n };\n\n const flags = Object.keys(this._flags);\n if (flags.length) {\n if (['empty', 'default', 'lazy', 'label'].some((flag) => this._flags.hasOwnProperty(flag))) {\n description.flags = {};\n for (let i = 0; i < flags.length; ++i) {\n const flag = flags[i];\n if (flag === 'empty') {\n description.flags[flag] = this._flags[flag].describe();\n }\n else if (flag === 'default') {\n if (Ref.isRef(this._flags[flag])) {\n description.flags[flag] = this._flags[flag].toString();\n }\n else if (typeof this._flags[flag] === 'function') {\n description.flags[flag] = {\n description: this._flags[flag].description,\n function : this._flags[flag]\n };\n }\n else {\n description.flags[flag] = this._flags[flag];\n }\n }\n else if (flag === 'lazy' || flag === 'label') {\n // We don't want it in the description\n }\n else {\n description.flags[flag] = this._flags[flag];\n }\n }\n }\n else {\n description.flags = this._flags;\n }\n }\n\n if (this._settings) {\n description.options = Hoek.clone(this._settings);\n }\n\n if (this._baseType) {\n description.base = this._baseType.describe();\n }\n\n if (this._description) {\n description.description = this._description;\n }\n\n if (this._notes.length) {\n description.notes = this._notes;\n }\n\n if (this._tags.length) {\n description.tags = this._tags;\n }\n\n if (this._meta.length) {\n description.meta = this._meta;\n }\n\n if (this._examples.length) {\n description.examples = this._examples;\n }\n\n if (this._unit) {\n description.unit = this._unit;\n }\n\n const valids = this._valids.values();\n if (valids.length) {\n description.valids = valids.map((v) => {\n\n return Ref.isRef(v) ? v.toString() : v;\n });\n }\n\n const invalids = this._invalids.values();\n if (invalids.length) {\n description.invalids = invalids.map((v) => {\n\n return Ref.isRef(v) ? v.toString() : v;\n });\n }\n\n description.rules = [];\n\n for (let i = 0; i < this._tests.length; ++i) {\n const validator = this._tests[i];\n const item = { name: validator.name };\n\n if (validator.arg !== void 0) {\n item.arg = Ref.isRef(validator.arg) ? validator.arg.toString() : validator.arg;\n }\n\n const options = validator.options;\n if (options) {\n if (options.hasRef) {\n item.arg = {};\n const keys = Object.keys(validator.arg);\n for (let j = 0; j < keys.length; ++j) {\n const key = keys[j];\n const value = validator.arg[key];\n item.arg[key] = Ref.isRef(value) ? value.toString() : value;\n }\n }\n\n if (typeof options.description === 'string') {\n item.description = options.description;\n }\n else if (typeof options.description === 'function') {\n item.description = options.description(item.arg);\n }\n }\n\n description.rules.push(item);\n }\n\n if (!description.rules.length) {\n delete description.rules;\n }\n\n const label = this._getLabel();\n if (label) {\n description.label = label;\n }\n\n return description;\n }\n\n label(name) {\n\n Hoek.assert(name && typeof name === 'string', 'Label name must be a non-empty string');\n\n const obj = this.clone();\n obj._flags.label = name;\n return obj;\n }\n\n _getLabel(def) {\n\n return this._flags.label || def;\n }\n\n}]" } } ], "_refs": [], "_flags": {}, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "children": null, "renames": [], "dependencies": [], "patterns": [] } } } ] } } }, { "schema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "object", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [ { "func": function (value, state, options) {\n\n if (value instanceof constructor) {\n return value;\n }\n\n return this.createError('object.type', { type: typeData.name, value }, state, options);\n }, "name": "type", "arg": { "name": "Joi object", "ctor": "[class extends Any {\n\n constructor() {\n\n super();\n this._type = 'object';\n this._inner.children = null;\n this._inner.renames = [];\n this._inner.dependencies = [];\n this._inner.patterns = [];\n }\n\n _init(...args) {\n\n return args.length ? this.keys(...args) : this;\n }\n\n _base(value, state, options) {\n\n let target = value;\n const errors = [];\n const finish = () => {\n\n return {\n value: target,\n errors: errors.length ? errors : null\n };\n };\n\n if (typeof value === 'string' &&\n options.convert) {\n\n if (value.length > 1 &&\n (value[0] === '{' || /^\\s*\\{/.test(value))) {\n\n try {\n value = Bourne.parse(value);\n }\n catch (e) { }\n }\n }\n\n const type = this._flags.func ? 'function' : 'object';\n if (!value ||\n typeof value !== type ||\n Array.isArray(value)) {\n\n errors.push(this.createError(type + '.base', { value }, state, options));\n return finish();\n }\n\n // Skip if there are no other rules to test\n\n if (!this._inner.renames.length &&\n !this._inner.dependencies.length &&\n !this._inner.children && // null allows any keys\n !this._inner.patterns.length) {\n\n target = value;\n return finish();\n }\n\n // Ensure target is a local copy (parsed) or shallow copy\n\n if (target === value) {\n if (type === 'object') {\n target = Object.create(Object.getPrototypeOf(value));\n }\n else {\n target = function (...args) {\n\n return value.apply(this, args);\n };\n\n target.prototype = Hoek.clone(value.prototype);\n }\n\n const valueKeys = Object.keys(value);\n for (let i = 0; i < valueKeys.length; ++i) {\n target[valueKeys[i]] = value[valueKeys[i]];\n }\n }\n else {\n target = value;\n }\n\n // Rename keys\n\n const renamed = {};\n for (let i = 0; i < this._inner.renames.length; ++i) {\n const rename = this._inner.renames[i];\n\n if (rename.isRegExp) {\n const targetKeys = Object.keys(target);\n const matchedTargetKeys = [];\n\n for (let j = 0; j < targetKeys.length; ++j) {\n if (rename.from.test(targetKeys[j])) {\n matchedTargetKeys.push(targetKeys[j]);\n }\n }\n\n const allUndefined = matchedTargetKeys.every((key) => target[key] === undefined);\n if (rename.options.ignoreUndefined && allUndefined) {\n continue;\n }\n\n if (!rename.options.multiple &&\n renamed[rename.to]) {\n\n errors.push(this.createError('object.rename.regex.multiple', { from: matchedTargetKeys, to: rename.to }, state, options));\n if (options.abortEarly) {\n return finish();\n }\n }\n\n if (Object.prototype.hasOwnProperty.call(target, rename.to) &&\n !rename.options.override &&\n !renamed[rename.to]) {\n\n errors.push(this.createError('object.rename.regex.override', { from: matchedTargetKeys, to: rename.to }, state, options));\n if (options.abortEarly) {\n return finish();\n }\n }\n\n if (allUndefined) {\n delete target[rename.to];\n }\n else {\n target[rename.to] = target[matchedTargetKeys[matchedTargetKeys.length - 1]];\n }\n\n renamed[rename.to] = true;\n\n if (!rename.options.alias) {\n for (let j = 0; j < matchedTargetKeys.length; ++j) {\n delete target[matchedTargetKeys[j]];\n }\n }\n }\n else {\n if (rename.options.ignoreUndefined && target[rename.from] === undefined) {\n continue;\n }\n\n if (!rename.options.multiple &&\n renamed[rename.to]) {\n\n errors.push(this.createError('object.rename.multiple', { from: rename.from, to: rename.to }, state, options));\n if (options.abortEarly) {\n return finish();\n }\n }\n\n if (Object.prototype.hasOwnProperty.call(target, rename.to) &&\n !rename.options.override &&\n !renamed[rename.to]) {\n\n errors.push(this.createError('object.rename.override', { from: rename.from, to: rename.to }, state, options));\n if (options.abortEarly) {\n return finish();\n }\n }\n\n if (target[rename.from] === undefined) {\n delete target[rename.to];\n }\n else {\n target[rename.to] = target[rename.from];\n }\n\n renamed[rename.to] = true;\n\n if (!rename.options.alias) {\n delete target[rename.from];\n }\n }\n }\n\n // Validate schema\n\n if (!this._inner.children && // null allows any keys\n !this._inner.patterns.length &&\n !this._inner.dependencies.length) {\n\n return finish();\n }\n\n const unprocessed = new Set(Object.keys(target));\n\n if (this._inner.children) {\n const stripProps = [];\n\n for (let i = 0; i < this._inner.children.length; ++i) {\n const child = this._inner.children[i];\n const key = child.key;\n const item = target[key];\n\n unprocessed.delete(key);\n\n const localState = new State(key, [...state.path, key], target, state.reference);\n const result = child.schema._validate(item, localState, options);\n if (result.errors) {\n errors.push(this.createError('object.child', { key, child: child.schema._getLabel(key), reason: result.errors }, localState, options));\n\n if (options.abortEarly) {\n return finish();\n }\n }\n else {\n if (child.schema._flags.strip || (result.value === undefined && result.value !== item)) {\n stripProps.push(key);\n target[key] = result.finalValue;\n }\n else if (result.value !== undefined) {\n target[key] = result.value;\n }\n }\n }\n\n for (let i = 0; i < stripProps.length; ++i) {\n delete target[stripProps[i]];\n }\n }\n\n // Unknown keys\n\n if (unprocessed.size && this._inner.patterns.length) {\n\n for (const key of unprocessed) {\n const localState = new State(key, [...state.path, key], target, state.reference);\n const item = target[key];\n\n for (let i = 0; i < this._inner.patterns.length; ++i) {\n const pattern = this._inner.patterns[i];\n\n if (pattern.regex ?\n pattern.regex.test(key) :\n !pattern.schema._validate(key, state, { ...options, abortEarly:true }).errors) {\n\n unprocessed.delete(key);\n\n const result = pattern.rule._validate(item, localState, options);\n if (result.errors) {\n errors.push(this.createError('object.child', {\n key,\n child: pattern.rule._getLabel(key),\n reason: result.errors\n }, localState, options));\n\n if (options.abortEarly) {\n return finish();\n }\n }\n\n target[key] = result.value;\n }\n }\n }\n }\n\n if (unprocessed.size && (this._inner.children || this._inner.patterns.length)) {\n if ((options.stripUnknown && this._flags.allowUnknown !== true) ||\n options.skipFunctions) {\n\n const stripUnknown = options.stripUnknown\n ? (options.stripUnknown === true ? true : !!options.stripUnknown.objects)\n : false;\n\n\n for (const key of unprocessed) {\n if (stripUnknown) {\n delete target[key];\n unprocessed.delete(key);\n }\n else if (typeof target[key] === 'function') {\n unprocessed.delete(key);\n }\n }\n }\n\n if ((this._flags.allowUnknown !== undefined ? !this._flags.allowUnknown : !options.allowUnknown)) {\n\n for (const unprocessedKey of unprocessed) {\n errors.push(this.createError('object.allowUnknown', { child: unprocessedKey, value: target[unprocessedKey] }, {\n key: unprocessedKey,\n path: [...state.path, unprocessedKey]\n }, options, {}));\n }\n }\n }\n\n // Validate dependencies\n\n for (let i = 0; i < this._inner.dependencies.length; ++i) {\n const dep = this._inner.dependencies[i];\n const hasKey = dep.key !== null;\n const splitKey = hasKey && dep.key.split('.');\n const localState = hasKey ? new State(splitKey[splitKey.length - 1], [...state.path, ...splitKey]) : new State(null, state.path);\n const err = internals[dep.type].call(this, dep.key, hasKey && Hoek.reach(target, dep.key, { functions: true }), dep.peers, target, localState, options);\n if (err instanceof Errors.Err) {\n errors.push(err);\n if (options.abortEarly) {\n return finish();\n }\n }\n }\n\n return finish();\n }\n\n keys(schema) {\n\n Hoek.assert(schema === null || schema === undefined || typeof schema === 'object', 'Object schema must be a valid object');\n Hoek.assert(!schema || !(schema instanceof Any), 'Object schema cannot be a joi schema');\n\n const obj = this.clone();\n\n if (!schema) {\n obj._inner.children = null;\n return obj;\n }\n\n const children = Object.keys(schema);\n\n if (!children.length) {\n obj._inner.children = [];\n return obj;\n }\n\n const topo = new Topo();\n if (obj._inner.children) {\n for (let i = 0; i < obj._inner.children.length; ++i) {\n const child = obj._inner.children[i];\n\n // Only add the key if we are not going to replace it later\n if (!children.includes(child.key)) {\n topo.add(child, { after: child._refs, group: child.key });\n }\n }\n }\n\n for (let i = 0; i < children.length; ++i) {\n const key = children[i];\n const child = schema[key];\n try {\n const cast = Cast.schema(this._currentJoi, child);\n topo.add({ key, schema: cast }, { after: cast._refs, group: key });\n }\n catch (castErr) {\n if (castErr.hasOwnProperty('path')) {\n castErr.path = key + '.' + castErr.path;\n }\n else {\n castErr.path = key;\n }\n\n throw castErr;\n }\n }\n\n obj._inner.children = topo.nodes;\n\n return obj;\n }\n\n append(schema) {\n // Skip any changes\n if (schema === null || schema === undefined || Object.keys(schema).length === 0) {\n return this;\n }\n\n return this.keys(schema);\n }\n\n unknown(allow) {\n\n const value = allow !== false;\n\n if (this._flags.allowUnknown === value) {\n return this;\n }\n\n const obj = this.clone();\n obj._flags.allowUnknown = value;\n return obj;\n }\n\n length(limit) {\n\n Hoek.assert(Number.isSafeInteger(limit) && limit >= 0, 'limit must be a positive integer');\n\n return this._test('length', limit, function (value, state, options) {\n\n if (Object.keys(value).length === limit) {\n return value;\n }\n\n return this.createError('object.length', { limit, value }, state, options);\n });\n }\n\n min(limit) {\n\n Hoek.assert(Number.isSafeInteger(limit) && limit >= 0, 'limit must be a positive integer');\n\n return this._test('min', limit, function (value, state, options) {\n\n if (Object.keys(value).length >= limit) {\n return value;\n }\n\n return this.createError('object.min', { limit, value }, state, options);\n });\n }\n\n max(limit) {\n\n Hoek.assert(Number.isSafeInteger(limit) && limit >= 0, 'limit must be a positive integer');\n\n return this._test('max', limit, function (value, state, options) {\n\n if (Object.keys(value).length <= limit) {\n return value;\n }\n\n return this.createError('object.max', { limit, value }, state, options);\n });\n }\n\n pattern(pattern, schema) {\n\n const isRegExp = pattern instanceof RegExp;\n Hoek.assert(isRegExp || pattern instanceof Any, 'pattern must be a regex or schema');\n Hoek.assert(schema !== undefined, 'Invalid rule');\n\n if (isRegExp) {\n Hoek.assert(!pattern.flags.includes('g') && !pattern.flags.includes('y'), 'pattern should not use global or sticky mode');\n }\n\n try {\n schema = Cast.schema(this._currentJoi, schema);\n }\n catch (castErr) {\n if (castErr.hasOwnProperty('path')) {\n castErr.message = `${castErr.message}(${castErr.path})`;\n }\n\n throw castErr;\n }\n\n const obj = this.clone();\n if (isRegExp) {\n obj._inner.patterns.push({ regex: pattern, rule: schema });\n }\n else {\n obj._inner.patterns.push({ schema: pattern, rule: schema });\n }\n\n return obj;\n }\n\n schema() {\n\n return this._test('schema', null, function (value, state, options) {\n\n if (value instanceof Any) {\n return value;\n }\n\n return this.createError('object.schema', null, state, options);\n });\n }\n\n with(key, peers) {\n\n Hoek.assert(arguments.length === 2, 'Invalid number of arguments, expected 2.');\n\n return this._dependency('with', key, peers);\n }\n\n without(key, peers) {\n\n Hoek.assert(arguments.length === 2, 'Invalid number of arguments, expected 2.');\n\n return this._dependency('without', key, peers);\n }\n\n xor(...peers) {\n\n peers = Hoek.flatten(peers);\n return this._dependency('xor', null, peers);\n }\n\n oxor(...peers) {\n\n return this._dependency('oxor', null, peers);\n }\n\n or(...peers) {\n\n peers = Hoek.flatten(peers);\n return this._dependency('or', null, peers);\n }\n\n and(...peers) {\n\n peers = Hoek.flatten(peers);\n return this._dependency('and', null, peers);\n }\n\n nand(...peers) {\n\n peers = Hoek.flatten(peers);\n return this._dependency('nand', null, peers);\n }\n\n requiredKeys(...children) {\n\n children = Hoek.flatten(children);\n return this.applyFunctionToChildren(children, 'required');\n }\n\n optionalKeys(...children) {\n\n children = Hoek.flatten(children);\n return this.applyFunctionToChildren(children, 'optional');\n }\n\n forbiddenKeys(...children) {\n\n children = Hoek.flatten(children);\n return this.applyFunctionToChildren(children, 'forbidden');\n }\n\n rename(from, to, options) {\n\n Hoek.assert(typeof from === 'string' || from instanceof RegExp, 'Rename missing the from argument');\n Hoek.assert(typeof to === 'string', 'Rename missing the to argument');\n Hoek.assert(to !== from, 'Cannot rename key to same name:', from);\n\n for (let i = 0; i < this._inner.renames.length; ++i) {\n Hoek.assert(this._inner.renames[i].from !== from, 'Cannot rename the same key multiple times');\n }\n\n const obj = this.clone();\n\n obj._inner.renames.push({\n from,\n to,\n options: Hoek.applyToDefaults(internals.renameDefaults, options || {}),\n isRegExp: from instanceof RegExp\n });\n\n return obj;\n }\n\n applyFunctionToChildren(children, fn, args = [], root) {\n\n children = [].concat(children);\n Hoek.assert(children.length > 0, 'expected at least one children');\n\n const groupedChildren = internals.groupChildren(children);\n let obj;\n\n if ('' in groupedChildren) {\n obj = this[fn](...args);\n delete groupedChildren[''];\n }\n else {\n obj = this.clone();\n }\n\n if (obj._inner.children) {\n root = root ? (root + '.') : '';\n\n for (let i = 0; i < obj._inner.children.length; ++i) {\n const child = obj._inner.children[i];\n const group = groupedChildren[child.key];\n\n if (group) {\n obj._inner.children[i] = {\n key: child.key,\n _refs: child._refs,\n schema: child.schema.applyFunctionToChildren(group, fn, args, root + child.key)\n };\n\n delete groupedChildren[child.key];\n }\n }\n }\n\n const remaining = Object.keys(groupedChildren);\n Hoek.assert(remaining.length === 0, 'unknown key(s)', remaining.join(', '));\n\n return obj;\n }\n\n _dependency(type, key, peers) {\n\n peers = [].concat(peers);\n for (let i = 0; i < peers.length; ++i) {\n Hoek.assert(typeof peers[i] === 'string', type, 'peers must be a string or array of strings');\n }\n\n const obj = this.clone();\n obj._inner.dependencies.push({ type, key, peers });\n return obj;\n }\n\n describe(shallow) {\n\n const description = super.describe();\n\n if (description.rules) {\n for (let i = 0; i < description.rules.length; ++i) {\n const rule = description.rules[i];\n // Coverage off for future-proof descriptions, only object().assert() is use right now\n if (/* $lab:coverage:off$ */rule.arg &&\n typeof rule.arg === 'object' &&\n rule.arg.schema &&\n rule.arg.ref /* $lab:coverage:on$ */) {\n rule.arg = {\n schema: rule.arg.schema.describe(),\n ref: rule.arg.ref.toString()\n };\n }\n }\n }\n\n if (this._inner.children &&\n !shallow) {\n\n description.children = {};\n for (let i = 0; i < this._inner.children.length; ++i) {\n const child = this._inner.children[i];\n description.children[child.key] = child.schema.describe();\n }\n }\n\n if (this._inner.dependencies.length) {\n description.dependencies = Hoek.clone(this._inner.dependencies);\n }\n\n if (this._inner.patterns.length) {\n description.patterns = [];\n\n for (let i = 0; i < this._inner.patterns.length; ++i) {\n const pattern = this._inner.patterns[i];\n if (pattern.regex) {\n description.patterns.push({ regex: pattern.regex.toString(), rule: pattern.rule.describe() });\n }\n else {\n description.patterns.push({ schema: pattern.schema.describe(), rule: pattern.rule.describe() });\n }\n }\n }\n\n if (this._inner.renames.length > 0) {\n description.renames = Hoek.clone(this._inner.renames);\n }\n\n return description;\n }\n\n assert(ref, schema, message) {\n\n ref = Cast.ref(ref);\n Hoek.assert(ref.isContext || ref.depth > 1, 'Cannot use assertions for root level references - use direct key rules instead');\n message = message || 'pass the assertion test';\n Hoek.assert(typeof message === 'string', 'Message must be a string');\n\n try {\n schema = Cast.schema(this._currentJoi, schema);\n }\n catch (castErr) {\n if (castErr.hasOwnProperty('path')) {\n castErr.message = `${castErr.message}(${castErr.path})`;\n }\n\n throw castErr;\n }\n\n const key = ref.path[ref.path.length - 1];\n const path = ref.path.join('.');\n\n return this._test('assert', { schema, ref }, function (value, state, options) {\n\n const result = schema._validate(ref(value), null, options, value);\n if (!result.errors) {\n return value;\n }\n\n const localState = new State(key, ref.path, state.parent, state.reference);\n return this.createError('object.assert', { ref: path, message }, localState, options);\n });\n }\n\n type(constructor, name = constructor.name) {\n\n Hoek.assert(typeof constructor === 'function', 'type must be a constructor function');\n const typeData = {\n name,\n ctor: constructor\n };\n\n return this._test('type', typeData, function (value, state, options) {\n\n if (value instanceof constructor) {\n return value;\n }\n\n return this.createError('object.type', { type: typeData.name, value }, state, options);\n });\n }\n}]" } } ], "_refs": [], "_flags": {}, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "children": null, "renames": [], "dependencies": [], "patterns": [] } } } ] } } }, { "key": "description", "schema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "alternatives", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [], "_refs": [], "_flags": {}, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "matches": [ { "schema": { "isJoi": true, "_type": "string", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": 0 }, "_tests": [], "_refs": [], "_flags": {}, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": {}, "_currentJoi": "[Circular ~.base._currentJoi]" } }, { "schema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "object", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [ { "func": function (value, state, options) {\n\n if (value.length === n) {\n return value;\n }\n\n return this.createError('function.arity', { n }, state, options);\n }, "name": "arity", "arg": 1 } ], "_refs": [], "_flags": { "func": true }, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "children": null, "renames": [], "dependencies": [], "patterns": [] } } } ] } } } ], "renames": [], "dependencies": [ { "type": "or", "key": null, "peers": [ "setup", "validate" ] } ], "patterns": [] } } ], "ordereds": [], "inclusions": [ { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "object", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [], "_refs": [], "_flags": {}, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "children": [ { "key": "name", "schema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "string", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": 0 }, "_tests": [], "_refs": [], "_flags": { "presence": "required" }, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": {} } }, { "key": "setup", "schema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "object", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [ { "func": function (value, state, options) {\n\n if (value.length === n) {\n return value;\n }\n\n return this.createError('function.arity', { n }, state, options);\n }, "name": "arity", "arg": 1 } ], "_refs": [], "_flags": { "func": true }, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "children": null, "renames": [], "dependencies": [], "patterns": [] } } }, { "key": "validate", "schema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "object", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [ { "func": function (value, state, options) {\n\n if (value.length === n) {\n return value;\n }\n\n return this.createError('function.arity', { n }, state, options);\n }, "name": "arity", "arg": 4 } ], "_refs": [], "_flags": { "func": true }, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "children": null, "renames": [], "dependencies": [], "patterns": [] } } }, { "key": "params", "schema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "alternatives", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [], "_refs": [], "_flags": {}, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "matches": [ { "schema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "object", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [], "_refs": [], "_flags": {}, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "children": null, "renames": [], "dependencies": [], "patterns": [ { "regex": {}, "rule": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "object", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [ { "func": function (value, state, options) {\n\n if (value instanceof constructor) {\n return value;\n }\n\n return this.createError('object.type', { type: typeData.name, value }, state, options);\n }, "name": "type", "arg": { "name": "Joi object", "ctor": "[class {\n\n constructor() {\n\n this.isJoi = true;\n this._type = 'any';\n this._settings = null;\n this._valids = new internals.Set();\n this._invalids = new internals.Set();\n this._tests = [];\n this._refs = [];\n this._flags = {\n /*\n presence: 'optional', // optional, required, forbidden, ignore\n allowOnly: false,\n allowUnknown: undefined,\n default: undefined,\n forbidden: false,\n encoding: undefined,\n insensitive: false,\n trim: false,\n normalize: undefined, // NFC, NFD, NFKC, NFKD\n case: undefined, // upper, lower\n empty: undefined,\n func: false,\n raw: false\n */\n };\n\n this._description = null;\n this._unit = null;\n this._notes = [];\n this._tags = [];\n this._examples = [];\n this._meta = [];\n\n this._inner = {}; // Hash of arrays of immutable objects\n }\n\n _init() {\n\n return this;\n }\n\n get schemaType() {\n\n return this._type;\n }\n\n createError(type, context, state, options, flags = this._flags) {\n\n return Errors.create(type, context, state, options, flags);\n }\n\n createOverrideError(type, context, state, options, message, template) {\n\n return Errors.create(type, context, state, options, this._flags, message, template);\n }\n\n checkOptions(options) {\n\n Schemas = Schemas || require('../../schemas');\n\n const result = Schemas.options.validate(options);\n\n if (result.error) {\n throw new Error(result.error.details[0].message);\n }\n }\n\n clone() {\n\n const obj = Object.create(Object.getPrototypeOf(this));\n\n obj.isJoi = true;\n obj._currentJoi = this._currentJoi;\n obj._type = this._type;\n obj._settings = this._settings;\n obj._baseType = this._baseType;\n obj._valids = this._valids.slice();\n obj._invalids = this._invalids.slice();\n obj._tests = this._tests.slice();\n obj._refs = this._refs.slice();\n obj._flags = Hoek.clone(this._flags);\n\n obj._description = this._description;\n obj._unit = this._unit;\n obj._notes = this._notes.slice();\n obj._tags = this._tags.slice();\n obj._examples = this._examples.slice();\n obj._meta = this._meta.slice();\n\n obj._inner = {};\n const inners = Object.keys(this._inner);\n for (let i = 0; i < inners.length; ++i) {\n const key = inners[i];\n obj._inner[key] = this._inner[key] ? this._inner[key].slice() : null;\n }\n\n return obj;\n }\n\n concat(schema) {\n\n Hoek.assert(schema instanceof internals.Any, 'Invalid schema object');\n Hoek.assert(this._type === 'any' || schema._type === 'any' || schema._type === this._type, 'Cannot merge type', this._type, 'with another type:', schema._type);\n\n let obj = this.clone();\n\n if (this._type === 'any' && schema._type !== 'any') {\n\n // Reset values as if we were \"this\"\n const tmpObj = schema.clone();\n const keysToRestore = ['_settings', '_valids', '_invalids', '_tests', '_refs', '_flags', '_description', '_unit',\n '_notes', '_tags', '_examples', '_meta', '_inner'];\n\n for (let i = 0; i < keysToRestore.length; ++i) {\n tmpObj[keysToRestore[i]] = obj[keysToRestore[i]];\n }\n\n obj = tmpObj;\n }\n\n obj._settings = obj._settings ? Settings.concat(obj._settings, schema._settings) : schema._settings;\n obj._valids.merge(schema._valids, schema._invalids);\n obj._invalids.merge(schema._invalids, schema._valids);\n obj._tests.push(...schema._tests);\n obj._refs.push(...schema._refs);\n if (obj._flags.empty && schema._flags.empty) {\n obj._flags.empty = obj._flags.empty.concat(schema._flags.empty);\n const flags = Object.assign({}, schema._flags);\n delete flags.empty;\n Hoek.merge(obj._flags, flags);\n }\n else if (schema._flags.empty) {\n obj._flags.empty = schema._flags.empty;\n const flags = Object.assign({}, schema._flags);\n delete flags.empty;\n Hoek.merge(obj._flags, flags);\n }\n else {\n Hoek.merge(obj._flags, schema._flags);\n }\n\n obj._description = schema._description || obj._description;\n obj._unit = schema._unit || obj._unit;\n obj._notes.push(...schema._notes);\n obj._tags.push(...schema._tags);\n obj._examples.push(...schema._examples);\n obj._meta.push(...schema._meta);\n\n const inners = Object.keys(schema._inner);\n const isObject = obj._type === 'object';\n for (let i = 0; i < inners.length; ++i) {\n const key = inners[i];\n const source = schema._inner[key];\n if (source) {\n const target = obj._inner[key];\n if (target) {\n if (isObject && key === 'children') {\n const keys = {};\n\n for (let j = 0; j < target.length; ++j) {\n keys[target[j].key] = j;\n }\n\n for (let j = 0; j < source.length; ++j) {\n const sourceKey = source[j].key;\n if (keys[sourceKey] >= 0) {\n target[keys[sourceKey]] = {\n key: sourceKey,\n schema: target[keys[sourceKey]].schema.concat(source[j].schema)\n };\n }\n else {\n target.push(source[j]);\n }\n }\n }\n else {\n obj._inner[key] = obj._inner[key].concat(source);\n }\n }\n else {\n obj._inner[key] = source.slice();\n }\n }\n }\n\n return obj;\n }\n\n _test(name, arg, func, options) {\n\n const obj = this.clone();\n obj._tests.push({ func, name, arg, options });\n return obj;\n }\n\n _testUnique(name, arg, func, options) {\n\n const obj = this.clone();\n obj._tests = obj._tests.filter((test) => test.name !== name);\n obj._tests.push({ func, name, arg, options });\n return obj;\n }\n\n options(options) {\n\n Hoek.assert(!options.context, 'Cannot override context');\n this.checkOptions(options);\n\n const obj = this.clone();\n obj._settings = Settings.concat(obj._settings, options);\n return obj;\n }\n\n strict(isStrict) {\n\n const obj = this.clone();\n\n const convert = isStrict === undefined ? false : !isStrict;\n obj._settings = Settings.concat(obj._settings, { convert });\n return obj;\n }\n\n raw(isRaw) {\n\n const value = isRaw === undefined ? true : isRaw;\n\n if (this._flags.raw === value) {\n return this;\n }\n\n const obj = this.clone();\n obj._flags.raw = value;\n return obj;\n }\n\n error(err, options = { self: false }) {\n\n Hoek.assert(err && (err instanceof Error || typeof err === 'function'), 'Must provide a valid Error object or a function');\n\n const unknownKeys = Object.keys(options).filter((k) => !['self'].includes(k));\n Hoek.assert(unknownKeys.length === 0, `Options ${unknownKeys} are unknown`);\n\n const obj = this.clone();\n obj._flags.error = err;\n\n if (options.self) {\n obj._flags.selfError = true;\n }\n\n return obj;\n }\n\n allow(...values) {\n\n const obj = this.clone();\n values = Hoek.flatten(values);\n for (let i = 0; i < values.length; ++i) {\n const value = values[i];\n\n Hoek.assert(value !== undefined, 'Cannot call allow/valid/invalid with undefined');\n obj._invalids.remove(value);\n obj._valids.add(value, obj._refs);\n }\n\n return obj;\n }\n\n valid(...values) {\n\n const obj = this.allow(...values);\n obj._flags.allowOnly = true;\n return obj;\n }\n\n invalid(...values) {\n\n const obj = this.clone();\n values = Hoek.flatten(values);\n for (let i = 0; i < values.length; ++i) {\n const value = values[i];\n\n Hoek.assert(value !== undefined, 'Cannot call allow/valid/invalid with undefined');\n obj._valids.remove(value);\n obj._invalids.add(value, obj._refs);\n }\n\n return obj;\n }\n\n required() {\n\n if (this._flags.presence === 'required') {\n return this;\n }\n\n const obj = this.clone();\n obj._flags.presence = 'required';\n return obj;\n }\n\n optional() {\n\n if (this._flags.presence === 'optional') {\n return this;\n }\n\n const obj = this.clone();\n obj._flags.presence = 'optional';\n return obj;\n }\n\n\n forbidden() {\n\n if (this._flags.presence === 'forbidden') {\n return this;\n }\n\n const obj = this.clone();\n obj._flags.presence = 'forbidden';\n return obj;\n }\n\n\n strip() {\n\n if (this._flags.strip) {\n return this;\n }\n\n const obj = this.clone();\n obj._flags.strip = true;\n return obj;\n }\n\n applyFunctionToChildren(children, fn, args = [], root) {\n\n children = [].concat(children);\n\n if (children.length !== 1 || children[0] !== '') {\n root = root ? (root + '.') : '';\n\n const extraChildren = (children[0] === '' ? children.slice(1) : children).map((child) => {\n\n return root + child;\n });\n\n throw new Error('unknown key(s) ' + extraChildren.join(', '));\n }\n\n return this[fn](...args);\n }\n\n default(value, description) {\n\n if (typeof value === 'function' &&\n !Ref.isRef(value)) {\n\n if (!value.description &&\n description) {\n\n value.description = description;\n }\n\n if (!this._flags.func) {\n Hoek.assert(typeof value.description === 'string' && value.description.length > 0, 'description must be provided when default value is a function');\n }\n }\n\n const obj = this.clone();\n obj._flags.default = value;\n Ref.push(obj._refs, value);\n return obj;\n }\n\n empty(schema) {\n\n const obj = this.clone();\n if (schema === undefined) {\n delete obj._flags.empty;\n }\n else {\n obj._flags.empty = Cast.schema(this._currentJoi, schema);\n }\n\n return obj;\n }\n\n when(condition, options) {\n\n Hoek.assert(options && typeof options === 'object', 'Invalid options');\n Hoek.assert(options.then !== undefined || options.otherwise !== undefined, 'options must have at least one of \"then\" or \"otherwise\"');\n\n const then = options.hasOwnProperty('then') ? this.concat(Cast.schema(this._currentJoi, options.then)) : undefined;\n const otherwise = options.hasOwnProperty('otherwise') ? this.concat(Cast.schema(this._currentJoi, options.otherwise)) : undefined;\n\n Alternatives = Alternatives || require('../alternatives');\n\n const alternativeOptions = { then, otherwise };\n if (Object.prototype.hasOwnProperty.call(options, 'is')) {\n alternativeOptions.is = options.is;\n }\n\n const obj = Alternatives.when(condition, alternativeOptions);\n obj._flags.presence = 'ignore';\n obj._baseType = this;\n\n return obj;\n }\n\n description(desc) {\n\n Hoek.assert(desc && typeof desc === 'string', 'Description must be a non-empty string');\n\n const obj = this.clone();\n obj._description = desc;\n return obj;\n }\n\n notes(notes) {\n\n Hoek.assert(notes && (typeof notes === 'string' || Array.isArray(notes)), 'Notes must be a non-empty string or array');\n\n const obj = this.clone();\n obj._notes = obj._notes.concat(notes);\n return obj;\n }\n\n tags(tags) {\n\n Hoek.assert(tags && (typeof tags === 'string' || Array.isArray(tags)), 'Tags must be a non-empty string or array');\n\n const obj = this.clone();\n obj._tags = obj._tags.concat(tags);\n return obj;\n }\n\n meta(meta) {\n\n Hoek.assert(meta !== undefined, 'Meta cannot be undefined');\n\n const obj = this.clone();\n obj._meta = obj._meta.concat(meta);\n return obj;\n }\n\n example(...examples) {\n\n Hoek.assert(examples.length > 0, 'Missing examples');\n\n const processed = [];\n for (let i = 0; i < examples.length; ++i) {\n const example = [].concat(examples[i]);\n Hoek.assert(example.length <= 2, `Bad example format at index ${i}`);\n\n const value = example[0];\n let options = example[1];\n if (options !== undefined) {\n Hoek.assert(options && typeof options === 'object', `Options for example at index ${i} must be an object`);\n const unknownOptions = Object.keys(options).filter((option) => !['parent', 'context'].includes(option));\n Hoek.assert(unknownOptions.length === 0, `Unknown example options ${unknownOptions} at index ${i}`);\n }\n else {\n options = {};\n }\n\n const localState = new State('', [], options.parent || null);\n const result = this._validate(value, localState, Settings.concat(internals.defaults, options.context ? { context: options.context } : null));\n Hoek.assert(!result.errors, `Bad example at index ${i}:`, result.errors && Errors.process(result.errors, value));\n\n const ex = { value };\n if (Object.keys(options).length) {\n ex.options = options;\n }\n\n processed.push(ex);\n }\n\n const obj = this.clone();\n obj._examples = processed;\n return obj;\n }\n\n unit(name) {\n\n Hoek.assert(name && typeof name === 'string', 'Unit name must be a non-empty string');\n\n const obj = this.clone();\n obj._unit = name;\n return obj;\n }\n\n _prepareEmptyValue(value) {\n\n if (typeof value === 'string' && this._flags.trim) {\n return value.trim();\n }\n\n return value;\n }\n\n _validate(value, state, options, reference) {\n\n const originalValue = value;\n\n // Setup state and settings\n\n state = state || new State('', [], null, reference);\n\n if (this._settings) {\n const isDefaultOptions = options === internals.defaults;\n if (isDefaultOptions && this._settings[Symbols.settingsCache]) {\n options = this._settings[Symbols.settingsCache];\n }\n else {\n options = Settings.concat(this._language ? Settings.concat({ language: this._language }, options) : options, this._settings);\n if (isDefaultOptions) {\n this._settings[Symbols.settingsCache] = options;\n }\n }\n }\n else if (this._language) {\n options = Settings.concat({ language: this._language }, options);\n }\n\n let errors = [];\n\n if (this._coerce) {\n const coerced = this._coerce(value, state, options);\n if (coerced.errors) {\n value = coerced.value;\n errors = errors.concat(coerced.errors);\n return this._finalizeValue(value, originalValue, errors, state, options); // Coerced error always aborts early\n }\n\n value = coerced.value;\n }\n\n if (this._flags.empty && !this._flags.empty._validate(this._prepareEmptyValue(value), null, internals.defaults).errors) {\n value = undefined;\n }\n\n // Check presence requirements\n\n const presence = this._flags.presence || options.presence;\n if (presence === 'optional') {\n if (value === undefined) {\n const isDeepDefault = this._flags.hasOwnProperty('default') && this._flags.default === undefined;\n if (isDeepDefault && this._type === 'object') {\n value = {};\n }\n else {\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n }\n }\n else if (presence === 'required' &&\n value === undefined) {\n\n errors.push(this.createError('any.required', null, state, options));\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n else if (presence === 'forbidden') {\n if (value === undefined) {\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n\n errors.push(this.createError('any.unknown', null, state, options));\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n\n // Check allowed and denied values using the original value\n\n let match = this._valids.get(value, state, options, this._flags.insensitive);\n if (match) {\n if (options.convert) {\n value = match.value;\n }\n\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n\n if (this._invalids.has(value, state, options, this._flags.insensitive)) {\n errors.push(this.createError(value === '' ? 'any.empty' : 'any.invalid', { value, invalids: this._invalids.values({ stripUndefined: true }) }, state, options));\n if (options.abortEarly) {\n\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n }\n\n // Convert value and validate type\n\n if (this._base) {\n const base = this._base(value, state, options);\n if (base.errors) {\n value = base.value;\n errors = errors.concat(base.errors);\n return this._finalizeValue(value, originalValue, errors, state, options); // Base error always aborts early\n }\n\n if (base.value !== value) {\n value = base.value;\n\n // Check allowed and denied values using the converted value\n\n match = this._valids.get(value, state, options, this._flags.insensitive);\n if (match) {\n value = match.value;\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n\n if (this._invalids.has(value, state, options, this._flags.insensitive)) {\n errors.push(this.createError(value === '' ? 'any.empty' : 'any.invalid', { value, invalids: this._invalids.values({ stripUndefined: true }) }, state, options));\n if (options.abortEarly) {\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n }\n }\n }\n\n // Required values did not match\n\n if (this._flags.allowOnly) {\n errors.push(this.createError('any.allowOnly', { value, valids: this._valids.values({ stripUndefined: true }) }, state, options));\n if (options.abortEarly) {\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n }\n\n // Validate tests\n\n for (let i = 0; i < this._tests.length; ++i) {\n const test = this._tests[i];\n const ret = test.func.call(this, value, state, options);\n if (ret instanceof Errors.Err) {\n errors.push(ret);\n if (options.abortEarly) {\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n }\n else {\n value = ret;\n }\n }\n\n return this._finalizeValue(value, originalValue, errors, state, options);\n }\n\n _finalizeValue(value, originalValue, errors, state, options) {\n\n let finalValue;\n\n if (value !== undefined) {\n finalValue = this._flags.raw ? originalValue : value;\n }\n else if (options.noDefaults) {\n finalValue = value;\n }\n else if (Ref.isRef(this._flags.default)) {\n finalValue = this._flags.default(state.parent, options);\n }\n else if (typeof this._flags.default === 'function' &&\n !(this._flags.func && !this._flags.default.description)) {\n\n let args;\n\n if (state.parent !== null &&\n this._flags.default.length > 0) {\n\n args = [Hoek.clone(state.parent), options];\n }\n\n const defaultValue = internals._try(this._flags.default, args);\n finalValue = defaultValue.value;\n if (defaultValue.error) {\n errors.push(this.createError('any.default', { error: defaultValue.error }, state, options));\n }\n }\n else {\n finalValue = Hoek.clone(this._flags.default);\n }\n\n if (errors.length &&\n typeof this._flags.error === 'function' &&\n (\n !this._flags.selfError ||\n errors.some((e) => state.path.length === e.path.length)\n )\n ) {\n const change = this._flags.error.call(this, errors);\n\n if (typeof change === 'string') {\n errors = [this.createOverrideError('override', { reason: errors }, state, options, change)];\n }\n else {\n errors = [].concat(change)\n .map((err) => {\n\n return err instanceof Error ?\n err :\n this.createOverrideError(err.type || 'override', err.context, state, options, err.message, err.template);\n });\n }\n }\n\n return {\n value: this._flags.strip ? undefined : finalValue,\n finalValue,\n errors: errors.length ? errors : null\n };\n }\n\n _validateWithOptions(value, options, callback) {\n\n if (options) {\n this.checkOptions(options);\n }\n\n const settings = Settings.concat(internals.defaults, options);\n const result = this._validate(value, null, settings);\n const errors = Errors.process(result.errors, value);\n\n if (callback) {\n return callback(errors, result.value);\n }\n\n return {\n error: errors,\n value: result.value,\n then(resolve, reject) {\n\n if (errors) {\n return Promise.reject(errors).catch(reject);\n }\n\n return Promise.resolve(result.value).then(resolve);\n },\n catch(reject) {\n\n if (errors) {\n return Promise.reject(errors).catch(reject);\n }\n\n return Promise.resolve(result.value);\n }\n };\n }\n\n validate(value, options, callback) {\n\n if (typeof options === 'function') {\n return this._validateWithOptions(value, null, options);\n }\n\n return this._validateWithOptions(value, options, callback);\n }\n\n describe() {\n\n const description = {\n type: this._type\n };\n\n const flags = Object.keys(this._flags);\n if (flags.length) {\n if (['empty', 'default', 'lazy', 'label'].some((flag) => this._flags.hasOwnProperty(flag))) {\n description.flags = {};\n for (let i = 0; i < flags.length; ++i) {\n const flag = flags[i];\n if (flag === 'empty') {\n description.flags[flag] = this._flags[flag].describe();\n }\n else if (flag === 'default') {\n if (Ref.isRef(this._flags[flag])) {\n description.flags[flag] = this._flags[flag].toString();\n }\n else if (typeof this._flags[flag] === 'function') {\n description.flags[flag] = {\n description: this._flags[flag].description,\n function : this._flags[flag]\n };\n }\n else {\n description.flags[flag] = this._flags[flag];\n }\n }\n else if (flag === 'lazy' || flag === 'label') {\n // We don't want it in the description\n }\n else {\n description.flags[flag] = this._flags[flag];\n }\n }\n }\n else {\n description.flags = this._flags;\n }\n }\n\n if (this._settings) {\n description.options = Hoek.clone(this._settings);\n }\n\n if (this._baseType) {\n description.base = this._baseType.describe();\n }\n\n if (this._description) {\n description.description = this._description;\n }\n\n if (this._notes.length) {\n description.notes = this._notes;\n }\n\n if (this._tags.length) {\n description.tags = this._tags;\n }\n\n if (this._meta.length) {\n description.meta = this._meta;\n }\n\n if (this._examples.length) {\n description.examples = this._examples;\n }\n\n if (this._unit) {\n description.unit = this._unit;\n }\n\n const valids = this._valids.values();\n if (valids.length) {\n description.valids = valids.map((v) => {\n\n return Ref.isRef(v) ? v.toString() : v;\n });\n }\n\n const invalids = this._invalids.values();\n if (invalids.length) {\n description.invalids = invalids.map((v) => {\n\n return Ref.isRef(v) ? v.toString() : v;\n });\n }\n\n description.rules = [];\n\n for (let i = 0; i < this._tests.length; ++i) {\n const validator = this._tests[i];\n const item = { name: validator.name };\n\n if (validator.arg !== void 0) {\n item.arg = Ref.isRef(validator.arg) ? validator.arg.toString() : validator.arg;\n }\n\n const options = validator.options;\n if (options) {\n if (options.hasRef) {\n item.arg = {};\n const keys = Object.keys(validator.arg);\n for (let j = 0; j < keys.length; ++j) {\n const key = keys[j];\n const value = validator.arg[key];\n item.arg[key] = Ref.isRef(value) ? value.toString() : value;\n }\n }\n\n if (typeof options.description === 'string') {\n item.description = options.description;\n }\n else if (typeof options.description === 'function') {\n item.description = options.description(item.arg);\n }\n }\n\n description.rules.push(item);\n }\n\n if (!description.rules.length) {\n delete description.rules;\n }\n\n const label = this._getLabel();\n if (label) {\n description.label = label;\n }\n\n return description;\n }\n\n label(name) {\n\n Hoek.assert(name && typeof name === 'string', 'Label name must be a non-empty string');\n\n const obj = this.clone();\n obj._flags.label = name;\n return obj;\n }\n\n _getLabel(def) {\n\n return this._flags.label || def;\n }\n\n}]" } } ], "_refs": [], "_flags": {}, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "children": null, "renames": [], "dependencies": [], "patterns": [] } } } ] } } }, { "schema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "object", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [ { "func": function (value, state, options) {\n\n if (value instanceof constructor) {\n return value;\n }\n\n return this.createError('object.type', { type: typeData.name, value }, state, options);\n }, "name": "type", "arg": { "name": "Joi object", "ctor": "[class extends Any {\n\n constructor() {\n\n super();\n this._type = 'object';\n this._inner.children = null;\n this._inner.renames = [];\n this._inner.dependencies = [];\n this._inner.patterns = [];\n }\n\n _init(...args) {\n\n return args.length ? this.keys(...args) : this;\n }\n\n _base(value, state, options) {\n\n let target = value;\n const errors = [];\n const finish = () => {\n\n return {\n value: target,\n errors: errors.length ? errors : null\n };\n };\n\n if (typeof value === 'string' &&\n options.convert) {\n\n if (value.length > 1 &&\n (value[0] === '{' || /^\\s*\\{/.test(value))) {\n\n try {\n value = Bourne.parse(value);\n }\n catch (e) { }\n }\n }\n\n const type = this._flags.func ? 'function' : 'object';\n if (!value ||\n typeof value !== type ||\n Array.isArray(value)) {\n\n errors.push(this.createError(type + '.base', { value }, state, options));\n return finish();\n }\n\n // Skip if there are no other rules to test\n\n if (!this._inner.renames.length &&\n !this._inner.dependencies.length &&\n !this._inner.children && // null allows any keys\n !this._inner.patterns.length) {\n\n target = value;\n return finish();\n }\n\n // Ensure target is a local copy (parsed) or shallow copy\n\n if (target === value) {\n if (type === 'object') {\n target = Object.create(Object.getPrototypeOf(value));\n }\n else {\n target = function (...args) {\n\n return value.apply(this, args);\n };\n\n target.prototype = Hoek.clone(value.prototype);\n }\n\n const valueKeys = Object.keys(value);\n for (let i = 0; i < valueKeys.length; ++i) {\n target[valueKeys[i]] = value[valueKeys[i]];\n }\n }\n else {\n target = value;\n }\n\n // Rename keys\n\n const renamed = {};\n for (let i = 0; i < this._inner.renames.length; ++i) {\n const rename = this._inner.renames[i];\n\n if (rename.isRegExp) {\n const targetKeys = Object.keys(target);\n const matchedTargetKeys = [];\n\n for (let j = 0; j < targetKeys.length; ++j) {\n if (rename.from.test(targetKeys[j])) {\n matchedTargetKeys.push(targetKeys[j]);\n }\n }\n\n const allUndefined = matchedTargetKeys.every((key) => target[key] === undefined);\n if (rename.options.ignoreUndefined && allUndefined) {\n continue;\n }\n\n if (!rename.options.multiple &&\n renamed[rename.to]) {\n\n errors.push(this.createError('object.rename.regex.multiple', { from: matchedTargetKeys, to: rename.to }, state, options));\n if (options.abortEarly) {\n return finish();\n }\n }\n\n if (Object.prototype.hasOwnProperty.call(target, rename.to) &&\n !rename.options.override &&\n !renamed[rename.to]) {\n\n errors.push(this.createError('object.rename.regex.override', { from: matchedTargetKeys, to: rename.to }, state, options));\n if (options.abortEarly) {\n return finish();\n }\n }\n\n if (allUndefined) {\n delete target[rename.to];\n }\n else {\n target[rename.to] = target[matchedTargetKeys[matchedTargetKeys.length - 1]];\n }\n\n renamed[rename.to] = true;\n\n if (!rename.options.alias) {\n for (let j = 0; j < matchedTargetKeys.length; ++j) {\n delete target[matchedTargetKeys[j]];\n }\n }\n }\n else {\n if (rename.options.ignoreUndefined && target[rename.from] === undefined) {\n continue;\n }\n\n if (!rename.options.multiple &&\n renamed[rename.to]) {\n\n errors.push(this.createError('object.rename.multiple', { from: rename.from, to: rename.to }, state, options));\n if (options.abortEarly) {\n return finish();\n }\n }\n\n if (Object.prototype.hasOwnProperty.call(target, rename.to) &&\n !rename.options.override &&\n !renamed[rename.to]) {\n\n errors.push(this.createError('object.rename.override', { from: rename.from, to: rename.to }, state, options));\n if (options.abortEarly) {\n return finish();\n }\n }\n\n if (target[rename.from] === undefined) {\n delete target[rename.to];\n }\n else {\n target[rename.to] = target[rename.from];\n }\n\n renamed[rename.to] = true;\n\n if (!rename.options.alias) {\n delete target[rename.from];\n }\n }\n }\n\n // Validate schema\n\n if (!this._inner.children && // null allows any keys\n !this._inner.patterns.length &&\n !this._inner.dependencies.length) {\n\n return finish();\n }\n\n const unprocessed = new Set(Object.keys(target));\n\n if (this._inner.children) {\n const stripProps = [];\n\n for (let i = 0; i < this._inner.children.length; ++i) {\n const child = this._inner.children[i];\n const key = child.key;\n const item = target[key];\n\n unprocessed.delete(key);\n\n const localState = new State(key, [...state.path, key], target, state.reference);\n const result = child.schema._validate(item, localState, options);\n if (result.errors) {\n errors.push(this.createError('object.child', { key, child: child.schema._getLabel(key), reason: result.errors }, localState, options));\n\n if (options.abortEarly) {\n return finish();\n }\n }\n else {\n if (child.schema._flags.strip || (result.value === undefined && result.value !== item)) {\n stripProps.push(key);\n target[key] = result.finalValue;\n }\n else if (result.value !== undefined) {\n target[key] = result.value;\n }\n }\n }\n\n for (let i = 0; i < stripProps.length; ++i) {\n delete target[stripProps[i]];\n }\n }\n\n // Unknown keys\n\n if (unprocessed.size && this._inner.patterns.length) {\n\n for (const key of unprocessed) {\n const localState = new State(key, [...state.path, key], target, state.reference);\n const item = target[key];\n\n for (let i = 0; i < this._inner.patterns.length; ++i) {\n const pattern = this._inner.patterns[i];\n\n if (pattern.regex ?\n pattern.regex.test(key) :\n !pattern.schema._validate(key, state, { ...options, abortEarly:true }).errors) {\n\n unprocessed.delete(key);\n\n const result = pattern.rule._validate(item, localState, options);\n if (result.errors) {\n errors.push(this.createError('object.child', {\n key,\n child: pattern.rule._getLabel(key),\n reason: result.errors\n }, localState, options));\n\n if (options.abortEarly) {\n return finish();\n }\n }\n\n target[key] = result.value;\n }\n }\n }\n }\n\n if (unprocessed.size && (this._inner.children || this._inner.patterns.length)) {\n if ((options.stripUnknown && this._flags.allowUnknown !== true) ||\n options.skipFunctions) {\n\n const stripUnknown = options.stripUnknown\n ? (options.stripUnknown === true ? true : !!options.stripUnknown.objects)\n : false;\n\n\n for (const key of unprocessed) {\n if (stripUnknown) {\n delete target[key];\n unprocessed.delete(key);\n }\n else if (typeof target[key] === 'function') {\n unprocessed.delete(key);\n }\n }\n }\n\n if ((this._flags.allowUnknown !== undefined ? !this._flags.allowUnknown : !options.allowUnknown)) {\n\n for (const unprocessedKey of unprocessed) {\n errors.push(this.createError('object.allowUnknown', { child: unprocessedKey, value: target[unprocessedKey] }, {\n key: unprocessedKey,\n path: [...state.path, unprocessedKey]\n }, options, {}));\n }\n }\n }\n\n // Validate dependencies\n\n for (let i = 0; i < this._inner.dependencies.length; ++i) {\n const dep = this._inner.dependencies[i];\n const hasKey = dep.key !== null;\n const splitKey = hasKey && dep.key.split('.');\n const localState = hasKey ? new State(splitKey[splitKey.length - 1], [...state.path, ...splitKey]) : new State(null, state.path);\n const err = internals[dep.type].call(this, dep.key, hasKey && Hoek.reach(target, dep.key, { functions: true }), dep.peers, target, localState, options);\n if (err instanceof Errors.Err) {\n errors.push(err);\n if (options.abortEarly) {\n return finish();\n }\n }\n }\n\n return finish();\n }\n\n keys(schema) {\n\n Hoek.assert(schema === null || schema === undefined || typeof schema === 'object', 'Object schema must be a valid object');\n Hoek.assert(!schema || !(schema instanceof Any), 'Object schema cannot be a joi schema');\n\n const obj = this.clone();\n\n if (!schema) {\n obj._inner.children = null;\n return obj;\n }\n\n const children = Object.keys(schema);\n\n if (!children.length) {\n obj._inner.children = [];\n return obj;\n }\n\n const topo = new Topo();\n if (obj._inner.children) {\n for (let i = 0; i < obj._inner.children.length; ++i) {\n const child = obj._inner.children[i];\n\n // Only add the key if we are not going to replace it later\n if (!children.includes(child.key)) {\n topo.add(child, { after: child._refs, group: child.key });\n }\n }\n }\n\n for (let i = 0; i < children.length; ++i) {\n const key = children[i];\n const child = schema[key];\n try {\n const cast = Cast.schema(this._currentJoi, child);\n topo.add({ key, schema: cast }, { after: cast._refs, group: key });\n }\n catch (castErr) {\n if (castErr.hasOwnProperty('path')) {\n castErr.path = key + '.' + castErr.path;\n }\n else {\n castErr.path = key;\n }\n\n throw castErr;\n }\n }\n\n obj._inner.children = topo.nodes;\n\n return obj;\n }\n\n append(schema) {\n // Skip any changes\n if (schema === null || schema === undefined || Object.keys(schema).length === 0) {\n return this;\n }\n\n return this.keys(schema);\n }\n\n unknown(allow) {\n\n const value = allow !== false;\n\n if (this._flags.allowUnknown === value) {\n return this;\n }\n\n const obj = this.clone();\n obj._flags.allowUnknown = value;\n return obj;\n }\n\n length(limit) {\n\n Hoek.assert(Number.isSafeInteger(limit) && limit >= 0, 'limit must be a positive integer');\n\n return this._test('length', limit, function (value, state, options) {\n\n if (Object.keys(value).length === limit) {\n return value;\n }\n\n return this.createError('object.length', { limit, value }, state, options);\n });\n }\n\n min(limit) {\n\n Hoek.assert(Number.isSafeInteger(limit) && limit >= 0, 'limit must be a positive integer');\n\n return this._test('min', limit, function (value, state, options) {\n\n if (Object.keys(value).length >= limit) {\n return value;\n }\n\n return this.createError('object.min', { limit, value }, state, options);\n });\n }\n\n max(limit) {\n\n Hoek.assert(Number.isSafeInteger(limit) && limit >= 0, 'limit must be a positive integer');\n\n return this._test('max', limit, function (value, state, options) {\n\n if (Object.keys(value).length <= limit) {\n return value;\n }\n\n return this.createError('object.max', { limit, value }, state, options);\n });\n }\n\n pattern(pattern, schema) {\n\n const isRegExp = pattern instanceof RegExp;\n Hoek.assert(isRegExp || pattern instanceof Any, 'pattern must be a regex or schema');\n Hoek.assert(schema !== undefined, 'Invalid rule');\n\n if (isRegExp) {\n Hoek.assert(!pattern.flags.includes('g') && !pattern.flags.includes('y'), 'pattern should not use global or sticky mode');\n }\n\n try {\n schema = Cast.schema(this._currentJoi, schema);\n }\n catch (castErr) {\n if (castErr.hasOwnProperty('path')) {\n castErr.message = `${castErr.message}(${castErr.path})`;\n }\n\n throw castErr;\n }\n\n const obj = this.clone();\n if (isRegExp) {\n obj._inner.patterns.push({ regex: pattern, rule: schema });\n }\n else {\n obj._inner.patterns.push({ schema: pattern, rule: schema });\n }\n\n return obj;\n }\n\n schema() {\n\n return this._test('schema', null, function (value, state, options) {\n\n if (value instanceof Any) {\n return value;\n }\n\n return this.createError('object.schema', null, state, options);\n });\n }\n\n with(key, peers) {\n\n Hoek.assert(arguments.length === 2, 'Invalid number of arguments, expected 2.');\n\n return this._dependency('with', key, peers);\n }\n\n without(key, peers) {\n\n Hoek.assert(arguments.length === 2, 'Invalid number of arguments, expected 2.');\n\n return this._dependency('without', key, peers);\n }\n\n xor(...peers) {\n\n peers = Hoek.flatten(peers);\n return this._dependency('xor', null, peers);\n }\n\n oxor(...peers) {\n\n return this._dependency('oxor', null, peers);\n }\n\n or(...peers) {\n\n peers = Hoek.flatten(peers);\n return this._dependency('or', null, peers);\n }\n\n and(...peers) {\n\n peers = Hoek.flatten(peers);\n return this._dependency('and', null, peers);\n }\n\n nand(...peers) {\n\n peers = Hoek.flatten(peers);\n return this._dependency('nand', null, peers);\n }\n\n requiredKeys(...children) {\n\n children = Hoek.flatten(children);\n return this.applyFunctionToChildren(children, 'required');\n }\n\n optionalKeys(...children) {\n\n children = Hoek.flatten(children);\n return this.applyFunctionToChildren(children, 'optional');\n }\n\n forbiddenKeys(...children) {\n\n children = Hoek.flatten(children);\n return this.applyFunctionToChildren(children, 'forbidden');\n }\n\n rename(from, to, options) {\n\n Hoek.assert(typeof from === 'string' || from instanceof RegExp, 'Rename missing the from argument');\n Hoek.assert(typeof to === 'string', 'Rename missing the to argument');\n Hoek.assert(to !== from, 'Cannot rename key to same name:', from);\n\n for (let i = 0; i < this._inner.renames.length; ++i) {\n Hoek.assert(this._inner.renames[i].from !== from, 'Cannot rename the same key multiple times');\n }\n\n const obj = this.clone();\n\n obj._inner.renames.push({\n from,\n to,\n options: Hoek.applyToDefaults(internals.renameDefaults, options || {}),\n isRegExp: from instanceof RegExp\n });\n\n return obj;\n }\n\n applyFunctionToChildren(children, fn, args = [], root) {\n\n children = [].concat(children);\n Hoek.assert(children.length > 0, 'expected at least one children');\n\n const groupedChildren = internals.groupChildren(children);\n let obj;\n\n if ('' in groupedChildren) {\n obj = this[fn](...args);\n delete groupedChildren[''];\n }\n else {\n obj = this.clone();\n }\n\n if (obj._inner.children) {\n root = root ? (root + '.') : '';\n\n for (let i = 0; i < obj._inner.children.length; ++i) {\n const child = obj._inner.children[i];\n const group = groupedChildren[child.key];\n\n if (group) {\n obj._inner.children[i] = {\n key: child.key,\n _refs: child._refs,\n schema: child.schema.applyFunctionToChildren(group, fn, args, root + child.key)\n };\n\n delete groupedChildren[child.key];\n }\n }\n }\n\n const remaining = Object.keys(groupedChildren);\n Hoek.assert(remaining.length === 0, 'unknown key(s)', remaining.join(', '));\n\n return obj;\n }\n\n _dependency(type, key, peers) {\n\n peers = [].concat(peers);\n for (let i = 0; i < peers.length; ++i) {\n Hoek.assert(typeof peers[i] === 'string', type, 'peers must be a string or array of strings');\n }\n\n const obj = this.clone();\n obj._inner.dependencies.push({ type, key, peers });\n return obj;\n }\n\n describe(shallow) {\n\n const description = super.describe();\n\n if (description.rules) {\n for (let i = 0; i < description.rules.length; ++i) {\n const rule = description.rules[i];\n // Coverage off for future-proof descriptions, only object().assert() is use right now\n if (/* $lab:coverage:off$ */rule.arg &&\n typeof rule.arg === 'object' &&\n rule.arg.schema &&\n rule.arg.ref /* $lab:coverage:on$ */) {\n rule.arg = {\n schema: rule.arg.schema.describe(),\n ref: rule.arg.ref.toString()\n };\n }\n }\n }\n\n if (this._inner.children &&\n !shallow) {\n\n description.children = {};\n for (let i = 0; i < this._inner.children.length; ++i) {\n const child = this._inner.children[i];\n description.children[child.key] = child.schema.describe();\n }\n }\n\n if (this._inner.dependencies.length) {\n description.dependencies = Hoek.clone(this._inner.dependencies);\n }\n\n if (this._inner.patterns.length) {\n description.patterns = [];\n\n for (let i = 0; i < this._inner.patterns.length; ++i) {\n const pattern = this._inner.patterns[i];\n if (pattern.regex) {\n description.patterns.push({ regex: pattern.regex.toString(), rule: pattern.rule.describe() });\n }\n else {\n description.patterns.push({ schema: pattern.schema.describe(), rule: pattern.rule.describe() });\n }\n }\n }\n\n if (this._inner.renames.length > 0) {\n description.renames = Hoek.clone(this._inner.renames);\n }\n\n return description;\n }\n\n assert(ref, schema, message) {\n\n ref = Cast.ref(ref);\n Hoek.assert(ref.isContext || ref.depth > 1, 'Cannot use assertions for root level references - use direct key rules instead');\n message = message || 'pass the assertion test';\n Hoek.assert(typeof message === 'string', 'Message must be a string');\n\n try {\n schema = Cast.schema(this._currentJoi, schema);\n }\n catch (castErr) {\n if (castErr.hasOwnProperty('path')) {\n castErr.message = `${castErr.message}(${castErr.path})`;\n }\n\n throw castErr;\n }\n\n const key = ref.path[ref.path.length - 1];\n const path = ref.path.join('.');\n\n return this._test('assert', { schema, ref }, function (value, state, options) {\n\n const result = schema._validate(ref(value), null, options, value);\n if (!result.errors) {\n return value;\n }\n\n const localState = new State(key, ref.path, state.parent, state.reference);\n return this.createError('object.assert', { ref: path, message }, localState, options);\n });\n }\n\n type(constructor, name = constructor.name) {\n\n Hoek.assert(typeof constructor === 'function', 'type must be a constructor function');\n const typeData = {\n name,\n ctor: constructor\n };\n\n return this._test('type', typeData, function (value, state, options) {\n\n if (value instanceof constructor) {\n return value;\n }\n\n return this.createError('object.type', { type: typeData.name, value }, state, options);\n });\n }\n}]" } } ], "_refs": [], "_flags": {}, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "children": null, "renames": [], "dependencies": [], "patterns": [] } } } ] } } }, { "key": "description", "schema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "alternatives", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [], "_refs": [], "_flags": {}, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "matches": [ { "schema": { "isJoi": true, "_type": "string", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": 0 }, "_tests": [], "_refs": [], "_flags": {}, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": {}, "_currentJoi": "[Circular ~.base._currentJoi]" } }, { "schema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "object", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [ { "func": function (value, state, options) {\n\n if (value.length === n) {\n return value;\n }\n\n return this.createError('function.arity', { n }, state, options);\n }, "name": "arity", "arg": 1 } ], "_refs": [], "_flags": { "func": true }, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "children": null, "renames": [], "dependencies": [], "patterns": [] } } } ] } } } ], "renames": [], "dependencies": [ { "type": "or", "key": null, "peers": [ "setup", "validate" ] } ], "patterns": [] } } ], "exclusions": [], "requireds": [] } } } ], "renames": [], "dependencies": [], "patterns": [] } }, "extensionsSchema": { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "array", "_settings": { "convert": false }, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [], "_refs": [], "_flags": { "sparse": false }, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "items": [ "[Circular ~.base]", { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "object", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [ { "func": function (value, state, options) {\n\n if (value.length === n) {\n return value;\n }\n\n return this.createError('function.arity', { n }, state, options);\n }, "name": "arity", "arg": 1 } ], "_refs": [], "_flags": { "func": true }, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "children": null, "renames": [], "dependencies": [], "patterns": [] } } ], "ordereds": [], "inclusions": [ "[Circular ~.base]", { "isJoi": true, "_currentJoi": "[Circular ~.base._currentJoi]", "_type": "object", "_settings": null, "_valids": { "_set": {}, "_hasRef": false }, "_invalids": { "_set": {}, "_hasRef": false }, "_tests": [ { "func": function (value, state, options) {\n\n if (value.length === n) {\n return value;\n }\n\n return this.createError('function.arity', { n }, state, options);\n }, "name": "arity", "arg": 1 } ], "_refs": [], "_flags": { "func": true }, "_description": null, "_unit": null, "_notes": [], "_tags": [], "_examples": [], "_meta": [], "_inner": { "children": null, "renames": [], "dependencies": [], "patterns": [] } } ], "exclusions": [], "requireds": [] } }, "version": "15.1.1" } }, "coerce": { "from": "string", "method": "[method(value) {\n if (typeof value !== 'string' || (value[0] !== '{' && !/^\\s*\\{/.test(value))) {\n return;\n }\n\n try {\n return { value: Bourne.parse(value) };\n } catch (ignoreErr) { }\n }]" }, �[41m"name"�[0m�[31m [1]: -- missing --�[0m } �[31m [1] "name" is required�[0m at Object.exports.process (/tmp/node_modules/@hapi/joi/lib/errors.js:202:19) at internals.Object._validateWithOptions (/tmp/node_modules/@hapi/joi/lib/types/any/index.js:763:31) at module.exports.internals.Any.root.validate (/tmp/node_modules/@hapi/joi/lib/index.js:145:23) at module.exports.internals.Any.root.attempt (/tmp/node_modules/@hapi/joi/lib/index.js:175:29) at module.exports.internals.Any.root.assert (/tmp/node_modules/@hapi/joi/lib/index.js:170:14) at module.exports.internals.Any.root.extend (/tmp/node_modules/@hapi/joi/lib/index.js:292:18) at new SchemaResolver (/tmp/node_modules/enjoi/lib/resolver.js:13:24) at Object.exports.schema (/tmp/node_modules/enjoi/index.js:47:12) at Object.<anonymous> (/tmp/main.js:3:20) at Module._compile (internal/modules/cjs/loader.js:1123:30) { isJoi: true, details: [ { message: '"name" is required', path: [Array], type: 'any.required', context: [Object] } ], _object: { type: 'object', base: { isJoi: true, _type: 'object', _settings: null, _valids: [InternalSet], _invalids: [InternalSet], _tests: [], _refs: [], _flags: {}, _description: null, _unit: null, _notes: [], _tags: [], _examples: [], _meta: [], _inner: [Object], _currentJoi: [Object] }, coerce: { from: 'string', method: [Function: method] } }, annotate: [Function (anonymous)] }
The text was updated successfully, but these errors were encountered:
No branches or pull requests
The example from the README is throwing an error. It is saying message: '"name" is required',.
Logs
The text was updated successfully, but these errors were encountered: