Skip to content

8.0.0 #109

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 21, 2021
Merged

8.0.0 #109

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
node_modules
coverage
coverage-ts
docs
npm-debug.log
.DS_Store
Expand Down
76 changes: 50 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
Node Rules
=====

Node-rules is a light weight forward chaining Rule Engine, written in JavaScript for both browser and node.js environments.
Node-rules is a light weight forward chaining Rule Engine, written in Typescript for all environments.


#### Installation

npm install node-rules
```console
npm install node-rules
```

![Sample Screencast](https://raw.githubusercontent.com/mithunsatheesh/node-rules/gh-pages/images/screencast.gif "See it in action")

Expand All @@ -34,16 +36,36 @@ Node-rules takes rules written in JSON friendly format as input. Once the rule e

A rule will consist of a condition and its corresponding consequence. You can find the explanation for various mandatory and optional parameters of a rule in [this wiki](https://github.com/mithunsatheesh/node-rules/wiki/Rules).

``` js
{
"condition" : function(R) {
```ts
import { API } from 'node-rules';

interface Fact {
result: boolean;
transactionTotal: number;
}

const rule = {
condition(this: Fact, R: API) {
R.when(this.transactionTotal < 500);
},
"consequence" : function(R) {
consequence(this: Fact, R: API) {
this.result = false;
R.stop();
}
}
};
```

```js
/** @type {import('./lib/node-rules').Rule} */
const rule = {
condition(this: Fact, R: API) {
R.when(this.transactionTotal < 500);
},
consequence(this: Fact, R: API) {
this.result = false;
R.stop();
}
};
```

Here priority is an optional parameter which will be used to specify priority of a rule over other rules when there are multiple rules running. In the above rule `R.when` evaluates the condition expression and `R.stop` used to stop further processing of the fact as we have arrived at a result.
Expand All @@ -56,30 +78,32 @@ Facts are those input json values on which the rule engine applies its rule to o

A sample Fact may look like

{
"name":"user4",
"application":"MOB2",
"transactionTotal":400,
"cardType":"Credit Card",
}
```json
{
"name": "user4",
"application": "MOB2",
"transactionTotal": 400,
"cardType": "Credit Card"
}
```

###### 3. Using the Rule Engine

The example below shows how to use the rule engine to apply a sample rule on a specific fact. Rules can be fed into the rule engine as Array of rules or as an individual rule object.

``` js
var RuleEngine = require("node-rules");
```js
const { RuleEngine } = require("node-rules");

/* Creating Rule Engine instance */
var R = new RuleEngine();
const R = new RuleEngine();

/* Add a rule */
var rule = {
"condition": function(R) {
const rule = {
condition(R) {
console.log(this);
R.when(this.transactionTotal < 500);
},
"consequence": function(R) {
consequence(R) {
this.result = false;
this.reason = "The transaction was blocked as it was less than 500";
R.stop();
Expand All @@ -90,19 +114,19 @@ var rule = {
R.register(rule);

/* Add a Fact with less than 500 as transaction, and this should be blocked */
var fact = {
"name": "user4",
"application": "MOB2",
"transactionTotal": 400,
"cardType": "Credit Card"
const fact = {
name: "user4",
application: "MOB2",
transactionTotal: 400,
cardType: "Credit Card"
};

/* Check if the engine blocks it! */
R.execute(fact, function (data) {
R.execute(fact, data => {
if (data.result) {
console.log("Valid transaction");
} else {
console.log("Blocked Reason:" + data.reason);
console.log('Blocked Reason: %s', data.reason);
}
});
```
Expand Down
59 changes: 29 additions & 30 deletions docs/Dynamic-Control.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,52 +8,51 @@ The various functions for dynamic control are
4. FindRules
5. Init

##### 1. `RuleEngine.turn(<state>,<filter>)`
##### 1. `ruleEngine.turn(<state>,<filter>)`
This function is used to dynamically activate or deactivate a rule. The syntax for using this function is shown in below example.

RuleEngine.turn("OFF", {
"id": "one"
});
```js
ruleEngine.turn("OFF", {
id: "one"
});
```

Here `RuleEngine` is the rule engine instance. The first parameter to turn function indicates whether we need to turn the rule ON or OFF. The second parameter passed to the function is a filter. It should be a key which can be used to uniquely distinguish the targeted rule or set of rules from the other rules running in the Rule Engine. Here the above example will deactivate all the rules where the `id` attribute equals "one".

##### 2. `RuleEngine.prioritize(<priority>,<filter>)`
##### 2. `ruleEngine.prioritize(<priority>,<filter>)`
This function is used to dynamically change the priority of a rule while rule engine is running. It works similar to the Turn function and just that instead of the ON/OFF state we will be passing a priority number value to the function. See example below

RuleEngine.prioritize(10, {
"id": "one"
});
```js
ruleEngine.prioritize(10, {
id: "one"
});
```

The above `prioritize` call will give priority to Rule with id "one" over all the rules which are having lesser priority than 10.


##### 3. `RuleEngine.register(<rules>)`
##### 3. `ruleEngine.register(<rules>)`
We know that we can pass Rules as parameter into the Rule Engine constructor while we create the Rule Engine object like below.

var RuleEngine = new RuleEngine(rules);

Where `rules` can be either an array of rule objects or a single array. But what if we need to add some rules later to the Rule Engine. Register can be used any time to append new rules into the Rule Engine. It can be used like.
```js
const ruleEngine = new RuleEngine();
ruleEngine.register(newRule);
ruleEngine.register(newRule);
```

var RuleEngine = new RuleEngine();
RuleEngine.register(newrule);
RuleEngine.register(newrule);


##### 4. `RuleEngine.findRules(<filter>)`
##### 4. `ruleEngine.findRules(<filter>)`
This function is used to retrieve the Rules which are registered on the Rule engine which matches the filter we pass as its parameter. A sample usage can be like below.
```js
const rules = RuleEngine.findRules({ id: "one" });
```

var rules = RuleEngine.findRules({"id": "one"});

##### 5. `RuleEngine.init()`
##### 5. `ruleEngine.init()`
This function is used to remove all the rules registered on the Rule Engine. This is mostly used for rule clean up purposes by internal functions. A sample usage can be like below.

var RuleEngine = new RuleEngine();
RuleEngine.register(badrule);
RuleEngine.init();//removes the bad rule and cleans up
RuleEngine.register(newrule);






```js
const ruleEngine = new RuleEngine();
ruleEngine.register(badRule);
ruleEngine.init(); // Removes the bad rule and cleans up
ruleEngine.register(newRule);
```
51 changes: 24 additions & 27 deletions docs/Examples.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,39 @@
The example below shows how to use the rule engine to apply a sample rule on a specific fact. Rules fed into the rule engine may be as Array of rules or as individual rule objects.
The example below shows how to use the rule engine to apply a sample rule on a specific fact. Rules fed into the rule engine may be arrays of rules or a single rule object.

``` js
//import the package
var RuleEngine = require('node-rules');
```js
// import the package
const RuleEngine = require('node-rules');

//define the rules
var rules = [{
"condition": function(R) {
const rules = [{
condition(R) {
R.when(this && (this.transactionTotal < 500));
},
"consequence": function(R) {
consequence(R) {
this.result = false;
R.stop();
}
}];
/*as you can see above we removed the priority
and on properties for this example as they are optional.*/
```

//sample fact to run the rules on
var fact = {
"userIP": "27.3.4.5",
"name":"user4",
"application":"MOB2",
"userLoggedIn":true,
"transactionTotal":400,
"cardType":"Credit Card",
As you can see above we didn't provide the `priority` and `on` properties for this example as they're optional.
```js
// sample fact to run the rules on
const fact = {
userIP: "27.3.4.5",
name: "user4",
application: "MOB2",
userLoggedIn: true,
transactionTotal: 400,
cardType: "Credit Card"
};

//initialize the rule engine
var R = new RuleEngine(rules);
// initialize the rule engine
const R = new RuleEngine(rules);

//Now pass the fact on to the rule engine for results
R.execute(fact,function(result){

if(result.result)
console.log("\n-----Payment Accepted----\n");
else
console.log("\n-----Payment Rejected----\n");

// Now pass the fact on to the rule engine for results
R.execute(fact, result => {
if (result.result) console.log("\n-----Payment Accepted----\n");
else console.log("\n-----Payment Rejected----\n");
});
```
Loading