Skip to content

Commit

Permalink
chore: update to joi 16.x.x (#29)
Browse files Browse the repository at this point in the history
Update to joi 16.x.x.

Optimise for validations which are synchronous.

Closes #27
  • Loading branch information
g-div authored and yoitsro committed Dec 11, 2019
1 parent 5d20ee5 commit 8390b70
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 83 deletions.
126 changes: 65 additions & 61 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,33 +24,29 @@ internals.convert = joiObject => {
throw new Error("Ensure the value you're trying to convert exists!");
}

// If this object isn't an object, we're done here
Joi.validate(joiObject, Joi.object());

if (!joiObject.isJoi) {
if (!Joi.isSchema(joiObject)) {
joiObject = Joi.object(joiObject);
}

var output = {};

if (joiObject._flags.default !== undefined) {
output.default = joiObject._flags.default;
}

if (joiObject._meta.length > 0) {
if (joiObject.$_terms.metas.length > 0) {
var toClass = {}.toString;
// console.log(JSON.stringify(joiObject, null, ' '));

// Iterate through the array
for (var i = 0; i < joiObject._meta.length; i++) {
for (var i = 0; i < joiObject.$_terms.metas.length; i++) {
// Only add objects
if (toClass.call(joiObject._meta[i]) !== "[object Object]") {
if (toClass.call(joiObject.$_terms.metas[i]) !== "[object Object]") {
continue;
}

for (var key in joiObject._meta[i]) {
for (var key in joiObject.$_terms.metas[i]) {
// Check for _objectId
if (key === "type" && joiObject._meta[i][key] === "ObjectId") {
if (key === "type" && joiObject.$_terms.metas[i][key] === "ObjectId") {
output.type = internals.mongoose.Schema.Types.ObjectId;

var originalJoiObject = Hoek.clone(joiObject);
Expand All @@ -62,26 +58,26 @@ internals.convert = joiObject => {

joiObject._isObjectId = true;
originalJoiObject._isObjectId = true;
joiObject._meta = originalJoiObject._meta;
joiObject.$_terms.metas = originalJoiObject.$_terms.metas;
joiObject._flags = originalJoiObject._flags;

output.validate = internals.mongooseValidateWrapper.bind(
this,
originalJoiObject
);
} else {
output[key] = joiObject._meta[i][key];
output[key] = joiObject.$_terms.metas[i][key];
}
}
}
}

if (joiObject._type === "object") {
if (joiObject.type === "object") {
// Allow for empty object - https://github.com/hapijs/joi/blob/v9.0.0-3/API.md#object
if (!joiObject._inner.children)
if (!joiObject.$_terms.keys)
return { type: internals.mongoose.Schema.Types.Mixed };

joiObject._inner.children.forEach(function(child) {
joiObject.$_terms.keys.forEach(function(child) {
output[child.key] = internals.convert(child.schema);

if (internals.isObjectId(child.schema)) {
Expand Down Expand Up @@ -123,22 +119,22 @@ internals.convert = joiObject => {
};

internals.typeDeterminer = joiObject => {
if (joiObject._type === "string") {
if (joiObject.type === "string") {
// If the type has already been set, that's probably
// because it was an ObjectId. In this case, don't set the
// type as a string.
return String;
}

if (joiObject._type === "number") {
if (joiObject.type === "number") {
return Number;
}

if (joiObject._type === "date") {
if (joiObject.type === "date") {
return Date;
}

if (joiObject._type === "boolean") {
if (joiObject.type === "boolean") {
return Boolean;
}

Expand All @@ -147,13 +143,13 @@ internals.typeDeterminer = joiObject => {
var i = 0;
var firstKey;

if (joiObject._type === "array") {
if (joiObject.type === "array") {
// Go through each of the children in the array and get their types
for (i = 0; i < joiObject._inner.items.length; i++) {
if (types[joiObject._inner.items[i]._type]) {
types[joiObject._inner.items[i]._type]++;
for (i = 0; i < joiObject.$_terms.items.length; i++) {
if (types[joiObject.$_terms.items[i].type]) {
types[joiObject.$_terms.items[i].type]++;
} else {
types[joiObject._inner.items[i]._type] = 1;
types[joiObject.$_terms.items[i].type] = 1;
}
}

Expand All @@ -167,18 +163,21 @@ internals.typeDeterminer = joiObject => {
// This is alright cos we know they're all the same type
firstKey = Object.keys(types)[0];
if (types[firstKey] > 1) {
type.push(internals.typeDeterminer({ _type: firstKey }));
type.push(internals.typeDeterminer({ type: firstKey }));
return type;
}

if (joiObject._inner.items.length === 0) {
if (joiObject.$_terms.items.length === 0) {
return type;
}

// Collate all meta objects because these need to be pushed into the schema options
let schemaOptions = joiObject._meta.reduce((options, currentOption) => {
return Object.assign({}, options, currentOption);
}, {});
let schemaOptions = joiObject.$_terms.metas.reduce(
(options, currentOption) => {
return Object.assign({}, options, currentOption);
},
{}
);

// Combine the explicit schema options with the global subdocument options
if (internals.subdocumentOptions) {
Expand All @@ -190,14 +189,14 @@ internals.typeDeterminer = joiObject => {
}

if (
internals.typeDeterminer(joiObject._inner.items[0]) !== Object &&
internals.typeDeterminer(joiObject._inner.items[0]) !== Array
internals.typeDeterminer(joiObject.$_terms.items[0]) !== Object &&
internals.typeDeterminer(joiObject.$_terms.items[0]) !== Array
) {
type.push(internals.convert(joiObject._inner.items[0]));
type.push(internals.convert(joiObject.$_terms.items[0]));
} else {
type.push(
new internals.mongoose.Schema(
internals.convert(joiObject._inner.items[0]),
internals.convert(joiObject.$_terms.items[0]),
schemaOptions
)
);
Expand All @@ -206,20 +205,20 @@ internals.typeDeterminer = joiObject => {
return type;
}

if (joiObject._type === "alternatives") {
if (joiObject.type === "alternatives") {
types = {};

if (joiObject._inner.matches.length === 0) {
if (joiObject.$_terms.matches.length === 0) {
return internals.mongoose.Schema.Types.Mixed;
}

// Go through each of the children in the array and get their types
for (i = 0; i < joiObject._inner.matches.length; i++) {
types[joiObject._inner.matches[i].schema._type] = types[
joiObject._inner.matches[i].schema._type
for (i = 0; i < joiObject.$_terms.matches.length; i++) {
types[joiObject.$_terms.matches[i].schema.type] = types[
joiObject.$_terms.matches[i].schema.type
]
? types[joiObject._inner.matches[i].schema._type] + 1
: (types[joiObject._inner.matches[i].schema._type] = 1);
? types[joiObject.$_terms.matches[i].schema.type] + 1
: (types[joiObject.$_terms.matches[i].schema.type] = 1);
}

// If there are multiple types, there's not much else we can do as far as Mongoose goes...
Expand All @@ -230,28 +229,28 @@ internals.typeDeterminer = joiObject => {
// If there are multiple of the same type, this means that there are different schemas, but the same type :D
firstKey = Object.keys(types)[0];
if (types[firstKey] > 1) {
return internals.typeDeterminer({ _type: firstKey });
return internals.typeDeterminer({ type: firstKey });
}

// If we're here, it's because there's a single type, and one schema. So actually, an alternative didn't need to be used...
return internals.typeDeterminer(joiObject._inner.matches[0].schema);
return internals.typeDeterminer(joiObject.$_terms.matches[0].schema);

// // If there are multiple types in the items, set the type to mixed
// mixedTypeFound = false;

// if (joiObject._inner.matches.length === 0) {
// if (joiObject.$_terms.matches.length === 0) {
// mixedTypeFound = true;
// }

// types = {};
// joiObject._inner.matches.forEach(function (item) {
// joiObject.$_terms.matches.forEach(function (item) {

// types[item.schema._type] = true;
// types[item.schema.type] = true;
// });

// // If we have one type, then all array items are this
// if (Object.keys(types).length === 1) {
// output = internals.convert(joiObject._inner.matches[0].schema);
// output = internals.convert(joiObject.$_terms.matches[0].schema);
// } else {
// mixedTypeFound = true;
// }
Expand All @@ -263,34 +262,34 @@ internals.typeDeterminer = joiObject => {
// return output;
}

if (joiObject._type === "object") {
if (joiObject.type === "object") {
return Object;
}

if (joiObject._type === "any") {
if (joiObject.type === "any") {
return internals.mongoose.Schema.Types.Mixed;
}

throw new TypeError(
'Unsupported Joi type: "' +
joiObject._type +
joiObject.type +
"\"! Raise an issue on GitHub if you'd like it to be added!"
);
};

internals.isObjectId = joiObject => {
if (joiObject._meta.length > 0) {
if (joiObject.$_terms.metas.length > 0) {
var toClass = {}.toString;

for (var i = 0; i < joiObject._meta.length; i++) {
for (var i = 0; i < joiObject.$_terms.metas.length; i++) {
// Only add objects
if (toClass.call(joiObject._meta[i]) !== "[object Object]") {
if (toClass.call(joiObject.$_terms.metas[i]) !== "[object Object]") {
continue;
}

for (var key in joiObject._meta[i]) {
for (var key in joiObject.$_terms.metas[i]) {
// Check for _objectId
if (key === "type" && joiObject._meta[i][key] === "ObjectId") {
if (key === "type" && joiObject.$_terms.metas[i][key] === "ObjectId") {
return true;
} else {
return false;
Expand All @@ -306,19 +305,24 @@ internals.mongooseValidateWrapper = async (originalJoiSchema, value) => {
var joiSchema = Hoek.clone(originalJoiSchema);

if (joiSchema._isObjectId) {
joiSchema = Joi.alternatives([
joiSchema = Joi.alternatives(
joiSchema,
Joi.object().type(internals.mongoose.Types.ObjectId)
]);
Joi.object().instance(internals.mongoose.Types.ObjectId)
);
}

try {
await Joi.validate(value, joiSchema, internals.joiGlobalOptions);
const { error } = joiSchema.validate(value, internals.joiGlobalOptions);
if (error) return false;
return true;
} catch (err) {
return false;
try {
await joiSchema.validateAsync(value, internals.joiGlobalOptions);
return true;
} catch (err) {
return false;
}
}

return true;
};

module.exports = internals.root;
54 changes: 40 additions & 14 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
},
"dependencies": {
"@hapi/hoek": "^6.2.1",
"@hapi/joi": "^15.0.0"
"@hapi/joi": "^16.1.7"
},
"devDependencies": {
"code": "^5.1.2",
Expand Down
Loading

0 comments on commit 8390b70

Please sign in to comment.