sift-rule v0.1.4
sift-rule
Define rules using sift (=~ MongoDB) queries
- Terminology
- Example
- String notation
- Debugging
- Extensions * References
- API
Rule
Rule.new()Rule.match()Rule.apply()RuleSetRuleSet.new()Managing rulesRuleSet.sizeRuleSet.add()RuleSet.addAll()RuleSet.delete()RuleSet.deleteAll()RuleSet.clear()Processing rulesRuleSet.every()RuleSet.some()RuleSet.filter()RuleSet.filterApply()RuleSet.first()RuleSet.firstApply()*RuleSet.toString()
Terminology
- Rules have a
headand atail. - Rules are applied to values. If the value matches the
head, thetailis implied. - Rules can have an optional name.
- Rulesets are list of rules.
- Rules are applied to values. Depending on the logic (which method is used, see RuleSet API below):
- Return all matching rules
- Return all an array of the
tailof all matching rules - Return whether ever rule in the set matched
- Return whether some rules in the set matched
Example
const {RuleSet} = require('sift-rule')
colorRules = new RuleSet()
colorRules.add({filename: {$regex: '\.js$'}}, 'red')
colorRules.add({filename: {$regex: '^foo'}}, 'green')
colorRules.filterApply({filename: 'foo.js'})
// => ['red', 'green']
colorRules.filterApply({filename: 'foo.css'})
// => ['green']String notation
headandtailare separated by-->- Rule and rule name are separated by
#== headandtailare parsed as HJSON, JSON with some extensions:- Object keys can be unquoted
- Escaped backslashes are doubled, to make it easier to write regexes
- Unquoted values of the form
YYYY-MM-DDare parsed asDate - Unquoted values of the form
0x...are parsed as hexadecimal numbers
{topic: "Universe"} --> 42 #== answer to everything parses as
{
head: { topic: "Universe" },
tail: 42,
name: 'answer to everything',
}Debugging
To get debug output:
- Set
process.env.SIFT_RULE_DEBUG='true'in Node.js - Set
window.SIFT_RULE_DEBUG='true'in the browser
NOTE: 'true' must be the string true not the boolean value true.
Extensions
References
You can add clauses to a rule head that reference data in the object to sift
using an object with a single $ref key and a JSON Pointer as the value.
For example, to define a rule that users may only edit their own posts:
var rule = new Rule({"post.user": {$ref: '/user/id'}}, true)
rule.apply({post: {title: 'title', user: 'john'}, user: {id: 'john'}})
// => true
rule.apply({post: {title: 'title', user: 'john'}, user: {id: 'mike'}}) // true
// => falseNOTE: references to non-existing values are set to NaN (not-a-number)
because NaN !== NaN so this clause will always fail.
API
Rule
Rule.new()
new Rule(stringRule)
new Rule(head[, tail][, name])Constructor takes either a rule in String notation or head, tail (optional) and name (optional)
Rule.match()
rule.match(value)Return true if the head matches val, false otherwise.
Rule.apply()
rule.match(value)Return the tail if the head matches val, undefined otherwise.
RuleSet
RuleSet.new()
new RuleSet{[rule1, rule2...]}
new RuleSet({name: 'ruleset1', rules: [rule1, rule2...]})Create a new Ruleset.
Managing rules
RuleSet.size
Return the number of rules in the RuleSet.
RuleSet.add()
ruleset.add(rule)
ruleset.add(ruleString)
ruleset.add(head, tail, name)Adds a single rule to the RuleSet. If rule is not an instance of a Rule, passes arguments to the Rule.new.
Returns the rule.
RuleSet.addAll()
ruleset.addAll(otherRuleset)
ruleset.addAll(arrayOfRules)RuleSet.delete()
RuleSet.deleteAll()
RuleSet.clear()
Delete all rules in this RuleSet.
Processing rules
RuleSet.every()
ruleset.every(value)Return true if the head of every rule matches value, false otherwise.
RuleSet.some()
ruleset.some(value)Return true if the head of any rule matches value, false if none match.
RuleSet.filter()
ruleset.filter(value)Return the rules whose head matches value.
RuleSet.filterApply()
ruleset.filter(value)Return the tail of any rule whose head matches value.
RuleSet.first()
ruleset.first(value)Return the first rule whose head matches value.
RuleSet.firstApply()
ruleset.firstApply(value)Return the tail of the first rule whose head matches value.