1.0.1 • Published 5 years ago

blackbox-rules v1.0.1

Weekly downloads
6
License
MIT
Repository
bitbucket
Last release
5 years ago

blackbox-rules

Version standard-readme compliant

Blackbox rulebase and basic rules engine.

The blackbox-rules package provides a basic framework for a distributed rules engine suitable for use in a Blackbox API. The project includes the rules engine and classes and interfaces for defining rules.

A Rule consist of a pre-condition, trigger, action and post-condition, all of which are Conditions. Conditions are made up of a type and left and right Values. Rules execute according to the following process:

  1. Make pre-condition true,
  2. Check if trigger Condition is true,
  3. If trigger Condition is true make action Condition true,
  4. Make post-condition true.

This package contains the basic components required to build a rulebase, but does not provide an implementation for numerous details such as the rule store (database) or mechanisms for interacting with remote rules. For default implementations of these required components, you can use the blackbox-rules-utils package. For use of the rulebase within the Blackbox IOC container see the blackbox-rules-services package.

For further information about the Blackbox Specification refer to the Blackbox website.

Table of Contents

Install

npm i blackbox-rules

Usage

Create a rulebase:

import RuleBase from 'blackbox-rules'

const rulebase = new RuleBase({
  runPeriod: 100,
  store: new MyStore(),
  remoteValueProtocol: new MyRemoteValueProtocol(),
  variableStore: new MyVariableStore()
});

Create a rule with triggers and actions:

rulebase.when(trigger).then(action).withName('my new rule')

Create an equals condition from two values:

leftValue.eq(rightValue).withName('trigger')

Create a constant value:

rulebase.constantValue('xml').withName('type')

Execute rules:

rulebase.processRules()

Alternaively you can assign interrupts to your rules and then start the rulebase:

rule.interrupt = new MyInterrupt()
rulebase.addRule(rule)
rulebase.start()

If start() is called and a rule is encountered with no interrupt it will be given a default of TimerInterrupt with a timeout set to rulebase.runPeriod. To stop the rule execution simply call rulebase.stop().

An example of blackbox-rules can be found on the Blackbox website.

API

RuleBase

import RuleBase from 'blackbox-rules'

constructor(params:{
  store?:Store,
  remoteValueProtocol?:RemoteValueProtocol,
  variableStore?:VariableStore,
  runPeriod?:number}
)

RuleBase CRUD

addValue(v:Value<any>) getValue(valueName:string):Value<any> removeValue(name:string) replaceValue(v:Value<any>) allValues():Value<any>[]

addCondition(c:Condition) getCondition(conditionName:string):Condition removeCondition(name:string) replaceCondition(c:Condition) allConditions():Condition[]

addRule(r:Rule) getRule(ruleName:string):Rule removeRule(name:string) replaceRule(r:Rule) allRules():Rule[]

Rule Processing

processRule(rule:Rule) Asynchronousely process a single rule.

processRules():Promise<boolean> Asynchronousely process all rules. Rules will only be processed if the time since the last call to processRules() is greater than RuleBase.runPeriod. This method of processing rules allows for manual handling of rule execution.

start() Start all rule interrupts. This method of processing rules allows for automatic handling of rule execution.

stop() Stop all rule interrupts.

RuleBase Factory Methods

when(trigger:ConditionData) Create a rule with a when().then() pattern.

unconditional():Condition Provides a Condition that always returns true.

constantValue<T>(v:T):ConstantValue<T>&WithName<ConstantValue<T>> Provides a Value whose get() method always returns v and cannot be changed; set(v) does nothing.

remoteValue<T>(remoteAddress:string, remoteValueName:string):RemoteValue<T>&WithName<RemoteValue<T>> Provides a value that is a proxy for a value in another rulebase.

dateTimeValue():DateTimeValue&WithName<DateTimeValue> Provides a read-only Value that gives the current date and time in a Date object.

logValue():LogValue&WithName<LogValue> Provides a write-only Value that logs the value given when calling set(v).

Store

An interface encapsulating the functionality required for storing Rules, Conditions, and Values.

VariableStore

An interface encapsulating the fuctionality required for storing VariableValues.

RemoteValueProtocol

An interface encapsulating the funcitonality required to interact with a remote Value.

RuleInterrupt

start(rulebase:RuleBase, rule:Rule) Called by the rulebase for each rule when RuleBase.start() is called. The Interrupt should set itself up ready to call rulebase.processRule(rule) when it's interrupt condition is met. For example, the TimerInterrupt setups up an interval timer to periodically process the rule.

stop(rulebase:RuleBase, rule:Rule) Called by the rulebase for each rule when RuleBase.stop() is called. The Interrupt should stop processing interrupts.

TimerInterrupt

A RuleInterrupt that setups up an interval timer to periodically process the rule.

Rule

The Rule class consists of a name and Conditions and can be constructed with the Rule constructor:

constructor(params:{
  name?:string
  preCondition?:Condition
  postCondition?:Condition
  trigger?:Condition
  action?:Condition
})

or with the RuleBase factory methods: rulebase.when(trigger).then(action).

Condition

The Condition interface includes a name and type, and checkTrue():boolean and makeTrue() methods. checkTrue() should return true if the condition is true, and makeTrue() changes the condition such that the next call to checkTrue() should return true. checkTrue() applies to triggers, while makeTrue() applies to pre-conditions, actions and post-conditions.

The Condition interface extends Value<boolean> since Conditions make up the left and right Values of an AndCondition and an OrCondition.

The ConditionImpl class provides a default implementation of a Condition. It can be constructed with the ConditionImpl constructor:

constructor(params:{
  name?:string
  left?:Value<any>
  right?:Value<any>
  type?:string
  template?:any
})

however the checkTrue() and makeTrue() methods will throw exceptions and must be overwritten in subclasses or instances. ConditionImpl also provides factory methods to create AndConditions and OrConditions via the and(cond:Condition) and or(cond:Condition) methods.

Some basic Conditions are provided through the following classes: EqualsCondition GreaterThanCondition LessThanCondition AndCondition OrCondition.

Value

The Value<T> interface incudes a name and type, and get():T and set(v:T) methods.

The ValueImpl<T> class provides a default implementation of a Value<T>. It can be constructed with the ValueImpl constructor:

constructor(params:{
  name?:string
	type?:string
})

however the get() and set() methods will throw exceptions and must be overwritten in subclasses or instances. ValueImpl also provides factory methods to create EqualsConditions, LessThanConditions and GreaterThanConditions via the eq(rhs:Value<T>), eq(rhs:Value<T>) and eq(rhs:Value<T>) methods.

Some basic Values are provided through the following classese: ConstantValue DateTimeValue LogValue RemoteValue VariableValue

Maintainers

@ellipsistechnology

Contributing

PRs accepted.

Small note: If editing the README, please conform to the standard-readme specification.

License

MIT © 2019 Ben Millar