aboutsummaryrefslogtreecommitdiff
path: root/node_modules/joi/lib/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/joi/lib/index.js')
-rw-r--r--node_modules/joi/lib/index.js434
1 files changed, 434 insertions, 0 deletions
diff --git a/node_modules/joi/lib/index.js b/node_modules/joi/lib/index.js
new file mode 100644
index 00000000..24022fdf
--- /dev/null
+++ b/node_modules/joi/lib/index.js
@@ -0,0 +1,434 @@
+'use strict';
+
+// Load modules
+
+const Hoek = require('hoek');
+const Any = require('./types/any');
+const Cast = require('./cast');
+const Errors = require('./errors');
+const Lazy = require('./types/lazy');
+const Ref = require('./ref');
+
+
+// Declare internals
+
+const internals = {
+ alternatives: require('./types/alternatives'),
+ array: require('./types/array'),
+ boolean: require('./types/boolean'),
+ binary: require('./types/binary'),
+ date: require('./types/date'),
+ func: require('./types/func'),
+ number: require('./types/number'),
+ object: require('./types/object'),
+ string: require('./types/string')
+};
+
+internals.applyDefaults = function (schema) {
+
+ Hoek.assert(this, 'Must be invoked on a Joi instance.');
+
+ if (this._defaults) {
+ schema = this._defaults(schema);
+ }
+
+ schema._currentJoi = this;
+
+ return schema;
+};
+
+internals.root = function () {
+
+ const any = new Any();
+
+ const root = any.clone();
+ Any.prototype._currentJoi = root;
+ root._currentJoi = root;
+
+ root.any = function () {
+
+ Hoek.assert(arguments.length === 0, 'Joi.any() does not allow arguments.');
+
+ return internals.applyDefaults.call(this, any);
+ };
+
+ root.alternatives = root.alt = function () {
+
+ const alternatives = internals.applyDefaults.call(this, internals.alternatives);
+ return arguments.length ? alternatives.try.apply(alternatives, arguments) : alternatives;
+ };
+
+ root.array = function () {
+
+ Hoek.assert(arguments.length === 0, 'Joi.array() does not allow arguments.');
+
+ return internals.applyDefaults.call(this, internals.array);
+ };
+
+ root.boolean = root.bool = function () {
+
+ Hoek.assert(arguments.length === 0, 'Joi.boolean() does not allow arguments.');
+
+ return internals.applyDefaults.call(this, internals.boolean);
+ };
+
+ root.binary = function () {
+
+ Hoek.assert(arguments.length === 0, 'Joi.binary() does not allow arguments.');
+
+ return internals.applyDefaults.call(this, internals.binary);
+ };
+
+ root.date = function () {
+
+ Hoek.assert(arguments.length === 0, 'Joi.date() does not allow arguments.');
+
+ return internals.applyDefaults.call(this, internals.date);
+ };
+
+ root.func = function () {
+
+ Hoek.assert(arguments.length === 0, 'Joi.func() does not allow arguments.');
+
+ return internals.applyDefaults.call(this, internals.func);
+ };
+
+ root.number = function () {
+
+ Hoek.assert(arguments.length === 0, 'Joi.number() does not allow arguments.');
+
+ return internals.applyDefaults.call(this, internals.number);
+ };
+
+ root.object = function () {
+
+ const object = internals.applyDefaults.call(this, internals.object);
+ return arguments.length ? object.keys.apply(object, arguments) : object;
+ };
+
+ root.string = function () {
+
+ Hoek.assert(arguments.length === 0, 'Joi.string() does not allow arguments.');
+
+ return internals.applyDefaults.call(this, internals.string);
+ };
+
+ root.ref = function () {
+
+ return Ref.create.apply(null, arguments);
+ };
+
+ root.isRef = function (ref) {
+
+ return Ref.isRef(ref);
+ };
+
+ root.validate = function (value /*, [schema], [options], callback */) {
+
+ const last = arguments[arguments.length - 1];
+ const callback = typeof last === 'function' ? last : null;
+
+ const count = arguments.length - (callback ? 1 : 0);
+ if (count === 1) {
+ return any.validate(value, callback);
+ }
+
+ const options = count === 3 ? arguments[2] : {};
+ const schema = root.compile(arguments[1]);
+
+ return schema._validateWithOptions(value, options, callback);
+ };
+
+ root.describe = function () {
+
+ const schema = arguments.length ? root.compile(arguments[0]) : any;
+ return schema.describe();
+ };
+
+ root.compile = function (schema) {
+
+ try {
+ return Cast.schema(this, schema);
+ }
+ catch (err) {
+ if (err.hasOwnProperty('path')) {
+ err.message = err.message + '(' + err.path + ')';
+ }
+ throw err;
+ }
+ };
+
+ root.assert = function (value, schema, message) {
+
+ root.attempt(value, schema, message);
+ };
+
+ root.attempt = function (value, schema, message) {
+
+ const result = root.validate(value, schema);
+ const error = result.error;
+ if (error) {
+ if (!message) {
+ if (typeof error.annotate === 'function') {
+ error.message = error.annotate();
+ }
+ throw error;
+ }
+
+ if (!(message instanceof Error)) {
+ if (typeof error.annotate === 'function') {
+ error.message = `${message} ${error.annotate()}`;
+ }
+ throw error;
+ }
+
+ throw message;
+ }
+
+ return result.value;
+ };
+
+ root.reach = function (schema, path) {
+
+ Hoek.assert(schema && schema instanceof Any, 'you must provide a joi schema');
+ Hoek.assert(typeof path === 'string', 'path must be a string');
+
+ if (path === '') {
+ return schema;
+ }
+
+ const parts = path.split('.');
+ const children = schema._inner.children;
+ if (!children) {
+ return;
+ }
+
+ const key = parts[0];
+ for (let i = 0; i < children.length; ++i) {
+ const child = children[i];
+ if (child.key === key) {
+ return this.reach(child.schema, path.substr(key.length + 1));
+ }
+ }
+ };
+
+ root.lazy = function (fn) {
+
+ return Lazy.set(fn);
+ };
+
+ root.defaults = function (fn) {
+
+ Hoek.assert(typeof fn === 'function', 'Defaults must be a function');
+
+ let joi = Object.create(this.any());
+ joi = fn(joi);
+
+ Hoek.assert(joi && joi instanceof this.constructor, 'defaults() must return a schema');
+
+ Object.assign(joi, this, joi.clone()); // Re-add the types from `this` but also keep the settings from joi's potential new defaults
+
+ joi._defaults = (schema) => {
+
+ if (this._defaults) {
+ schema = this._defaults(schema);
+ Hoek.assert(schema instanceof this.constructor, 'defaults() must return a schema');
+ }
+
+ schema = fn(schema);
+ Hoek.assert(schema instanceof this.constructor, 'defaults() must return a schema');
+ return schema;
+ };
+
+ return joi;
+ };
+
+ root.extend = function () {
+
+ const extensions = Hoek.flatten(Array.prototype.slice.call(arguments));
+ Hoek.assert(extensions.length > 0, 'You need to provide at least one extension');
+
+ this.assert(extensions, root.extensionsSchema);
+
+ const joi = Object.create(this.any());
+ Object.assign(joi, this);
+
+ for (let i = 0; i < extensions.length; ++i) {
+ let extension = extensions[i];
+
+ if (typeof extension === 'function') {
+ extension = extension(joi);
+ }
+
+ this.assert(extension, root.extensionSchema);
+
+ const base = (extension.base || this.any()).clone(); // Cloning because we're going to override language afterwards
+ const ctor = base.constructor;
+ const type = class extends ctor { // eslint-disable-line no-loop-func
+
+ constructor() {
+
+ super();
+ if (extension.base) {
+ Object.assign(this, base);
+ }
+
+ this._type = extension.name;
+
+ if (extension.language) {
+ this._settings = this._settings || { language: {} };
+ this._settings.language = Hoek.applyToDefaults(this._settings.language, {
+ [extension.name]: extension.language
+ });
+ }
+ }
+
+ };
+
+ if (extension.coerce) {
+ type.prototype._coerce = function (value, state, options) {
+
+ if (ctor.prototype._coerce) {
+ const baseRet = ctor.prototype._coerce.call(this, value, state, options);
+
+ if (baseRet.errors) {
+ return baseRet;
+ }
+
+ value = baseRet.value;
+ }
+
+ const ret = extension.coerce.call(this, value, state, options);
+ if (ret instanceof Errors.Err) {
+ return { value, errors: ret };
+ }
+
+ return { value: ret };
+ };
+ }
+ if (extension.pre) {
+ type.prototype._base = function (value, state, options) {
+
+ if (ctor.prototype._base) {
+ const baseRet = ctor.prototype._base.call(this, value, state, options);
+
+ if (baseRet.errors) {
+ return baseRet;
+ }
+
+ value = baseRet.value;
+ }
+
+ const ret = extension.pre.call(this, value, state, options);
+ if (ret instanceof Errors.Err) {
+ return { value, errors: ret };
+ }
+
+ return { value: ret };
+ };
+ }
+
+ if (extension.rules) {
+ for (let j = 0; j < extension.rules.length; ++j) {
+ const rule = extension.rules[j];
+ const ruleArgs = rule.params ?
+ (rule.params instanceof Any ? rule.params._inner.children.map((k) => k.key) : Object.keys(rule.params)) :
+ [];
+ const validateArgs = rule.params ? Cast.schema(this, rule.params) : null;
+
+ type.prototype[rule.name] = function () { // eslint-disable-line no-loop-func
+
+ if (arguments.length > ruleArgs.length) {
+ throw new Error('Unexpected number of arguments');
+ }
+
+ const args = Array.prototype.slice.call(arguments);
+ let hasRef = false;
+ let arg = {};
+
+ for (let k = 0; k < ruleArgs.length; ++k) {
+ arg[ruleArgs[k]] = args[k];
+ if (!hasRef && Ref.isRef(args[k])) {
+ hasRef = true;
+ }
+ }
+
+ if (validateArgs) {
+ arg = joi.attempt(arg, validateArgs);
+ }
+
+ let schema;
+ if (rule.validate) {
+ const validate = function (value, state, options) {
+
+ return rule.validate.call(this, arg, value, state, options);
+ };
+
+ schema = this._test(rule.name, arg, validate, {
+ description: rule.description,
+ hasRef
+ });
+ }
+ else {
+ schema = this.clone();
+ }
+
+ if (rule.setup) {
+ const newSchema = rule.setup.call(schema, arg);
+ if (newSchema !== undefined) {
+ Hoek.assert(newSchema instanceof Any, `Setup of extension Joi.${this._type}().${rule.name}() must return undefined or a Joi object`);
+ schema = newSchema;
+ }
+ }
+
+ return schema;
+ };
+ }
+ }
+
+ if (extension.describe) {
+ type.prototype.describe = function () {
+
+ const description = ctor.prototype.describe.call(this);
+ return extension.describe.call(this, description);
+ };
+ }
+
+ const instance = new type();
+ joi[extension.name] = function () {
+
+ return internals.applyDefaults.call(this, instance);
+ };
+ }
+
+ return joi;
+ };
+
+ root.extensionSchema = internals.object.keys({
+ base: internals.object.type(Any, 'Joi object'),
+ name: internals.string.required(),
+ coerce: internals.func.arity(3),
+ pre: internals.func.arity(3),
+ language: internals.object,
+ describe: internals.func.arity(1),
+ rules: internals.array.items(internals.object.keys({
+ name: internals.string.required(),
+ setup: internals.func.arity(1),
+ validate: internals.func.arity(4),
+ params: [
+ internals.object.pattern(/.*/, internals.object.type(Any, 'Joi object')),
+ internals.object.type(internals.object.constructor, 'Joi object')
+ ],
+ description: [internals.string, internals.func.arity(1)]
+ }).or('setup', 'validate'))
+ }).strict();
+
+ root.extensionsSchema = internals.array.items([internals.object, internals.func.arity(1)]).strict();
+
+ root.version = require('../package.json').version;
+
+ return root;
+};
+
+
+module.exports = internals.root();