@clipboard-health/rules-engine
Advanced tools
Comparing version 0.1.0 to 0.1.1
@@ -5,2 +5,4 @@ # Changelog | ||
## [0.1.1](https://github.com/ClipboardHealth/cbh-core/compare/rules-engine-0.1.0...rules-engine-0.1.1) (2023-12-22) | ||
## 0.1.0 (2023-12-20) | ||
@@ -7,0 +9,0 @@ |
{ | ||
"name": "@clipboard-health/rules-engine", | ||
"version": "0.1.0", | ||
"version": "0.1.1", | ||
"main": "./src/index.js", | ||
@@ -11,3 +11,6 @@ "scripts": { | ||
}, | ||
"dependencies": { | ||
"type-fest": "4.8.3" | ||
}, | ||
"type": "commonjs" | ||
} |
@@ -5,4 +5,4 @@ # @clipboard-health/rules-engine | ||
- firstMatch: Runs the first rule that matches the criteria | ||
- all: Runs all the rules that matches the criteria | ||
- `firstMatch`: Runs the first rule that matches the criteria | ||
- `all`: Runs all the rules that matches the criteria | ||
@@ -26,3 +26,9 @@ ## Table of Contents | ||
import { all, firstMatch, type Rule, type RuleContext } from "@clipboard-health/rules-engine"; | ||
import { | ||
all, | ||
appendOutput, | ||
firstMatch, | ||
type Rule, | ||
type RuleContext, | ||
} from "@clipboard-health/rules-engine"; | ||
@@ -38,5 +44,3 @@ interface Input { | ||
interface ExampleRuleContext extends RuleContext<Input, Output> {} | ||
const exampleContext: ExampleRuleContext = { | ||
const exampleContext: RuleContext<Input, Output> = { | ||
input: { | ||
@@ -49,29 +53,26 @@ number1: 2, | ||
const addNumbersIfPositiveRule: Rule<ExampleRuleContext> = { | ||
runIf: (context) => context.input.number1 > 0 && context.input.number2 > 0, | ||
const addNumbersIfPositiveRule: Rule<Input, Output> = { | ||
runIf: (input) => input.number1 > 0 && input.number2 > 0, | ||
run: (context) => { | ||
const { number1, number2 } = context.input; | ||
const sum = number1 + number2; | ||
context.output.push({ result: sum }); | ||
return context; | ||
return appendOutput(context, { result: sum }); | ||
}, | ||
}; | ||
const multiplyNumbersIfPositiveRule: Rule<ExampleRuleContext> = { | ||
runIf: (context) => context.input.number1 > 0 && context.input.number2 > 0, | ||
const multiplyNumbersIfPositiveRule: Rule<Input, Output> = { | ||
runIf: (input) => input.number1 > 0 && input.number2 > 0, | ||
run: (context) => { | ||
const { number1, number2 } = context.input; | ||
const sum = number1 * number2; | ||
context.output.push({ result: sum }); | ||
return context; | ||
return appendOutput(context, { result: sum }); | ||
}, | ||
}; | ||
const divideNumbersIfNegative: Rule<ExampleRuleContext> = { | ||
runIf: (context) => context.input.number1 < 0 && context.input.number2 < 0, | ||
const divideNumbersIfNegative: Rule<Input, Output> = { | ||
runIf: (input) => input.number1 < 0 && input.number2 < 0, | ||
run: (context) => { | ||
const { number1, number2 } = context.input; | ||
const sum = number1 * number2; | ||
context.output.push({ result: sum }); | ||
return context; | ||
return appendOutput(context, { result: sum }); | ||
}, | ||
@@ -87,3 +88,2 @@ }; | ||
// eslint-disable-next-line no-console | ||
console.log(allResult.output); // AllResult.output = [{ result: 7 }, { result: 10 }] | ||
@@ -98,3 +98,2 @@ | ||
// eslint-disable-next-line no-console | ||
console.log(firstMatchResult.output); // [{ result: 7 }] | ||
@@ -101,0 +100,0 @@ ``` |
@@ -0,3 +1,7 @@ | ||
import { type ReadonlyDeep } from "type-fest"; | ||
import { type RuleContext } from "./rule"; | ||
export declare function appendOutput<TInput, TOutput>(context: RuleContext<TInput, TOutput>, output: TOutput): RuleContext<TInput, TOutput>; | ||
/** | ||
* Rule output is immutable, do not modify existing items, only append. | ||
*/ | ||
export declare function appendOutput<TInput, TOutput>(context: RuleContext<TInput, TOutput>, output: ReadonlyDeep<TOutput>): RuleContext<TInput, TOutput>; | ||
//# sourceMappingURL=append-output.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.appendOutput = void 0; | ||
/** | ||
* Rule output is immutable, do not modify existing items, only append. | ||
*/ | ||
function appendOutput(context, output) { | ||
@@ -5,0 +8,0 @@ return { |
@@ -1,9 +0,29 @@ | ||
export interface RuleContext<TInput = unknown, TOutput = unknown> { | ||
input: TInput; | ||
output: TOutput[]; | ||
import { type ReadonlyDeep } from "type-fest"; | ||
export interface RuleContext<TInput, TOutput> { | ||
/** | ||
* Input is immutable, rules must not modify it. | ||
*/ | ||
input: ReadonlyDeep<TInput>; | ||
/** | ||
* Output is immutable, do not modify existing items, only append. | ||
* | ||
* @see {@link appendOutput} | ||
*/ | ||
output: ReadonlyArray<ReadonlyDeep<TOutput>>; | ||
} | ||
export interface Rule<TContext extends RuleContext> { | ||
runIf: (context: TContext) => boolean; | ||
export interface Rule<TInput, TOutput, TContext extends RuleContext<TInput, TOutput> = RuleContext<TInput, TOutput>> { | ||
/** | ||
* Returns whether the rule should run or not. | ||
* | ||
* Only the `input` and not the full `context` is passed to `runIf`. This prevents rules from | ||
* relying on `output`, which may be modified by previous rules by the time `run` is called. | ||
*/ | ||
runIf: (input: ReadonlyDeep<TInput>) => boolean; | ||
/** | ||
* Runs the actual rule and returns a new context by appending to the output array. | ||
* | ||
* @see {@link appendOutput} | ||
*/ | ||
run: (context: TContext) => TContext; | ||
} | ||
//# sourceMappingURL=rule.d.ts.map |
@@ -1,9 +0,8 @@ | ||
import { type Rule, type RuleContext } from "../.."; | ||
import { type Rule, type RuleContext } from "../rule"; | ||
/** | ||
* Runs all the rules that return true for `runIf`. | ||
* Runs all rules that return true for `runIf`. | ||
* | ||
* @param rules The rules to run. | ||
* @returns Rule<TContext> | ||
*/ | ||
export declare function all<TContext extends RuleContext>(...rules: Array<Rule<TContext>>): Rule<TContext>; | ||
export declare function all<TInput, TOutput, TContext extends RuleContext<TInput, TOutput>>(...rules: Array<Rule<TInput, TOutput, TContext>>): Rule<TInput, TOutput, TContext>; | ||
//# sourceMappingURL=all.d.ts.map |
@@ -5,20 +5,12 @@ "use strict"; | ||
/** | ||
* Runs all the rules that return true for `runIf`. | ||
* Runs all rules that return true for `runIf`. | ||
* | ||
* @param rules The rules to run. | ||
* @returns Rule<TContext> | ||
*/ | ||
function all(...rules) { | ||
return { | ||
runIf: function (context) { | ||
return rules.some((rule) => rule.runIf(context)); | ||
}, | ||
run: function (context) { | ||
return rules.reduce((previousContext, rule) => { | ||
if (rule.runIf(context)) { | ||
return rule.run(previousContext); | ||
} | ||
return previousContext; | ||
}, context); | ||
}, | ||
runIf: (input) => rules.some((rule) => rule.runIf(input)), | ||
run: (context) => rules | ||
.filter((rule) => rule.runIf(context.input)) | ||
.reduce((previousContext, rule) => rule.run(previousContext), context), | ||
}; | ||
@@ -25,0 +17,0 @@ } |
@@ -1,4 +0,4 @@ | ||
import { type Rule, type RuleContext } from "../.."; | ||
import { type Rule, type RuleContext } from "../rule"; | ||
/** | ||
* Runs the first rule that returns true for `runIf`. | ||
* Run the first rule that returns true for `runIf`. | ||
* | ||
@@ -8,3 +8,3 @@ * @param rules The rules to run. | ||
*/ | ||
export declare function firstMatch<TContext extends RuleContext>(...rules: Array<Rule<TContext>>): Rule<TContext>; | ||
export declare function firstMatch<TInput, TOutput, TContext extends RuleContext<TInput, TOutput>>(...rules: Array<Rule<TInput, TOutput, TContext>>): Rule<TInput, TOutput, TContext>; | ||
//# sourceMappingURL=first-match.d.ts.map |
@@ -5,3 +5,3 @@ "use strict"; | ||
/** | ||
* Runs the first rule that returns true for `runIf`. | ||
* Run the first rule that returns true for `runIf`. | ||
* | ||
@@ -13,7 +13,5 @@ * @param rules The rules to run. | ||
return { | ||
runIf: function (context) { | ||
return rules.some((rule) => rule.runIf(context)); | ||
}, | ||
run: function (context) { | ||
const rule = rules.find((rule) => rule.runIf(context)); | ||
runIf: (input) => rules.some((rule) => rule.runIf(input)), | ||
run: (context) => { | ||
const rule = rules.find((rule) => rule.runIf(context.input)); | ||
return rule ? rule.run(context) : context; | ||
@@ -20,0 +18,0 @@ }, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
11540
111
1
99
+ Addedtype-fest@4.8.3
+ Addedtype-fest@4.8.3(transitive)