Skip to content

Commit

Permalink
Consider extended types parameters
Browse files Browse the repository at this point in the history
Fixes #1000. Fixes #1521.
  • Loading branch information
Marsup committed Jun 6, 2018
1 parent 944dbe9 commit 8a1eb96
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 16 deletions.
30 changes: 14 additions & 16 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const internals = {
string: require('./types/string')
};

internals.applyDefaults = function (schema) {
internals.callWithDefaults = function (schema, args) {

Hoek.assert(this, 'Must be invoked on a Joi instance.');

Expand All @@ -35,7 +35,7 @@ internals.applyDefaults = function (schema) {

schema._currentJoi = this;

return schema;
return schema._init(...args);
};

internals.root = function () {
Expand All @@ -50,68 +50,66 @@ internals.root = function () {

Hoek.assert(args.length === 0, 'Joi.any() does not allow arguments.');

return internals.applyDefaults.call(this, any);
return internals.callWithDefaults.call(this, any, args);
};

root.alternatives = root.alt = function (...args) {

const alternatives = internals.applyDefaults.call(this, internals.alternatives);
return args.length ? alternatives.try.apply(alternatives, args) : alternatives;
return internals.callWithDefaults.call(this, internals.alternatives, args);
};

root.array = function (...args) {

Hoek.assert(args.length === 0, 'Joi.array() does not allow arguments.');

return internals.applyDefaults.call(this, internals.array);
return internals.callWithDefaults.call(this, internals.array, args);
};

root.boolean = root.bool = function (...args) {

Hoek.assert(args.length === 0, 'Joi.boolean() does not allow arguments.');

return internals.applyDefaults.call(this, internals.boolean);
return internals.callWithDefaults.call(this, internals.boolean, args);
};

root.binary = function (...args) {

Hoek.assert(args.length === 0, 'Joi.binary() does not allow arguments.');

return internals.applyDefaults.call(this, internals.binary);
return internals.callWithDefaults.call(this, internals.binary, args);
};

root.date = function (...args) {

Hoek.assert(args.length === 0, 'Joi.date() does not allow arguments.');

return internals.applyDefaults.call(this, internals.date);
return internals.callWithDefaults.call(this, internals.date, args);
};

root.func = function (...args) {

Hoek.assert(args.length === 0, 'Joi.func() does not allow arguments.');

return internals.applyDefaults.call(this, internals.func);
return internals.callWithDefaults.call(this, internals.func, args);
};

root.number = function (...args) {

Hoek.assert(args.length === 0, 'Joi.number() does not allow arguments.');

return internals.applyDefaults.call(this, internals.number);
return internals.callWithDefaults.call(this, internals.number, args);
};

root.object = function (...args) {

const object = internals.applyDefaults.call(this, internals.object);
return args.length ? object.keys(...args) : object;
return internals.callWithDefaults.call(this, internals.object, args);
};

root.string = function (...args) {

Hoek.assert(args.length === 0, 'Joi.string() does not allow arguments.');

return internals.applyDefaults.call(this, internals.string);
return internals.callWithDefaults.call(this, internals.string, args);
};

root.ref = function (...args) {
Expand Down Expand Up @@ -402,9 +400,9 @@ internals.root = function () {
}

const instance = new type();
joi[extension.name] = function () {
joi[extension.name] = function (...extArgs) {

return internals.applyDefaults.call(this, instance);
return internals.callWithDefaults.call(this, instance, extArgs);
};
}

Expand Down
5 changes: 5 additions & 0 deletions lib/types/alternatives/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ internals.Alternatives = class extends Any {
this._inner.matches = [];
}

_init(...args) {

return args.length ? this.try(...args) : this;
}

_base(value, state, options) {

let errors = [];
Expand Down
5 changes: 5 additions & 0 deletions lib/types/any/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ module.exports = internals.Any = class {
this._inner = {}; // Hash of arrays of immutable objects
}

_init() {

return this;
}

get schemaType() {

return this._type;
Expand Down
5 changes: 5 additions & 0 deletions lib/types/object/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ internals.Object = class extends Any {
this._inner.patterns = [];
}

_init(...args) {

return args.length ? this.keys(...args) : this;
}

_base(value, state, options) {

let target = value;
Expand Down
27 changes: 27 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3009,6 +3009,33 @@ describe('Joi', () => {
]);
});

it('defines a custom type with a custom base while preserving its original helper params', () => {

const customJoi = Joi.extend({
base: Joi.object(),
name: 'myType'
});

expect(Joi.myType).to.not.exist();
expect(customJoi.myType).to.be.a.function();

const schema = customJoi.myType({ a: customJoi.number() });
Helper.validate(schema, [
[undefined, true],
[{}, true],
[{ a: 1 }, true],
[{ a: 'a' }, false, null, {
message: 'child "a" fails because ["a" must be a number]',
details: [{
message: '"a" must be a number',
path: ['a'],
type: 'number.base',
context: { key: 'a', label: 'a' }
}]
}]
]);
});

it('defines a custom type with new rules', () => {

const customJoi = Joi.extend({
Expand Down

0 comments on commit 8a1eb96

Please sign in to comment.