enjoi
enjoi copied to clipboard
Basic example is not working
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)]
}