Nools
Rete based rules engine written in javascript
Install / Use
/learn @noolsjs/NoolsREADME
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.
Nools
Nools is a rete based rules engine written entirely in javascript.
Installation
npm install nools
Or download the source (minified)
Usage
- Flows * Defining A Flow * Sessions * Facts
- Defining Rules
- Browser Support
- Fibonacci
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
textmust match the regular expression/^hello\\sworld$/ - When matched the message's
textis modified and then we let the engine know that we modified the message.
- Goodbye
- Requires a Message
- The messages's
textmust 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 assertedretract (fact)- emitted when facts are retractedmodify (fact)- emitted when facts are modifiedfire (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.noolsor 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 usingnools.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
node-connect
336.9kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
83.0kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
336.9kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
83.0kCommit, push, and open a PR


