SkillAgentSearch skills...

Nools

Rete based rules engine written in javascript

Install / Use

/learn @noolsjs/Nools
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Deprecation Warning

C2FO is no longer maintaining this project. Please use accordingly. If you would like to help maintain or take over the project please let us know.

Build Status

browser support

Nools

Join the chat at https://gitter.im/C2FO/nools

Nools is a rete based rules engine written entirely in javascript.

Installation

npm install nools

Or download the source (minified)

Usage

Resources

<a name="flow"></a>

Defining a flow

When using nools you define a flow which acts as a container for rules that can later be used to get a session

Programmatically

var nools = require("nools");

var Message = function (message) {
    this.text = message;
};

var flow = nools.flow("Hello World", function (flow) {

    //find any message that is exactly hello world
    flow.rule("Hello", [Message, "m", "m.text =~ /^hello\\sworld$/"], function (facts) {
        facts.m.text = facts.m.text + " goodbye";
        this.modify(facts.m);
    });

    //find all messages then end in goodbye
    flow.rule("Goodbye", [Message, "m", "m.text =~ /.*goodbye$/"], function (facts) {
        console.log(facts.m.text);
    });
});

In the above flow definition 2 rules were defined

  • Hello
    • Requires a Message
    • The messages's text must match the regular expression /^hello\\sworld$/
    • When matched the message's text is modified and then we let the engine know that we modified the message.
  • Goodbye
    • Requires a Message
    • The messages's text must match the regular expression /.*goodbye$/(anything that ends in goodbye)
    • When matched the resulting message is logged.

DSL

You may also use the nools rules language to define your rules.

The following is the equivalent of the rules defined programmatically above.

define Message {
    text : '',
    constructor : function(message){
        this.text = message;
    }
}

//find any message that starts with hello
rule Hello {
    when {
        m : Message m.text =~ /^hello(\s*world)?$/;
    }
    then {
        modify(m, function(){this.text += " goodbye";});
    }
}

//find all messages then end in goodbye
rule Goodbye {
    when {
        m : Message m.text =~ /.*goodbye$/;
    }
    then {
        console.log(m.text);
    }
}

To use the flow

var flow = nools.compile(__dirname + "/helloworld.nools"),
    Message = flow.getDefined("message");

Flow Events

Each flow can have the following events emitted.

  • assert (fact) - emitted when facts are asserted
  • retract (fact) - emitted when facts are retracted
  • modify (fact) - emitted when facts are modified
  • fire (name, rule) - emitted when an activation is fired.
session.on("assert", function(fact){
    //fact was asserted
});

session.on("retract", function(fact){
    //fact was retracted
});

session.on("modify", function(fact){
    //fact was modifed
});

session.on("fire", function(name, rule){
    //a rule was fired.
});

nools.compile

The compile method accepts the following parameters

  • source|path - The first argument must either be a path that ends in .nools or a string which is the source of the rules that you wish to compile.
  • options?
    • name : This is the name of the flow. You can use this name to look up the flow by using nools.getFlow.
    • define : A hash of Classes that should be aviable to the rules that you are compiling.
    • scope: A hash of items that should be available to rules as they run. (i.e. a logger)
  • cb? - an options function to invoke when compiling is done.

Example

rule "person name is bob" {
    when {
        p : Person p.name == 'bob';
    }
    then {
        logger.info("Found person with name of bob");
        retract(p);
    }
}

In the above rules file we make use of a Person class and a logger. In order for nools to properly reference the Class and logger you must specify them in your options.

var flow = nools.compile("personFlow.nools", {
    define: {
        //The person class the flow should use
        Person: Person
    },
    scope: {
        //the logger you want your flow to use.
        logger: logger
    }
});

You may also compile source directly.

var noolsSource = "rule 'person name is bob' {"
    + "   when {"
    + "     p : Person p.name == 'bob';"
    + "   }"
    + "   then {"
    + "       logger.info('Found person with name of bob');"
    + "       retract(p);"
    + "   }"
    + "}";

var flow = nools.compile(noolsSource, {
    define: {
        //The person class the flow should use
        Person: Person
    },
    scope: {
        //the logger you want your flow to use.
        logger: logger
    },
    name: 'person name is bob'
});

<a name="session"></a>

Working with a session

A session is an instance of the flow that contains a working memory and handles the assertion, modification, and retraction of facts from the engine.

To obtain an engine session from the flow invoke the getSession method.

var session = flow.getSession();

<a name="facts"></a>

Working with facts

Facts are items that the rules should try to match.

<a name="facts-assert"></a>

Assert

To add facts to the session use assert method.

session.assert(new Message("hello"));
session.assert(new Message("hello world"));
session.assert(new Message("goodbye"));

As a convenience any object passed into getSession will also be asserted.

Note assert is typically used pre engine execution and during the execution of the rules.

flow.getSession(new Message("hello"), new Message("hello world"), new Message("goodbye"));

<a name="facts-retract"></a>

Retract

To remove facts from the session use the retract method.

var m = new Message("hello");

//assert the fact into the engine
session.assert(m);

//remove the fact from the engine
session.retract(m);

Note retract is typically used during the execution of the rules.

<a name="facts-modify"></a>

Modify

To modify a fact use the modify method.

Note modify will not work with immutable objects (i.e. strings).


var m = new Message("hello");

session.assert(m);

m.text = "hello goodbye";

session.modify(m);

Note modify is typically used during the execution of the rules.

<a name="get-facts"></a>

Retrieving Facts

To get a list of facts currently in the session you can use the getFacts() method exposed on a session.

session.assert(1);
session.assert("A");
session.assert("B");
session.assert(2);

session.getFacts(); //[1, "A", "B", 2];

You may also pass in a Type to getFacts which will return facts only of the given type.

session.assert(1);
session.assert("A");
session.assert("B");
session.assert(2);

session.getFacts(Number); //[1, 2];
session.getFacts(String); //["A", "B"];

<a name="firing"></a>

Firing the rules

When you get a session from a flow no rules will be fired until the match method is called.

var session = flow.getSession();
//assert your different messages
session.assert(new Message("goodbye"));
session.assert(new Message("hello"));
session.assert(new Message("hello world"));

//now fire the rules
session.match(function(err){
    if(err){
        console.error(err.stack);
    }else{
        console.log("done");
    }
})

The match method also returns a promise that is resolved once there are no more rules to a

Related Skills

View on GitHub
GitHub Stars957
CategoryDevelopment
Updated2mo ago
Forks176

Languages

JavaScript

Security Score

95/100

Audited on Jan 22, 2026

No findings