Serializable object assertions.
npm install @rule.js/coreModule for testing objects. There's a variety of uses for this module, such as
schema validation.
Motivation for this is that there isn't anything of expressive/flexible enough
for my needs. The closest thing would have to be Joi, but for some reason there
isn't much in terms of serialization solutions. I also don't like the API...
Performance should be pretty good, since the underlying data structure used to
store the data is already json-convertable (just stringify it). The method
chaining only provides a more fluid api.
``javascript
const Rule = require('rule.js/core'
const test = Rule()
.equal('foo.bar', 'hello world!')
.test;
test({
foo: {
bar: 'hello world!'
}
}); // => true
`
This module can be useful for creating serializable conditions based on a certain context.
In other words, user defined logic.
`javascript
const data = Rule()
.null('created')
.serialize(); // outputs an array of objects ready to be stored.
// ... imagine pulling this out of a db
const test = Rule(data).test;
if(test({ created: new Date() })) {
sendEmail({...}); // etc...
}
`
`javascript`
const result = Rule().equal('foo', 1).test({ foo: 1 }) // => true
`javascript`
const result = Rule()
.propsEqual('foo', 'bar')
.test({ foo: 1, bar: 1 }) // => true
`javascript`
const result = Rule().null('foo').test({ foo: null }) // => true$3
Checks if the given property is equal to true.
`javascript`
const result = Rule().true('foo').test({ foo: false }) // => returns false
`javascript`
const result = Rule().false('foo').test({ foo: false }) // => true
`javascript
const result1 = Rule().gt('one', 1).test({ one: 1 }) // => false
const result2 = Rule().gt('two', 1).test({ two: 2 }) // => true
`
`javascript`
const result = Rule().lt('one', 2).test({ one: 1 }) // => true
`javascript`
const result = Rule().any('letter', ['a', 'b']).test({ letter: 'a' }) // => true
, the next method chain's result will be inverted.
`javascript
Rule()
.not().equal('a', 1)
.not().exist('c')
.test({ a: 2 }); // => true
`Binding to a specific key
`javascript
Rule()
.bind('fullName')
.equal('firstName', 'Jonathan')
.equal('lastName', 'Boudreau')
.end()
.test({
fullName: {
firstName: 'Jonathan',
lastName: 'Boudreau'
}
}); // => true
`Or Statement
`javascript
Rule()
.or()
.equal('a', 1)
.equal('a', 2)
.end()
.test({ a: 2 }); // => trueRule()
.or()
.equal('a', 1)
.and()
.equal('a', 2)
.equal('b', 3)
.end()
.end()
.test({ a: 2, b: 3 }) // => true
`Composition
Because the instances are immutable, you can use an existing instance to
concatenate it with another.
`javascript
// you can currently do this
const cond = Rule().equal('name', 'Jonathan');
// You get a new object which will test for both properties.
const merged = Rule().equal('fullName.lastName', 'Boudreau').concat(cond);
`Extensions
This module is somewhat extendable. The first argument is the series of asserts runners,
and the second argument is the set of methods to add to the builder.
`javascript
const objectIs = Rule.extend({
foo(context, args) {
return Rule.get(context, args.key) === 'bar';
}
}, {
foo(key) {
return this.concat({
type: 'foo', // this specifies what assertion to call
key
});
}
});objectIs
.foo('a')
.exist('today') // previous methods remain, but they can be overriden.
.test({ today: new Date(), a: 'bar' }); // returns true!
`Or even...
`javascript
const eql = require('deep-eql');
const objectIs = Rule.extend({
eql(context, args) {
return eql(args.compare);
}
}, {
eql(compare) {
return this.concat({
type: 'eql',
compare
});
}
});``To keep this module lightweight I decided to not include a ton of depdencies.
Instead the module aims to be extendable for your specific needs. Mainly, this
module defines a "grammar", you can add whatever "nouns" you want.