Skip to content

Commit

Permalink
Update @hapi/joi to just joi
Browse files Browse the repository at this point in the history
  • Loading branch information
marshallswain committed May 8, 2021
1 parent f1af4a4 commit dc2105e
Show file tree
Hide file tree
Showing 7 changed files with 918 additions and 331 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Here's an example validation file for an `faqs` service. You might put the follo

```js
// src/services/faqs/faqs.model.js
const Joi = require('@hapi/joi')
const Joi = require('joi')
const { objectId } = require('@feathers-plus/validate-joi-mongodb')

const attrs = {
Expand Down Expand Up @@ -61,7 +61,7 @@ const { attrs, schema } = require('./faqs.model')

module.exports = {
before: {
all: [
all: [
// ... handle authentication first
iff(
isProvider('external'),
Expand Down
12 changes: 7 additions & 5 deletions object-id.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const Joi = require('@hapi/joi');
const { ObjectID } = require('mongodb');
const Joi = require("joi");
const { ObjectID } = require("mongodb");
/**
* Custom objectId validator
*/
Expand All @@ -11,9 +11,11 @@ module.exports = function objectId() {
try {
return new ObjectID(value);
} catch (error) {
const errVal = helpers.error('any.invalid');
errVal.message = `"${errVal.path.join('.')}" objectId validation failed because ${error.message}`;
const errVal = helpers.error("any.invalid");
errVal.message = `"${errVal.path.join(
"."
)}" objectId validation failed because ${error.message}`;
return errVal;
}
}, 'objectId');
}, "objectId");
};
104 changes: 53 additions & 51 deletions object-ids-in-query.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const objectId = require('./object-id')
const validate = require('@feathers-plus/validate-joi')
const Joi = require('@hapi/joi')
const objectId = require("./object-id");
const validate = require("@feathers-plus/validate-joi");
const Joi = require("joi");

/**
* Creates a validation rule for each of the `keys` which validates and converts
Expand All @@ -11,76 +11,78 @@ const Joi = require('@hapi/joi')
*/
module.exports = function objectIdsInQuery(keys) {
if (!Array.isArray(keys)) {
throw new Error('the first argument to objectIdsInQuery should be an array of keys')
throw new Error(
"the first argument to objectIdsInQuery should be an array of keys"
);
}

const validations = {}
keys.forEach(option => {
let key
const rules = []
const validations = {};
keys.forEach((option) => {
let key;
const rules = [];

if (typeof option === 'string') {
key = option
if (typeof option === "string") {
key = option;
} else if (option.key) {
key = option.key
key = option.key;
if (option.rules && Array.isArray(option.rules)) {
option.rules.forEach(rule => {
rules.push(rule)
})
option.rules.forEach((rule) => {
rules.push(rule);
});
}
}
if (key.includes('.')) {
const [first, second] = key.split('.')
if (key.includes(".")) {
const [first, second] = key.split(".");

// Make rules for first level. I don't think this is needed. Dunno
const baseRules = makeBaseRules(first)
baseRules.forEach(rule => {
rules.push(rule)
})
const baseRules = makeBaseRules(first);
baseRules.forEach((rule) => {
rules.push(rule);
});

const dotRules = [
Joi.array().items(Joi.object({
[second]: objectId()
})),
Joi.array().items(
Joi.object({
[second]: objectId(),
})
),
Joi.object({
tags: Joi.object({
[second]: objectId()
})
[second]: objectId(),
}),
}),
Joi.object({
[key]: objectId()
})
]
dotRules.forEach(rule => {
rules.push(rule)
})
[key]: objectId(),
}),
];
dotRules.forEach((rule) => {
rules.push(rule);
});
} else {
const baseRules = makeBaseRules(key)
baseRules.forEach(rule => {
rules.push(rule)
})
const baseRules = makeBaseRules(key);
baseRules.forEach((rule) => {
rules.push(rule);
});
}
if (typeof key !== 'string') {
throw new Error('all keys passed to objectIdsInQuery must be strings')
if (typeof key !== "string") {
throw new Error("all keys passed to objectIdsInQuery must be strings");
}
// Each item in this array is a possible validation match that Joi will handle:
validations[key] = [
...rules
]
})
const _idSchema = Joi.object(validations)
validations[key] = [...rules];
});
const _idSchema = Joi.object(validations);

return validate.form(_idSchema, {
allowUnknown: true,
getContext: context => context.params.query,
getContext: (context) => context.params.query,
setContext: (context, values) => {
if (values) {
Object.assign(context.params.query, values)
Object.assign(context.params.query, values);
}
return context
}
})
}
return context;
},
});
};

function makeBaseRules() {
return [
Expand All @@ -91,7 +93,7 @@ function makeBaseRules() {
// Handle the $in: [] syntax
Joi.object({
$in: Joi.array().items(objectId()),
$nin: Joi.array().items(objectId())
})
]
$nin: Joi.array().items(objectId()),
}),
];
}
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,16 @@
"access": "public"
},
"dependencies": {
"mongodb": "^3.5.9"
"mongodb": "^3.6.6"
},
"peerDependencies": {
"@feathers-plus/validate-joi": "^3.4.0",
"@hapi/joi": "^17.1.1"
"joi": "^17.4.0"
},
"devDependencies": {
"@feathers-plus/validate-joi": "^3.1.0",
"@hapi/joi": "^17.1.1",
"chai": "^4.2.0"
"chai": "^4.3.4",
"joi": "^17.4.0",
"mocha": "^8.4.0"
}
}
101 changes: 52 additions & 49 deletions test/object-id.test.js
Original file line number Diff line number Diff line change
@@ -1,75 +1,78 @@
const assert = require('assert')
const objectId = require('../object-id')
const Joi = require('@hapi/joi')
const { ObjectID } = require('mongodb')
const assert = require("assert");
const objectId = require("../object-id");
const Joi = require("joi");
const { ObjectID } = require("mongodb");

const idString = '5af9f1e35b9df500148d6986'
const _id = new ObjectID(idString)
const idString = "5af9f1e35b9df500148d6986";
const _id = new ObjectID(idString);

describe('Joi objectId validation', () => {
it('updates valid objectId strings to ObjectIDs', () => {
const { value } = objectId().validate(idString)
describe("Joi objectId validation", () => {
it("updates valid objectId strings to ObjectIDs", () => {
const { value } = objectId().validate(idString);

assert(value instanceof ObjectID, 'should get back an ObjectID')
})
assert(value instanceof ObjectID, "should get back an ObjectID");
});

it('validates ObjectIDs', () => {
const { value } = objectId().validate(_id)
it("validates ObjectIDs", () => {
const { value } = objectId().validate(_id);

assert(_id === value, 'the _id should not be modified')
assert(value instanceof ObjectID, 'should get back an ObjectID')
})
assert(_id === value, "the _id should not be modified");
assert(value instanceof ObjectID, "should get back an ObjectID");
});

it('allows null to pass', () => {
const { value } = objectId().validate(null)
it("allows null to pass", () => {
const { value } = objectId().validate(null);

assert(value === null, 'the value should still be null')
})
assert(value === null, "the value should still be null");
});

it('throws an error on invalid strings', () => {
it("throws an error on invalid strings", () => {
const userSchema = Joi.object({
userId: objectId(),
name: Joi.string()
})
name: Joi.string(),
});
const user = {
userId: 'moo',
name: 'Marshall Thompson'
}
const { error, value } = userSchema.validate(user)
assert.equal(error.message, '"userId" objectId validation failed because Argument passed in must be a single String of 12 bytes or a string of 24 hex characters')
assert(value.userId === 'moo', 'the value should not have been changed')
})

it('Can be used in another schema', () => {
userId: "moo",
name: "Marshall Thompson",
};
const { error, value } = userSchema.validate(user);
assert.equal(
error.message,
'"userId" objectId validation failed because Argument passed in must be a single String of 12 bytes or a string of 24 hex characters'
);
assert(value.userId === "moo", "the value should not have been changed");
});

it("Can be used in another schema", () => {
const userSchema = Joi.object({
userId: objectId(),
name: Joi.string()
})
name: Joi.string(),
});

const user = {
userId: idString,
name: 'Marshall Thompson'
}
name: "Marshall Thompson",
};

const { value } = userSchema.validate(user)
const { value } = userSchema.validate(user);

assert(value.userId instanceof ObjectID, 'userId should be an ObjectID')
})
assert(value.userId instanceof ObjectID, "userId should be an ObjectID");
});

it('Can disallow null values', () => {
it("Can disallow null values", () => {
const userSchema = Joi.object({
userId: objectId().disallow(null),
name: Joi.string()
})
name: Joi.string(),
});

const user = {
userId: null,
name: 'Marshall Thompson'
}
name: "Marshall Thompson",
};

const { error, value } = userSchema.validate(user)
assert.equal(error.message, '"userId" contains an invalid value')
const { error, value } = userSchema.validate(user);
assert.equal(error.message, '"userId" contains an invalid value');

assert(value.userId === null, 'userId is still null')
})
})
assert(value.userId === null, "userId is still null");
});
});
Loading

0 comments on commit dc2105e

Please sign in to comment.