1.20.0 • Published 5 months ago

@clipboard-health/rules-engine v1.20.0

Weekly downloads
-
License
MIT
Repository
github
Last release
5 months ago

@clipboard-health/rules-engine

A pure functional rules engine to keep logic-dense code simple, reliable, understandable, and explainable.

The engine uses static rules created in code instead of dynamic rules serialized to a database since we haven't needed the latter yet.

Table of contents

Install

npm install @clipboard-health/rules-engine

Usage

import { deepEqual } from "node:assert/strict";

import {
  all,
  allIf,
  appendOutput,
  firstMatch,
  type Rule,
  type RuleContext,
} from "@clipboard-health/rules-engine";

interface Input {
  a: number;
  b: number;
}

interface Output {
  result: number;
}

const exampleContext: RuleContext<Input, Output> = {
  input: {
    a: 2,
    b: 5,
  },
  output: [],
};

const addNumbersIfPositiveRule: Rule<Input, Output> = {
  runIf: (input) => input.a > 0 && input.b > 0,
  run: (context) => {
    const { a, b } = context.input;
    return appendOutput(context, { result: a + b });
  },
};

const multiplyNumbersIfPositiveRule: Rule<Input, Output> = {
  runIf: (input) => input.a > 0 && input.b > 0,
  run: (context) => {
    const { a, b } = context.input;
    return appendOutput(context, { result: a * b });
  },
};

const divideNumbersIfNegative: Rule<Input, Output> = {
  runIf: (input) => input.a < 0 && input.b < 0,
  run: (context) => {
    const { a, b } = context.input;
    return appendOutput(context, { result: a / b });
  },
};

// Using all() applies all the rules to the context
const allResult = all(
  addNumbersIfPositiveRule,
  divideNumbersIfNegative,
  multiplyNumbersIfPositiveRule,
).run(exampleContext);

deepEqual(allResult.output, [{ result: 7 }, { result: 10 }]);

// Using firstMatch() applies the first the rules to the context
const firstMatchResult = firstMatch(
  divideNumbersIfNegative,
  addNumbersIfPositiveRule,
  multiplyNumbersIfPositiveRule,
).run(exampleContext);

deepEqual(firstMatchResult.output, [{ result: 7 }]);

// Using allIf() applies all the rules that return true for `runIf` to the context when the predicate
// (a function received as firs argument) returns true
const allIfResult = allIf(
  (input) => input.a === 2,
  divideNumbersIfNegative,
  addNumbersIfPositiveRule,
  multiplyNumbersIfPositiveRule,
).run(exampleContext);

deepEqual(allIfResult.output, [{ result: 7 }, { result: 10 }]);

Local development commands

See package.json scripts for a list of commands.

1.14.1

12 months ago

1.14.0

12 months ago

1.18.1

7 months ago

1.16.3

11 months ago

1.18.0

7 months ago

1.16.2

12 months ago

1.16.1

12 months ago

1.16.0

12 months ago

1.16.7

10 months ago

1.16.6

10 months ago

1.18.3

6 months ago

1.16.5

10 months ago

1.18.2

7 months ago

1.16.4

10 months ago

1.16.8

9 months ago

1.15.0

12 months ago

1.13.1

1 year ago

1.13.0

1 year ago

1.19.0

5 months ago

1.17.2

8 months ago

1.17.1

8 months ago

1.17.0

9 months ago

1.17.6

7 months ago

1.17.5

8 months ago

1.17.4

8 months ago

1.17.3

8 months ago

1.17.8

7 months ago

1.17.7

7 months ago

1.20.0

5 months ago

1.12.7

1 year ago

1.12.6

1 year ago

1.12.8

1 year ago

1.12.3

1 year ago

1.12.2

1 year ago

1.12.1

1 year ago

1.12.0

1 year ago

1.12.5

1 year ago

1.12.4

1 year ago

1.9.0

1 year ago

1.8.1

1 year ago

1.8.0

1 year ago

1.7.0

1 year ago

1.11.0

1 year ago

1.10.0

1 year ago

1.6.0

1 year ago

1.5.1

1 year ago

1.5.0

1 year ago

1.4.1

1 year ago

1.4.0

1 year ago

1.3.0

1 year ago

1.2.7

1 year ago

1.2.6

1 year ago

1.2.5

1 year ago

1.2.4

1 year ago

1.2.3

1 year ago

1.2.2

1 year ago

1.2.1

1 year ago

0.0.0

1 year ago

1.2.9

1 year ago

1.2.0

1 year ago

1.1.6

1 year ago

1.1.5

1 year ago

1.1.2

1 year ago

1.1.1

1 year ago

1.0.3

1 year ago

1.0.2

1 year ago

1.0.1

1 year ago

0.1.6

1 year ago

0.1.5

1 year ago

0.1.4

1 year ago

0.1.3

1 year ago

0.1.2

2 years ago

0.1.1

2 years ago

0.1.0

2 years ago