A JavaScript library for structuring business rules.
Overview
Structuring and validating business rules in JavaScript
Example
Consider the following scenario:
On entering a train station, passengers are required to insert a ticket into a slot beside a closed barrier. An entry barrier opens only if the ticket meets all of the following criteria:
- it is valid for travel from that station;
- it has not expired;
- it has not already been used for the maximum number of journeys allowed.
'use strict'; // use promise-based specificationsvar Spec = PromiseSpec; // hardcore the `today` date for the sake of consistent resultsvar TODAY = 2015 2 1; // Is the ticket expired?var { return Promise;}; // Is the ticket has been used for the maximum number of journeys allowed?var { return Promise;}; // Is the ticket valid for travel from `name` station?var { return Promise;}; // Rule implementation for the `Riva` station barriervar barrierSpec = ; // A ticket we would like to checkvar ticket = stations: 'Riva' expires_at: 2015 2 6 max_journeys: 30 cur_journeys: 11; // Verify the ticket satisfies the created specificationbarrierSpec ;
Installation
installing with npm:
$ npm install bspec --save
In browser
To use bspec in a browser, use the bspec.js
file in the /dist
directory of this repository, or build it manually. To build a fresh version:
$ npm install$ npm run browser
installing with bower:
$ bower install bspec
Usage
The essential part of the library is a specification -- an object with the following properties:
- it can be combined with other specification-objects using
.and()
,.or()
and.not()
methods to form a composite specification and express more complex rules. - it implements
isSatisfiedBy
method -- a predicate that determines whether a candidate object does or does not satisfy some criteria.
The library supports the following specifications:
- Synchronous --
SyncSpec
- Callback-based --
CallbackSpec
- Promise-based --
PromiseSpec
var Spec = SyncSpec;
var Spec = CallbackSpec;
var Spec = PromiseSpec;
To create a composable specification, make an instance of Spec
and define the isSatisfiedBy
method to check for some condition. isSatisfiedBy
method signature depends on the type of specification (see the API section below).
There are several ways you can define the isSatisfiedBy
method:
- Write a predicate-function and wrap it in a
Spec
object; - Create an object with the
isSatisfiedBy
property and wrap it in aSpec
object; - Derive a new object from
Spec
and implement theisSatisfiedBy
function.
Spec
object
Writing a predicate-function and wrapping it in a var Spec = SyncSpec; { return > orderdate;} var expiredSpec = isExpired;console;
isSatisfiedBy
property and wrapping it in a Spec
Creating an object with the var Spec = SyncSpec; var isExpired = { return > orderdate; }; var expiredSpec = isExpired;console;
Spec
and implementing the isSatisfiedBy
function
Deriving a new object from var Spec = SyncSpec;var util = ; { } util; IsExpiredSpecprototype { return > orderdate;}; var expiredSpec = ;console;
OR with ES6 classes:
var Spec = SyncSpec; { return > orderdate; } var expiredSpec = ;console;
API
.and(otherSpec)
the and of a set of specifications is true if and only if all of its operands are true.
var spec = spec1;
.or(otherSpec)
the or of a set of specifications is true if and only if one or more of its operands is true
var spec = spec1;
.not()
not negates the specification
var spec = spec1;
.explain()
returns a string that describes a composite specification
console;// ((ValidOrderSpec AND (NOT OverDueOrderSpec)) AND (NOT OrderProcessed))
NOTE: meaningful names will be printed only for specifications derived from a Spec
object.
.isSatisfiedBy(...)
checks whether some candidate object satisfies the specification. isSatisfiedBy method signature depends on the specification type:
SyncSpec (synchronous specification)
// signature: : boolean; // usage: var result = spec.isSatisfiedBy(obj); // `result` true|false value // should throw an exception in case of an error
CallbackSpec (callback-based specification)
// signature: : void; // usage: spec.isSatisfiedBy(obj, function(err, result) { // `err` contains an error if any // `result` true|false value });
PromiseSpec (promise-based specification)
// signature: : Promise; // usage: spec.isSatisfiedBy(obj) .then(function(result) { // `result` true|false value });
NOTE: To use promise-based specifications you need ES6 Promise to be implemented in your environment, e.g. io.js
, a modern browser or a polyfill like es6-promise.
For the details of usage, take a look at the examples section in the project.
Tests
To run the tests for bspec:
$ npm test
Contact
License
Distributed under the The MIT License (MIT).