Giter Site home page Giter Site logo

mithunsatheesh / node-rules Goto Github PK

View Code? Open in Web Editor NEW
650.0 39.0 115.0 3.91 MB

Node-rules is a light weight forward chaining rule engine that can be used in JavaScript and TypeScript based projects.

Home Page: https://mithunsatheesh.github.io/node-rules

License: MIT License

JavaScript 2.70% TypeScript 97.30%
rule-engine rules-engine rules business-rules-engine javascript rule engine json business-rules expression-language forward-chaining rules-processor javascipt typescript

node-rules's Introduction

Build Status npm npm version Coverage Status npm downloads install size install size Known Vulnerabilities CDNJS

Node Rules

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

Installation

npm install node-rules

Sample Screencast

Try This Out!

You can see this in action in a node.js environment using this RunKit example. If you are interested to use it in the browser, use this JSFiddle for a quick start.

Overview

Node-rules takes rules written in JSON friendly format as input. Once the rule engine is running with rules registered on it, you can feed it facts and the rules will be applied one by one to generate an outcome.

1. Defining a Rule

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.

{
    "condition" : (R, fact) => {
        R.when(fact.transactionTotal < 500);
    },
    "consequence" : (R, fact) => {
        fact.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.

The functions R.stop, R.when, R.next, R.restart are part of the Flow Control API which allows user to control the Engine Flow. Read more about Flow Controls in wiki.

2. Defining a Fact

Facts are those input json values on which the rule engine applies its rule to obtain results. A fact can have multiple attributes as you decide.

A sample Fact may look like

{
  "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.

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

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

/* Add a rule */
const rule = {
  condition: (R, fact) => {
    R.when(fact.transactionTotal < 500);
  },
  consequence: (R, fact) => {
    fact.result = false;
    fact.reason = "The transaction was blocked as it was less than 500";
    R.stop();
  },
};

/* Register Rule */
R.register(rule);

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

/* Check if the engine blocks it! */
R.execute(fact, (data) => {
  if (data.result !== false) {
    console.log("Valid transaction");
  } else {
    console.log("Blocked Reason:" + data.reason);
  }
});
4. Controlling Rules running on the Rule Engine

If you are looking for ways to specify the order in which the rules get applied on a fact, it can be done via using the priority parameter. Read more about it in the Rule wiki. If you need to know about how to change priority of rules or remove add new rules to a Running Rule Engine, you may read more about it in Dynamic Control Wiki.

5. Exporting Rules to an external storage

To read more about storing rules running on the engine to an external DB, refer this wiki article.

Wiki

To read more about the Rule engine functions, please read the wiki here!. To find more examples of implementation please look in the examples folder.

Issues

Got issues with the implementation?. Feel free to open an issue here.

Licence

Node rules is distributed under the MIT License.

External References

Credits

The JSON friendly rule formats used in version 2.x.x of this module were initially based on the node module jools. The screencast image shown in this page is taken from nmotv.in which has a pretty nice article on how to use this module!

node-rules's People

Contributors

alec2435 avatar dependabot[bot] avatar drejahl avatar heckj avatar hestef00 avatar jakesjews avatar matija avatar mi04 avatar mithunsatheesh avatar mohammadufo avatar munimkazia avatar nikollatesla avatar pdapel avatar ramanaveli2i avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

node-rules's Issues

auto-next?

Why not have rules call next automatically when the condition function is done...? Saves boilerplate IMO.

Store functions as objects containing string representation and function object

The mixing of function definitions in the JSON specification of rules and such is a real pain, also for debugging. I can imagine a "debug" running mode where the functions are eval-ed from their string representations every time so yield meaningful errors and such.

I'm just starting to work with this great library, and that just made me cringe... Is this a change you are willing to consider?

Unregister rule

Hi there,

Nice work guys.
Was wondering why is there no method to unregister a rule.
Should not be a simple loop through the rules array ?

Regards

Large self-reference chain

Alright, so after adding the fix for #12 to my own node_modules directory, I tried again.

It seems that the returned object doesn't have execute as specified by the docs. Not only this, but on outputting the returned object, I get a /huge/ object which looks like it contains the object we created it in.

Let's say, for example, we created an array of rules.

var rules = [
    { name: 'Normal temperature',
      description: 'Standard safe temperatures.',
      priority: 3,
      on: 1,
      condition: [Function],
      consequence: [Function] }
]

We pass this into the RulesEngine..

var Engine = require("node-rules");
var e = Engine(rules);

Okay, now let's output it..

logger.debug(e);

I get output akin to the following (The above isn't production code, but this is output from it): https://gist.githubusercontent.com/gdude2002/63be061e9dccfe5497ca/raw/argh.js [WARNING: LARGE FILE]

While I know that a fair amount of this output is normal.. Where's .execute()?

Typescript support

Hello,

Thanks for creating a great library !!
I would like to use it with a Typescript project. Do you have any Type definition files which can be used?

Logic AND/OR between Rules

Is it possible to add AND/OR the this.result results between rules for a given fact?

Right now I'm doing this myself but its a bit messy using nested if statements in each Rule's "consequence" function

Question: Fact should always be a a simple Object or it can be an array as well ?

I am trying to use this module in my app.

Quick question- can i pass a complex object like below and apply rules on property like "f" in the below object which is an array of objects. How will this be handled inside When keyWord ?

a: {
        b: {
            c1: "i am key c1",
            c2: "",
            c3: undefined,
            c4: [],
            c5: NaN,
            c6: true,
            c7: false
        },
        d: NaN,
        e: "value a.e",
        f: [{
            firstName: "sampleFirstName",
            group: []
        }, {
            firstName: "sampleFirstName",
            group: [1, 3]
        }, {
            firstName: "sampleFirstName",
            group: []
        }],
        g: {
            firstName: "sampleLastName",
            lastName: "",
            age: NaN,
            city: undefined,
            Numbers: []
        },
        h: {
            firstName: "sampleFirstName",
            lastName: "",
            age: NaN,
            city: undefined,
            "h.a1": "I am Key with dot"
        },
        i: [{
            showWeather: true,
            weather: "sunny",
            temperature: "70F",
            city: "Dallas",
            days: ["mon", "tue", "wed"]
        }, {
            showWeather: true,
            weather: "",
            temperature: NaN,
            city: undefined,
            days: ["thr", "fri", "sat"]
        }, {
            showWeather: true,
            weather: "sunny",
            temperature: "70F",
            city: "Irving",
            days: []
        }, {
            showWeather: false,
            weather: "sunny",
            temperature: "70F",
            city: "Ft.Worth",
            days: []
        }]

    }
};

Creating dynamic rule object with nested rules

In my case i have an interface where various entities can set rules , hence there is no static set of rules which can be written on my codebase. i have to create them dynamically.But i have problems in creating nested rule objects where i have to validate if else tree scenarious with consequences for every test cases

Install failed for the release 3.0.2 on Windows

Hi,
Your module is very interesting and I would try to use it.

But,I will try to install the last release and

npm ERR! Windows_NT 6.1.7601
npm ERR! argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "i" "[email protected]"
npm ERR! node v0.12.0
npm ERR! npm  v2.5.1
npm ERR! path D:\Developpement\workspaces\webUI\gitAlert\node_modules\node-rules
npm ERR! code EEXIST
npm ERR! errno -4075

npm ERR! EEXIST, mkdir 'D:\Developpement\workspaces\webUI\gitAlert\node_modules\node-rules'
File exists: D:\Developpement\workspaces\webUI\gitAlert\node_modules\node-rules
Move it away, and try again.

I have to downgrade and use the release 3.0.1.

Using internally defined functions inside the conditions and consequence

what about using internally defined functions in conditions and consequence for flow control?

Like user can call fail(); to fail the execution completely. Or do a skip to(rule-id) to skip rest. Or even do a restart() to start over. These functions can reside inside the Engine scope and users can use them while defining rules.

Difference in the implementation of condition and consequence

If you see the implementation of both condition and consequence inside the engine, you can see that it is implemented in different ways. Consequence has the fact available in this context where in the condition has the fact injected into it via arguments.

We can keep both in same terms to keep the code more readable. Fact in context will be available in this at both condition and consequence.

Fixing this will in turn help in fixing #20.

Example code is not working my environment

I have trying to run example listed in https://github.com/mithunsatheesh/node-rules and getting following response, and not sure what may be missing. I am getting response "Valid transaction" instead of "The transaction was blocked as it was less than 500". I did not change any data in the "fact". The fact that first line in the response is empty {}, I feel data is not going into the RuleEngine and Rule. It could be issue with my environment but I could not nail it down.
Any help or pointer is much appreciated.

{}
{ name: 'user4',
application: 'MOB2',
transactionTotal: 400,
cardType: 'Credit Card',
result: true,
matchPath: [] }
Valid transaction

Catching exceptions in consequence/conditions

Is there a way to catch errors when the consequence/condition functions are called. I've modified the execute() method where it calls these functions as follows:

                        var _consequence = _rules[x].consequence;
                        process.nextTick(function() {
                            try {
                                _consequence.call(session, API);
                            }
                            catch (err) {
                                callback(err, session);
                            }
                        });

I've also modified the callback signature to take an error parameter but I'm not sure it is as simple as it seems?

Removing support for Array of consequence for a condition.

Currently Rule engine supports defining multiple consequences in the form of arrays for a single condition. This was added as per a previous issue raised. We don't find any strong reasons why we should keep a support for consequence arrays as the user can embed his logic inside a single consequence function.

Please share your thoughts.

Error when exporting rules using toJSON()

node_modules/node-rules/lib/node-rules.js:94
                _rule.call(session, API);
                      ^

TypeError: _rule.call is not a function
    at FnRuleLoop (/Users/anh/code/test/node_modules/node-rules/lib/node-rules.js:94:23)
    at RuleEngine.execute (/Users/anh/code/test/node_modules/node-rules/lib/node-rules.js:101:11)
    at Object.<anonymous> (/Users/anh/code/test/utils/ruleEngine.js:29:3)
    at Module._compile (module.js:569:30)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:503:32)
    at tryModuleLoad (module.js:466:12)
    at Function.Module._load (module.js:458:3)
    at Function.Module.runMain (module.js:605:10)
    at startup (bootstrap_node.js:158:16)

The code: I just copied the example.

const RuleEngine = require('node-rules')

//define the rules
var rules = [{
    "condition": function(R) {
        R.when(this && (this.transactionTotal < 500))
    },
    "consequence": function(R) {
        this.result = false
        R.stop()
    }
}]

//sample fact to run the rules on
var fact = {
    "name":"user4",
    "application":"MOB2",
    "transactionTotal":400,
    "cardType":"Credit Card",
}

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

var store = R.toJSON();
console.log(store)

//Now pass the fact on to the rule engine for results
R.execute(fact,function(result){
    
    if(result.result)
        console.log("Payment Accepted")
    else
        console.log("Payment Rejected")

})

Can't find fact values within rule. but i find values within response

I can't use my facts values wihtin my rules. can you help me with it?

const allowedActions = ['payment-received', 'checkin'];
  const rules = [
    {
      name: '1- Check actions',
      on: true,
      condition: (F) => {
       // this rule shouldn't execute, because i am providing proper action, but i find it undefined
        F.when(!allowedActions.includes(this.action));
      },
      priority: 100,
      consequence: (F) => {
        debug('1')
        // but its getting executed
        this.result = false;
        this.error = new CustomErrors.InvalidValueError(`please select only allowed action: ${allowedActions.join(', ')}`);
        F.stop();
      },
    },
    {
      name: '2- throw error If appointment is not cancelled or completed',
      on: true,
      priority: 90,
      condition: (F) => {
        debug('2');
        F.when(this.appointment.status >= enums.appointmentStatus.cancelled);
      },
      consequence: (F) => {
        this.result = false;
        this.error = new CustomErrors.PreconditionError('Can\'t edit appointment at this stage');
        F.stop();
      },
    },
    {
      name: '3- Check if action is "checkin" and status is confirmed',
      on: true,
      priority: 80,
      condition: (F) => {
        debug('3');

        F.when(this.action === 'checkin' && this.appointment.status === enums.appointmentStatus.confirmed);
      },
      consequence: (F) => {
        this.result = true;
        this.status = enums.appointmentStatus.checkin;
        F.stop();
      },
    },
    {
      name: '3- Check if payment received and provider exists',
      on: true,
      priority: 70,
      description: 'check if payment received and provider exists',
      condition: (F) => {
        debug('3');
        F.when(this.appointment.provider && this.action === 'payment-received');
      },
      consequence: (F) => {
        this.result = true;
        this.status = enums.appointmentStatus.confirmed;
        F.stop();
      },
    },
    {
      name: '4- check if payment received and provider DOES NOT exists',
      on: true,
      priority: 60,
      description: 'check if payment received and provider exists',
      condition: (F) => {
        debug('4');

        F.when(!this.appointment.provider && this.action === 'payment-received');
      },
      consequence: (F) => {
        // NOTE: this status is confirmed from shafaque (2:23PM, 21-Nov-17 discussion)
        this.result = true;
        this.status = enums.appointmentStatus.new;
        F.stop();
      },
    },
    {
      name: '5- if there is no result assigned, this should throw error',
      on: true,
      priority: 1,
      condition: (F) => {
        F.when(!this.result);
      },
      consequence: (F) => {
        debug('5');
        this.result = false;
        this.error = new CustomErrors.BadRequestError("couldn't identify next status");
        F.stop();
      },
    },
  ];

  const ruleEngine = new RuleEngine();
  ruleEngine.register(rules);
  return new Promise((resolve, reject) => {
    debug(payload);
    ruleEngine.execute({
      action: 'checkin',
      appointment: { status: 7, provider: "ABC XYZ" }
    }, (response) => {
     // here i get all facts, match_paths etc.
      debug('result = ', response);
      if (response.result) {
        resolve({ result: response.status });
      } else {
        reject(response.error);
      }
    });
  });

Modify fact in consequences

Thanks for the much needed module.

I'm wondering if it's possible to modify the fact object inside of the consequences function?

If so, how do would you get at the modified fact in the execute callback?

Here's a sample rule where I want to modify a field on the fact based on the test:

{
    name: "Source Test",
    condition: function(R) {
        R.when(this.Title === "STF" && this.Credit === "Noble Source")
    },
    consequence: function(R) {
        this.Caption = this.Caption + ". Noble Staffer found!";
        R.next()
    }
}

Thanks,
Fred

How to use node-rules with questions?

Hello,
I would like to develop an akinator/20q like application. I have some objects with caracteristics. After some auto selected questions (yes/no/don't know), the application will choose the best object according to user answers.
Is node-rules a good solution to do that? Should I use a decision tree library instead? I to s there a way to cover all possible questions?
Thank you :-)

Question: Running facts in batches

Firstly thanks a lot for this library! Working with this has been a pleasure!

I wrapped your library in a REST API. I then sent it batches of anything from 100 to a 1000 records / facts to evaluate. The API call must only resolve once all the facts have been evaluated. I achieved it using Q like below.

function run(facts) {

	var promises = [];

	facts.forEach(function(value, key) {
		promises.push(perFactRuleRunner(value));
	});

	return Q.all(promises);
}

function perFactRuleRunner(fact) {

	var defer = Q.defer();

	R.execute(fact, function(data) {
		defer.resolve(data);
	}, function(error){
		defer.reject(error);
	});

	return defer.promise;
}

Is there a builtin way to achieve the same result, or must I stick with this?

Implement function Rules.register as part of Engine

Currently we pass the rules to apply via the constructor call. This wont be useful when we need to perform add/update/delete on a running rule engine. So we need to separate this as a new function named add. It will accept both array of rules as well as a single rule and input.

Equality condition does not work in Rules engine

I changed the rule in the samepleRule.js such that it is now using the "===" in rules. After that the rules is not getting evaluated properly. The changed file is attached here with. Could any of you help with the same.

PS
The same below code is also attached as text file for easy execution and clarity

simpleRule - Copy.txt

Rules run twice

Hi,

First of all, great module.
I found that the rules are being applied twice, generating duplication in same cases.

Version: 3.0.2

RuleEngine = require('node-rules')

rules = [
  {
      "name": "rule1",
      "condition": (R) ->
        R.when(this.value1 > 5)
      ,
      "consequence": (R) ->
        @result = false;
        @errors = @errors || []
        @errors.push('must be less than 5')
        R.next()
  }
]

fact = {
    "value1": 6
}

R = new RuleEngine(rules)

R.execute(fact, (result) ->
  console.log(JSON.stringify(result))
)

It should print

{"value1":6,"result":false,"errors":["must be less than 5"]}

but instead is printing:

{"value1":6,"result":false,"errors":["must be less than 5","must be less than 5"]}

Cheers.

rule signature and execute improvements

First off this is very simple to get going, thanks!

But....

The very first thing i wanted to do is add more properties to rules, that are used from within the rule's functions, e.g. a threshold value for comparing to the fact's properties. Another good thing to access is the rule's name, because what good is it if we don't know which rule(s) actually accepted the fact?

There appears to be no interface for this, but it is incredibly easy to add.

within the RuleEngine.prototype.execute function, simply add this to the API object's definition (roughly line 55):

var API = {
  "rule": function() { return _rules[x]; },
  // the rest

i added this to my copy and it works great! please incorporate into the code. Here is a sample of how it works:

{
    "name": "Array Too Long",
    "threshold": 0,
    "condition": function(rx) {
        rx.when(this.fact.hasOwnProperty("value") && this.fact.value instanceof Array && this.fact.value.length > rx.rule().threshold);
    },
    "consequence": function(rx) {
        this.accepted = true;
        this.addAdvice(rx.rule().name, "warning", "Too many errors and warnings: " + this.fact.value.length + "; threshold: " + rx.rule().threshold);
        rx.next();
    }
},

You should also consider providing more infrastructure for returning evaluation results, beyond a simple boolean. In this example, i get a nice list of all the consequences, via addAdvice(), but that should be built-in to the engine.

A "better" calling convention for rules would be to set "this" to the rule itself, and add the fact as another parameter to the rule functions.

Another change should be to allow passing a separate context object to the rules from execute(), instead of the "modules" workaround that attaches all that to each fact. That should be a "constant" object passed into execute() and then passed to the rule functions:

var context = { "http": require("http"), "url": require("url"), "otherstuff": true };
engine.execute(context, fact, function(result) { dosomething(); });

and using the proposed function signature changes:

"name": "The New Rule Signatures",
"path": "/the/path/to/check",
"threshold": 0,
"condition": function(R, context, fact) {
    R.when(context.url.parse(fact.url).path == this.path && fact.count > this.threshold);
},
"consequence": function(R, context, fact) {
    context.accepted = true;
    context.addAdvice(this.name, "warning", "Whatever message: " + fact.count + "; threshold: " + this.threshold);
    rx.next();
}

That just reads better!

Another feature to implement is providing for intermediate results to be passed between the condition and consequence functions. For example, the "fact" is actually an array, and a traversal is required (map/reduce) before evaluating the condition. Attaching that result object to the fact is bad news, it causes a re-scan of the rules! Better would be to allow the condition to return a value that is then passed to the consequence, so it can leverage the computed results, instead of repeating them.

Implement function Rules.sync as part of Engine

Separate the rule set up logic which is currently inside RuleEngine constructor to a new function called sync. This will help when we add functionality to add rules later and resync them with priority and status.

Also once this is done, sync will be internally called by all functions which make changes to the rule engine. Like adding rules, editing or deleting.

Implement Rules.toJSON() and Rules.fromJSON() functions

Currently the rule engine supports stringified rules. But the logic is embedded in the core engine logic. We don't want this. The engine should support serialise() and unserialise() functions so that the rules can be stored on to an external storage and loaded back on. Once this is implemented, we can remove the evals from the core engine code.

consider use node's vm module instead of eval when using fromJSON

no need to add details for why eval is evil so i think a better solution and more safety is to use the vm module.

example implementation (it works):

RuleEngine.prototype.fromJSON = function(rules) {
        var sandbox = {
            condition: undefined,
            consequence: undefined
        };

        this.init();
        if (typeof(rules) == "string") {
            rules = JSON.parse(rules);
        }
        if (rules instanceof Array) {
            rules = rules.map(function(rule) {
                sandbox = {
                    condition: undefined,
                    consequence: undefined
                };

                vm.runInNewContext("condition = (" + rule.condition + ")", sandbox);
                vm.runInNewContext("consequence = (" + rule.consequence + ")", sandbox);

                rule.condition = sandbox.condition;
                rule.consequence = sandbox.consequence;
                return rule;
            });
        } else if (rules !== null && typeof(rules) == "object") {
            vm.runInNewContext("condition = (" + rule.condition + ")", sandbox);
            vm.runInNewContext("consequence = (" + rule.consequence + ")", sandbox);

            rule.condition = sandbox.condition;
            rule.consequence = sandbox.consequence;
        }
        this.register(rules);
    };

Rules Editor

While the node-rules module solves the runtime problem of executing rule, how about having simple minimalist UI to author business rules? I understand its a big move, but collaboratively we can achieve.

something like,

  1. UI to author business rules based on vocabulary,
  2. decistion table to author symmetric rules,
  3. decision tree to author asymmetric rules...

Upcoming release?

There doesn't seem to be a GitHub release since 2015. It might be useful to have a recent release available on the GitHub releases page.

What are the plans for an upcoming release?

Fact availability in consequence

Is it possible to have the matched fact available in the consequence? We're attempting to use this rules engine to match arbitrary data from a database and then to - for example - send an email on match. We'd need the fact itself to be available for that, though.

So, is it possible to get at the fact from within the consequence function?

EDIT: Also, I've noticed that calling cb() within a consequence results in the consequence being run multiple times, so I've decided not to call it. What's the cb() for?

Turning Rules On and Off in runtime.

Currently there is no way that we can turn off or turn on rules after the rule engine is initialized. The On and Off function will allow the user to turn off and turn on a rule dynamically by providing a rule id field which should be used to uniquely identify a rule.

Note: Right now rule id is not a mandatory field. We may need to enforce that field to get this feature working.

Use external module in consequence

I'm wondering if there's any way to use an external module inside of a consequence function?

I was hoping to be able to do something like the following:

    {
        "condition" : function(R) {
            R.when(true)
        },
        "consequence" : function(R) {
            var guid_generator = require('uuid');
            this.RecordId = guid_generator.v4();
            R.next();
        }
    }

However, that seems to trigger a recursive loop with this error:

(node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral.

I imagine this is because require() uses process.nextTick().

Forgive me if this is a naive question as I'm new to Node and Javascript.

Thanks,
Fred

Register function

There is an error in the "register" function: the condition of "if" (if (rules instanceof Array)) does not work so you must change it to "if (Array.isArray(rules))".

Hence, now, the register function looks like:

 RuleEngine.prototype.register = function(rules) {
    if (Array.isArray(rules)) {
        this.rules = this.rules.concat(rules);
    } else if (rules !== null && typeof(rules) == "object") {
        this.rules.push(rules);
    }
    this.sync();
};

How does it work for Objects with nested elements?

I have my JSON Object as shown below

var fact = {
        "testList": [{
            "test" : {
                "name" : "Steelers"
            }
        }]
 };

Trying to filter based on a return value of true.

var rule = {
        "condition": (ruleEngine) => {
            ruleEngine.when(this.testList[0].test.name === "Steelers" );
        },
        "consequence": (ruleEngine) => {
            this.result = true;
            ruleEngine.stop();
        }
    };

I am seeing the below error

mscorlib: TypeError: Cannot read property '0' of undefined
    at Object.condition (D:\home\site\wwwroot\RulesEngine\index.js:12:46)
    at FnRuleLoop (D:\home\site\wwwroot\RulesEngine\node_modules\node-rules\lib\node-rules.js:98:23)
    at RuleEngine.execute (D:\home\site\wwwroot\RulesEngine\node_modules\node-rules\lib\node-rules.js:105:11)
    at module.exports (D:\home\site\wwwroot\RulesEngine\index.js:39:16)
    at D:\Program Files (x86)\SiteExtensions\Functions\1.0.11820\bin\azurefunctions\functions.js:106:24.

Not sure what I am missing here. Does this library support nested objects as facts?

npm ERR! tar.unpack untar error on Windows

NodeJs : 0.12.2
Npm : 2.7.4

npm ERR! tar.unpack untar error C:\Users\lmo0\AppData\Roaming\npm-cache\node-rules\3.0.2\package.tgz
npm ERR! Windows_NT 6.1.7601
npm ERR! argv "C:\\Program Files (x86)\\nodejs\\\\node.exe" "C:\\Program Files (x86)\\nodejs\\node_modules\\npm\\bin\\npm-cli.js"
"-g" "install" "node-rules"
npm ERR! node v0.12.2
npm ERR! npm  v2.7.4
npm ERR! path C:\Users\<User>\AppData\Roaming\npm\node_modules\node-rules
npm ERR! code EEXIST
npm ERR! errno -4075

npm ERR! EEXIST, mkdir 'C:\Users\<User>\AppData\Roaming\npm\node_modules\node-rules'
File exists: C:\Users\lmo0\AppData\Roaming\npm\node_modules\node-rules
Move it away, and try again.

npm ERR! Please include the following file with any support request:
npm ERR!     Z:\lmo0\git\puppet\puppet-test\npm-debug.log

Can I run many RuleEngine with different rules at the same time?

Please help, Let says:

  • I have many facts.
  • With every fact, I would like to run a rule engine with a different set of rules.
  • the rule engine for every fact could be run at the same time.
    --> Can I do that with node-rules (many instances of ruleEngine at a same time)?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.