npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

jsrules

v0.2.8

Published

jsrules is a rule engine that models formal propositional logic. It allows you to separate conditional logic from source code and database triggers in a reusable package, where explicit rules can be independently defined and managed.

Downloads

151

Readme

jsrules

jsrules is a JavaScript rule engine that models formal propositional logic. It allows you to separate conditional logic from source code and database triggers in a reusable package, where explicit rules can be independently defined and managed.

build status Coverage Status Code Climate Codacy Badge

Overview of jsrules

What are Rules?

Rules are explicit constraints that govern actions.

Rules are defined and stored as JSON. They consist of three types of RuleElements:

  • Propositions: statements that are either, true, false, or null (unknown)
  • Variables: symbols that represent the value of something
  • Operators: Boolean and quantifier operators

RuleContexts (aka "facts") and Rules

RuleContexts are facts, stored in text files, databases, etc., that provide the informational context for the execution of Rules. Rules evaluate RuleContexts, returning a Proposition that tells us whether a given set of facts conform to the defined Rule.

RuleElements are evaluated using Reverse Polish Notation (RPN). See the examples below for details.

Example 1: Is this customer eligible for a discount?

Executing a Rule is simple. Suppose we have a very simple rule that checks whether a customer is eligible for a discount. In order to be eligible, the customer simply needs to be a Gold Card holder.

// Create the rule
var rule = new jsrules.Rule('eligibleForDiscount');

// Add a Proposition, i.e., a statement that has a value of true or false
rule.addProposition('customerIsGoldCardHolder', true);

// Create a RuleContext, i.e., a "Fact"
var ruleContext = new jsrules.RuleContext('eligibleForDiscountContext');

// Provide the truth statement as to whether the actual customer
// has a Gold Card
ruleContext.addProposition('customerIsGoldCardHolder', true);

// Evaluate
var result = rule.evaluate(ruleContext);

// Log the resulting Proposition
console.log(result.toString());

// Outputs
// Proposition statement = customerIsGoldCardHolder, value = true

Example 2: Group discount for six or more people

Say you provide a discount to a group of six or more people:

// Create the rule
var rule = new jsrules.Rule('eligibleForGroupDiscount');

// Declare a "placeholder" variable for the actual number of people
// (This value will be retrieved from the RuleContext)
rule.addVariable('actualNumPeople', null);

// Declare the minimun number of people required for discount
rule.addVariable('minNumPeople', 6);

// Compare the two, i.e.,
// actualNumPeople >= minNumPeople
rule.addOperator(jsrules.Operator.GREATER_THAN_OR_EQUAL_TO);

// Create a RuleContext, i.e., a "Fact"
var ruleContext = new jsrules.RuleContext('eligibleForGroupDiscountFact');

// How many people are there?
ruleContext.addVariable('actualNumPeople', 5);

// Declare the "placeholder" minimun number of people required for discount
// (This value will be retrieved from the Rule)
ruleContext.addVariable('minNumPeople', null);

// Evaluate
var result = rule.evaluate(ruleContext);

// Log the resulting Proposition
console.log(result.toString());

// OUTPUT:
// Proposition statement =
// (actualNumPeople >= minNumPeople), value = false

Example 3: Is an airline passenger eligible for an upgrade?

In this example, we’re determining whether a given airline passenger is eligible to have their coach seat upgraded to a first-class seat. In order to be eligible, a passenger must:

  • be in economy class now and either
  • hold a Gold member card or
  • hold a Silver member card and
  • their carry-on luggage must be less than or equal to 15.0 pounds.

In order to determine this, we must compare a passenger’s facts with our rule.

// Create the rule
var rule = new jsrules.Rule('eligibleForUpgrade');

// Populate the rule using method chaining
rule.addProposition('passengerIsEconomy', true)
    .addProposition('passengerIsGoldCardHolder', true)
    .addProposition('passengerIsSilverCardHolder', true)
    .addOperator(jsrules.Operator.OR)
    .addOperator(jsrules.Operator.AND)
    .addVariable('passengerCarryOnBaggageWeight', null)
    .addVariable('passengerCarryOnBaggageAllowance', 15.0)
    .addOperator(jsrules.Operator.LESS_THAN_OR_EQUAL_TO)
    .addOperator(jsrules.Operator.AND);

// Create the RuleContext
var fact = new jsrules.RuleContext('eligibleForUpgradeFact');

// Load it with the facts about the passenger
fact.addProposition('passengerIsEconomy', true)
    .addProposition('passengerIsGoldCardHolder', true)
    .addProposition('passengerIsSilverCardHolder', false)
    .addVariable('passengerCarryOnBaggageWeight', 10.0)
    .addVariable('passengerCarryOnBaggageAllowance', null);

// Log the resulting Proposition
console.log(rule.evaluate(fact));

// Outputs (as a single string; newlines added here for readability):
// Proposition statement = (
//  (passengerIsEconomy AND
//    (passengerIsGoldCardHolder OR passengerIsSilverCardHolder)
//  ) AND (
//    passengerCarryOnBaggageWeight <= passengerCarryOnBaggageAllowance
//  )
// ), value = true

Installation

npm

$ npm install jsrules

bower

$ bower install jsrules

Specs/tests

Execute specs (and code coverage) with either

$ grunt test

or

$ npm test

The origin of jsrules: the Rule Archetype Pattern

For a detailed description of jsrules, please read chapter 12, “Rule archetype pattern,” in Enterprise Patterns and MDA: Building Better Software with Archetype Patterns and UML. I cannot recommend this book enough, and my thanks go to its authors — Jim Arlow and Ila Neustadt — for their permission to avail the “Rule Archetype Pattern” to JavaScript developers.

Development roadmap

  1. ~~Quality assurance~~
  2. ~~Code coverage with istanbul.~~
  3. ~~travis-ci integration.~~
  4. ~~Complexity reports.~~
  5. Persistence: create examples where
  6. Rules are created, read, updated, and deleted (e.g., Redis or MongoDB)
  7. RuleContexts (facts) are retrieved from multiple data stores
  8. Universally-unique identifiers: create a uuid property for Rules, RuleContexts, and RuleElements (Propositions, Variables, and Operators)