@shepherdnerds/json-rules-engine 7.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,96 @@
1
+ {
2
+ "name": "@shepherdnerds/json-rules-engine",
3
+ "version": "7.3.1",
4
+ "description": "Rules Engine expressed in simple json",
5
+ "main": "dist/index.js",
6
+ "types": "types/index.d.ts",
7
+ "engines": {
8
+ "node": ">=18.0.0"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/withshepherd/nested-json-rules-engine"
13
+ },
14
+ "keywords": [
15
+ "rules",
16
+ "engine",
17
+ "rules engine"
18
+ ],
19
+ "standard": {
20
+ "parser": "babel-eslint",
21
+ "ignore": [
22
+ "/dist",
23
+ "/examples/node_modules"
24
+ ],
25
+ "globals": [
26
+ "context",
27
+ "xcontext",
28
+ "describe",
29
+ "xdescribe",
30
+ "it",
31
+ "xit",
32
+ "before",
33
+ "beforeEach",
34
+ "expect",
35
+ "factories"
36
+ ]
37
+ },
38
+ "mocha": {
39
+ "require": [
40
+ "babel-core/register",
41
+ "babel-polyfill"
42
+ ],
43
+ "file": "./test/support/bootstrap.js",
44
+ "checkLeaks": true,
45
+ "recursive": true,
46
+ "globals": [
47
+ "expect"
48
+ ]
49
+ },
50
+ "author": "Cache Hamm <cache.hamm@gmail.com>",
51
+ "contributors": [
52
+ "Chris Pardy <chris.pardy@gmail.com>"
53
+ ],
54
+ "license": "ISC",
55
+ "bugs": {
56
+ "url": "https://github.com/withshepherd/nested-json-rules-engine/issues"
57
+ },
58
+ "homepage": "https://github.com/withshepherd/nested-json-rules-engine",
59
+ "devDependencies": {
60
+ "babel-cli": "6.26.0",
61
+ "babel-core": "6.26.3",
62
+ "babel-eslint": "10.1.0",
63
+ "babel-loader": "8.2.2",
64
+ "babel-polyfill": "6.26.0",
65
+ "babel-preset-es2015": "~6.24.1",
66
+ "babel-preset-stage-0": "~6.24.1",
67
+ "babel-register": "6.26.0",
68
+ "chai": "^4.3.4",
69
+ "chai-as-promised": "^7.1.1",
70
+ "colors": "~1.4.0",
71
+ "dirty-chai": "2.0.1",
72
+ "lodash": "4.17.21",
73
+ "mocha": "^8.4.0",
74
+ "perfy": "^1.1.5",
75
+ "sinon": "^11.1.1",
76
+ "sinon-chai": "^3.7.0",
77
+ "snazzy": "^9.0.0",
78
+ "standard": "^16.0.3",
79
+ "tsd": "^0.17.0"
80
+ },
81
+ "dependencies": {
82
+ "clone": "^2.1.2",
83
+ "eventemitter2": "^6.4.4",
84
+ "hash-it": "^6.0.0",
85
+ "jsonpath-plus": "^10.3.0"
86
+ },
87
+ "scripts": {
88
+ "test": "mocha && npm run lint --silent && npm run test:types",
89
+ "test:types": "tsd",
90
+ "lint": "standard --verbose --env mocha | snazzy || true",
91
+ "lint:fix": "standard --fix --env mocha",
92
+ "build": "babel --stage 1 -d dist/ src/",
93
+ "watch": "babel --watch --stage 1 -d dist/ src",
94
+ "examples": "./test/support/example_runner.sh"
95
+ }
96
+ }
@@ -0,0 +1,312 @@
1
+ export interface AlmanacOptions {
2
+ allowUndefinedFacts?: boolean;
3
+ pathResolver?: PathResolver;
4
+ }
5
+
6
+ export interface EngineOptions extends AlmanacOptions {
7
+ allowUndefinedConditions?: boolean;
8
+ replaceFactsInEventParams?: boolean;
9
+ }
10
+
11
+ export interface RunOptions {
12
+ almanac?: Almanac;
13
+ }
14
+
15
+ export interface EngineResult {
16
+ events: Event[];
17
+ failureEvents: Event[];
18
+ almanac: Almanac;
19
+ results: RuleResult[];
20
+ failureResults: RuleResult[];
21
+ }
22
+
23
+ export default function engineFactory(
24
+ rules: Array<RuleProperties>,
25
+ options?: EngineOptions
26
+ ): Engine;
27
+
28
+ export class Engine {
29
+ constructor(rules?: Array<RuleProperties>, options?: EngineOptions);
30
+
31
+ addRule(rule: RuleProperties): this;
32
+ removeRule(ruleOrName: Rule | string): boolean;
33
+ updateRule(rule: Rule): void;
34
+
35
+ setCondition(name: string, conditions: TopLevelCondition): this;
36
+ removeCondition(name: string): boolean;
37
+
38
+ addOperator(operator: Operator): void;
39
+ addOperator<A, B>(
40
+ operatorName: string,
41
+ callback: OperatorEvaluator<A, B>
42
+ ): void;
43
+ removeOperator(operator: Operator | string): boolean;
44
+
45
+ addOperatorDecorator(decorator: OperatorDecorator): void;
46
+ addOperatorDecorator<A, B, NextA, NextB>(decoratorName: string, callback: OperatorDecoratorEvaluator<A, B, NextA, NextB>): void;
47
+ removeOperatorDecorator(decorator: OperatorDecorator | string): boolean;
48
+
49
+ addFact<T>(fact: Fact<T>): this;
50
+ addFact<T>(
51
+ id: string,
52
+ valueCallback: DynamicFactCallback<T> | T,
53
+ options?: FactOptions
54
+ ): this;
55
+ removeFact(factOrId: string | Fact): boolean;
56
+ getFact<T>(factId: string): Fact<T>;
57
+
58
+ on<T = Event>(eventName: string, handler: EventHandler<T>): this;
59
+
60
+ run(facts?: Record<string, any>, runOptions?: RunOptions): Promise<EngineResult>;
61
+ stop(): this;
62
+ }
63
+
64
+ export interface OperatorEvaluator<A, B> {
65
+ (factValue: A, compareToValue: B): boolean;
66
+ }
67
+
68
+ export class Operator<A = unknown, B = unknown> {
69
+ public name: string;
70
+ constructor(
71
+ name: string,
72
+ evaluator: OperatorEvaluator<A, B>,
73
+ validator?: (factValue: A) => boolean
74
+ );
75
+ }
76
+
77
+ export interface OperatorDecoratorEvaluator<A, B, NextA, NextB> {
78
+ (factValue: A, compareToValue: B, next: OperatorEvaluator<NextA, NextB>): boolean
79
+ }
80
+
81
+ export class OperatorDecorator<A = unknown, B = unknown, NextA = unknown, NextB = unknown> {
82
+ public name: string;
83
+ constructor(
84
+ name: string,
85
+ evaluator: OperatorDecoratorEvaluator<A, B, NextA, NextB>,
86
+ validator?: (factValue: A) => boolean
87
+ )
88
+ }
89
+
90
+ export class Almanac {
91
+ constructor(options?: AlmanacOptions);
92
+ factValue<T>(
93
+ factId: string,
94
+ params?: Record<string, any>,
95
+ path?: string
96
+ ): Promise<T>;
97
+ /**
98
+ * Resolves a path - only valid in scoped context (ScopedAlmanac)
99
+ * Throws error when called on regular Almanac to catch misuse of scoped conditions
100
+ */
101
+ resolvePath<T>(path: string): Promise<T>;
102
+ addFact<T>(fact: Fact<T>): this;
103
+ addFact<T>(
104
+ id: string,
105
+ valueCallback: DynamicFactCallback<T> | T,
106
+ options?: FactOptions
107
+ ): this;
108
+ addRuntimeFact(factId: string, value: any): void;
109
+ }
110
+
111
+ /**
112
+ * Scoped Almanac for nested condition evaluation
113
+ * Wraps a parent almanac but prioritizes item properties for fact resolution
114
+ */
115
+ export class ScopedAlmanac {
116
+ constructor(parentAlmanac: Almanac, item: any);
117
+ /**
118
+ * Resolves a path directly on the current scoped item
119
+ * Used by scoped conditions that have path but no fact
120
+ */
121
+ resolvePath<T>(path: string): Promise<T>;
122
+ factValue<T>(
123
+ factId: string,
124
+ params?: Record<string, any>,
125
+ path?: string
126
+ ): Promise<T>;
127
+ getValue<T>(value: any): Promise<T>;
128
+ }
129
+
130
+ export type FactOptions = {
131
+ cache?: boolean;
132
+ priority?: number;
133
+ };
134
+
135
+ export type DynamicFactCallback<T = unknown> = (
136
+ params: Record<string, any>,
137
+ almanac: Almanac
138
+ ) => T;
139
+
140
+ export class Fact<T = unknown> {
141
+ id: string;
142
+ priority: number;
143
+ options: FactOptions;
144
+ value?: T;
145
+ calculationMethod?: DynamicFactCallback<T>;
146
+
147
+ constructor(
148
+ id: string,
149
+ value: T | DynamicFactCallback<T>,
150
+ options?: FactOptions
151
+ );
152
+ }
153
+
154
+ export interface Event {
155
+ type: string;
156
+ params?: Record<string, any>;
157
+ }
158
+
159
+ export type PathResolver = (value: object, path: string) => any;
160
+
161
+ export type EventHandler<T = Event> = (
162
+ event: T,
163
+ almanac: Almanac,
164
+ ruleResult: RuleResult
165
+ ) => void;
166
+
167
+ export interface RuleProperties {
168
+ conditions: TopLevelCondition;
169
+ event: Event;
170
+ name?: string;
171
+ priority?: number;
172
+ onSuccess?: EventHandler;
173
+ onFailure?: EventHandler;
174
+ }
175
+ export type RuleSerializable = Pick<
176
+ Required<RuleProperties>,
177
+ "conditions" | "event" | "name" | "priority"
178
+ >;
179
+
180
+ export type RuleResultSerializable = Pick<
181
+ Required<RuleResult>,
182
+ "name" | "event" | "priority" | "result"> & {
183
+ conditions: TopLevelConditionResultSerializable
184
+ }
185
+
186
+ export interface RuleResult {
187
+ name: string;
188
+ conditions: TopLevelConditionResult;
189
+ event?: Event;
190
+ priority?: number;
191
+ result: any;
192
+ toJSON(): string;
193
+ toJSON<T extends boolean>(
194
+ stringify: T
195
+ ): T extends true ? string : RuleResultSerializable;
196
+ }
197
+
198
+ export class Rule implements RuleProperties {
199
+ constructor(ruleProps: RuleProperties | string);
200
+ name: string;
201
+ conditions: TopLevelCondition;
202
+ /**
203
+ * @deprecated Use {@link Rule.event} instead.
204
+ */
205
+ ruleEvent: Event;
206
+ event: Event
207
+ priority: number;
208
+ setConditions(conditions: TopLevelCondition): this;
209
+ setEvent(event: Event): this;
210
+ setPriority(priority: number): this;
211
+ toJSON(): string;
212
+ toJSON<T extends boolean>(
213
+ stringify: T
214
+ ): T extends true ? string : RuleSerializable;
215
+ }
216
+
217
+ interface BooleanConditionResultProperties {
218
+ result?: boolean
219
+ }
220
+
221
+ interface ConditionResultProperties extends BooleanConditionResultProperties {
222
+ factResult?: unknown
223
+ valueResult?: unknown
224
+ }
225
+
226
+ interface ConditionProperties {
227
+ fact: string;
228
+ operator: string;
229
+ value: { fact: string } | any;
230
+ path?: string;
231
+ priority?: number;
232
+ params?: Record<string, any>;
233
+ name?: string;
234
+ }
235
+
236
+ /**
237
+ * Scoped condition that evaluates a path directly on the current array item
238
+ * Used inside nested conditions where the "fact" is implicitly the current array item
239
+ * The path is resolved using JSONPath against the scoped item
240
+ */
241
+ interface ScopedConditionProperties {
242
+ path: string;
243
+ operator: string;
244
+ value: { path: string } | any;
245
+ priority?: number;
246
+ params?: Record<string, any>;
247
+ name?: string;
248
+ }
249
+
250
+ interface ScopedConditionPropertiesResult extends ScopedConditionProperties, ConditionResultProperties {}
251
+
252
+ /**
253
+ * Nested condition that evaluates conditions against array items
254
+ * Uses the 'some' operator to check if at least one array item matches
255
+ */
256
+ interface NestedConditionProperties {
257
+ fact: string;
258
+ operator: 'some';
259
+ conditions: TopLevelCondition;
260
+ path?: string;
261
+ priority?: number;
262
+ params?: Record<string, any>;
263
+ name?: string;
264
+ }
265
+
266
+ interface NestedConditionPropertiesResult extends NestedConditionProperties, ConditionResultProperties {
267
+ conditions: TopLevelConditionResult;
268
+ }
269
+
270
+ type ConditionPropertiesResult = ConditionProperties & ConditionResultProperties
271
+
272
+ type NestedCondition = ConditionProperties | NestedConditionProperties | ScopedConditionProperties | TopLevelCondition;
273
+ type NestedConditionResult = ConditionPropertiesResult | NestedConditionPropertiesResult | ScopedConditionPropertiesResult | TopLevelConditionResult;
274
+ type AllConditions = {
275
+ all: NestedCondition[];
276
+ name?: string;
277
+ priority?: number;
278
+ };
279
+ type AllConditionsResult = AllConditions & {
280
+ all: NestedConditionResult[]
281
+ } & BooleanConditionResultProperties
282
+ type AnyConditions = {
283
+ any: NestedCondition[];
284
+ name?: string;
285
+ priority?: number;
286
+ };
287
+ type AnyConditionsResult = AnyConditions & {
288
+ any: NestedConditionResult[]
289
+ } & BooleanConditionResultProperties
290
+ type NotConditions = { not: NestedCondition; name?: string; priority?: number };
291
+ type NotConditionsResult = NotConditions & {not: NestedConditionResult} & BooleanConditionResultProperties;
292
+ type ConditionReference = {
293
+ condition: string;
294
+ name?: string;
295
+ priority?: number;
296
+ };
297
+ type ConditionReferenceResult = ConditionReference & BooleanConditionResultProperties
298
+ export type TopLevelCondition =
299
+ | AllConditions
300
+ | AnyConditions
301
+ | NotConditions
302
+ | ConditionReference;
303
+ export type TopLevelConditionResult =
304
+ | AllConditionsResult
305
+ | AnyConditionsResult
306
+ | NotConditionsResult
307
+ | ConditionReferenceResult
308
+ export type TopLevelConditionResultSerializable =
309
+ | AllConditionsResult
310
+ | AnyConditionsResult
311
+ | NotConditionsResult
312
+ | ConditionReference