description and source-codefunction enjoi(schema, options) {
options = options || {};
Assert.ok(Thing.isObject(schema) || Thing.isString(schema), 'Expected schema to be an object or type string.');
Assert.ok(Thing.isObject(options), 'Expected options to be an object.');
const subSchemas = options.subSchemas;
const types = options.types;
Assert.ok(!subSchemas || Thing.isObject(subSchemas), 'Expected options.subSchemas to be an object.');
Assert.ok(!types || Thing.isObject(types), 'Expected options.types to be an object.');
function resolve(current) {
if (current.type) {
return resolvetype(current);
}
if (current.anyOf) {
return resolveAnyOf(current);
}
if (current.allOf) {
return resolveAllOf(current);
}
if (current.oneOf) {
return resolveOneOf(current);
}
if (current.$ref) {
return resolve(resolveref(current.$ref));
}
//if no type is specified, just enum
if (current.enum) {
return Joi.any().valid(current.enum);
}
// If current is itself a string, interpret it as a type
if (typeof current === 'string') {
return resolvetype({ type: current });
}
//Fall through to whatever.
console.warn('WARNING: schema missing a \'type\' or \'$ref\' or \'enum\': %s', JSON.stringify(current));
return Joi.any();
}
function resolveref(value) {
let refschema;
const id = value.substr(0, value.indexOf('#') + 1);
const path = value.substr(value.indexOf('#') + 1);
if (id && subSchemas) {
refschema = subSchemas[id] || subSchemas[id.substr(0, id.length - 1)];
}
if (!refschema) {
refschema = schema;
}
Assert.ok(refschema, 'Can not find schema reference: ' + value + '.');
let fragment = refschema;
const paths = path.split('/');
for (let i = 1; i < paths.length && fragment; i++) {
fragment = typeof fragment === 'object' && fragment[paths[i]];
}
return fragment;
}
function resolvetype(current) {
let joischema;
const typeDefinitionMap = {
description: 'description',
title: 'label',
default: 'default'
};
function joitype(type) {
let joischema;
switch (type) {
case 'array':
joischema = array(current);
break;
case 'boolean':
joischema = Joi.boolean();
break;
case 'integer':
case 'number':
joischema = number(current);
break;
case 'object':
joischema = object(current);
break;
case 'string':
joischema = string(current);
break;
case 'null':
joischema = Joi.any().valid(null);
break;
default:
if (types) {
joischema = types[current.type];
}
}
return joischema;
}
if (Thing.isArray(current.type)) {
const schemas = [];
for (let i = 0; i < current.type.length; i++) {
schemas.push(joitype(current.type[i]));
}
joischema = Joi.alternatives(schemas);
}
else {
joischema = joitype(current.type);
}
Assert.ok(joischema, 'Could not resolve type: ' + current.type + '.');
Object.keys(typeDefinitionMap).forEach(function (key) {
if (current[key]) {
joischema = joischema[typeDefinitionMap[key]](current[key]);
}
});
return joischema;
}
function resolveAnyOf(current) {
Assert.ok(Thing.isArray(current.anyOf), 'Expected anyOf to be a ...