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

regula-js

v1.0.0

Published

A rule parsing engine written in JS

Downloads

11

Readme

Regula.JS - A Simple Rule Parsing Engine written in JS

Regula.JS is a simple rule parsing engine that can be used to delegate one decision. The primary purpose of this library is to create a rule that can be stored remotely and be accessed wherever needed to make decisions based on user input.

Regula.JS is not a programming language thus it does not include any getters, setters or loops. One rule always corresponds to one decision.

Installation

npm install regula-js

or

yarn add regula-js

Usage

  1. Import applyRules from regula-js.
import { applyRules } from "regula-js"
  1. Regula.JS takes in an array of rule objects as the first parameter and the user input object as the second parameter.
const result = applyRules(rules, userInput);

Alternatively, if you only have one rule object, you can wrap it up in an array and pass it to the function.

const result = applyRules([rule], userInput);
  1. ???

  2. Profit

Rule Object

A rule object typically looks like this

const singleVarRule = {
    variables: [
        {
            identifier: "age",
            operation: ">",
            operand: 18,
            expression: "$1"
        }
    ],
    condition: "$1",
};

This is what a single variable rule looks like. You can see a rule object consists of two major keys; variables, and condition.

Here's a corresponding data or user input object for this rule

const data = {
        age: 25,
    }

variables

Going back to the rule object, variables is an array of objects that contains sub conditions that make up the full condition. In this case, the sub-condition and the full condition are the same.

Let us discuss the objects in variables in more detail.

  • identifier key is how Regula.JS knows what input to take from the data or user input object.
  • operation corresponds to the operation (default or registered) to be used to evaluate the sub-condition.
  • operand corresponds to what value will the user input be compared against.
  • expression is an identifier used by Regula.JS to know sub-condition has been evaluated. Typically this can be anything unique such as uuid or an index.

conditions

Let us now discussion the condition key.

  • All sub-conditions once evaluated are substituted in the condition value.
  • All logical operations are defined in the condition value.
  • The expression key is utilized to identify which part of the condition value has to be substituted.

For a more indepth idea, look at this multi variable rule below.

const multiVarRule = {
    variables: [
        {
            identifier: "age",
            operation: ">",
            operand: 18,
            expression: "$1"
        },
        {
            identifier: "position",
            operation: "<",
            operand: 4,
            expression: "$2"
        },
        {
            identifier: "position",
            operation: ">",
            operand: 0,
            expression: "$3"
        }
    ],
    condition: "$1 && ($2 && $3)",
};

Additional Keys

The rule object accepts two optional keys; result, and extra.

result

You can pass anything you want into the result key. If the rule is evaluated as true and the result key exists, Regula.JS will return the result key instead of true.

extra

This key can be used to store any extra data such as some kind of metadata you want stored with the rule object. Regula.JS does not acknowledge the extra key and ignores whatever content is present in this key.

Supported Operations

Boolean Operations

  • ===
  • !==
  • >
  • <
  • >=
  • <=

Logic Operations

  • !
  • !!
  • &&
  • ||

Regula.JS is written in JS therefore the default functions provided with Regula.JS follow the precedence and logic provided by JS. However, that's not the main hook of Regula.JS. Regula.JS provides two other functions called

registerOperations()

and

overrideOperation()

registerOperations()

registerOperations function requires an object that contains the identifier for your function as well as the function to be called.

For example

import { registerOperations } from "regula-js"

registerOperations({
    "includes": (LHS, RHS) => {
        return LHS.includes(RHS);
    }
});

Here, we are registering a new operation called includes at runtime that can now be utilized by Regula.JS while parsing rules. The LHS corresponds to the value taken from user input while RHS corresponds to the value taken from the rule itself. You can register multiple operations at once by adding them to the object being passed to registerOperations function.

overrideOperation()

overrideOperation function requires the identifier for the operation to be replaced as well as the new operation replacement.

For example

import { overrideOperation } from "regula-js"

overrideOperation("===", (LHS, RHS) => {
    return LHS == RHS;
})

Here, we are overriding the strict equality operation with loose equality operation at runtime. Do take note that if the identifier provided to be overriden does not exist, a new operation will be registered instead of overriding any operation.

Current Shortcomings

  • The engine currently uses eval at the end to evaluate the whole condition. There are plans to replace eval with a custom function that evaluates the condition in the future but eval stays for now.
  • A side-effect of using eval is, the condition being parsed follows the operation precedence provided by JS. There are plans to allow users to override the current evaluation algorithm with their own in some future version.
  • Regula.JS currently only supports one condition in one rule object.

To further elaborate my point,

if (age > 16 && position < 4) {
    ///do something
}

It does not currently support else and else if conditions. For example,

if (age > 16 && position < 4) {
    ///do something
} else if (age < 16 && position > 4) {
    ///do something else
} else {
    ///execute the else clause
}

The above snippet is currently not supported by Regula.JS. There are plans to include this functionality in the next version.

How can you help?

  • I have added some rudimentary unit tests via QUnit in the library but they are not at all sufficient to cover everything Regula.JS has to offer. You can help by adding more in-depth test cases that also covers the edge cases as well.
  • You can also help by requesting features, reporting bugs or helping to develop Regula.JS further.
  • If you feel like I missed discussing something in the readme, do be sure to tell me about that as well.