@infitx/decision 0.0.1 → 1.3.2
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/CHANGELOG.md +38 -0
- package/README.md +432 -0
- package/index.js +35 -0
- package/package.json +21 -8
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [1.3.2](https://github.com/infitx-org/release-cd/compare/decision-v1.3.1...decision-v1.3.2) (2026-02-09)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* update package versions and permissions in workflows ([c582d9f](https://github.com/infitx-org/release-cd/commit/c582d9faff24e6a0549e529608f0ef6a8b362bcf))
|
|
9
|
+
|
|
10
|
+
## [1.3.1](https://github.com/infitx-org/release-cd/compare/decision-v1.3.0...decision-v1.3.1) (2026-02-09)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* deploy ([9aa2bd6](https://github.com/infitx-org/release-cd/commit/9aa2bd69093d4374f86dd8554a527b627032c326))
|
|
16
|
+
|
|
17
|
+
## [1.3.0](https://github.com/infitx-org/release-cd/compare/decision-v1.2.0...decision-v1.3.0) (2026-02-09)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* add .npmignore files and ci-publish script for decision and match libraries ([c518708](https://github.com/infitx-org/release-cd/commit/c5187080c63a215a670fcbe37a11989d6ec4c37f))
|
|
23
|
+
|
|
24
|
+
## [1.2.0](https://github.com/infitx-org/release-cd/compare/decision-v1.1.0...decision-v1.2.0) (2026-01-06)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### Features
|
|
28
|
+
|
|
29
|
+
* implement multiple decisions ([74cb3b6](https://github.com/infitx-org/release-cd/commit/74cb3b6bcc5cc15fb59fd28843cf920897b27c9c))
|
|
30
|
+
|
|
31
|
+
## [1.1.0](https://github.com/infitx-org/release-cd/compare/decision-v1.0.0...decision-v1.1.0) (2025-12-23)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
### Features
|
|
35
|
+
|
|
36
|
+
* add build script to package.json for decision and match libraries ([f4da999](https://github.com/infitx-org/release-cd/commit/f4da9993feec346cc94f573fa103dffa8c4a9eed))
|
|
37
|
+
* match and decision libraries ([db62341](https://github.com/infitx-org/release-cd/commit/db623419a179b3e0ec0cbda05b2f135e01375552))
|
|
38
|
+
* update decision module to use YAML for configuration and improve rule handling ([92fa802](https://github.com/infitx-org/release-cd/commit/92fa80243508ff486c3e39f1b32d90701c2eb5d6))
|
package/README.md
ADDED
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
# Decision Library
|
|
2
|
+
|
|
3
|
+
A lightweight rule engine for evaluating facts against configurable rules and
|
|
4
|
+
generating decisions. The library uses pattern matching to determine which rules
|
|
5
|
+
apply to a given fact and returns corresponding decisions.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Pattern Matching**: Uses `@infitx/match` for flexible fact matching
|
|
10
|
+
- **Priority-based Evaluation**: Rules can have explicit or implicit priorities
|
|
11
|
+
- **Multiple Decision Support**: Can return first match or all matching rules
|
|
12
|
+
- **YAML Configuration**: Define rules in human-readable YAML format
|
|
13
|
+
- **Type Safety**: Built-in support for various data types including dates and timestamps
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```javascript
|
|
18
|
+
const decision = require('./');
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Basic Usage
|
|
22
|
+
|
|
23
|
+
```javascript
|
|
24
|
+
const decision = require('./');
|
|
25
|
+
const { decide, rules } = decision('./config.yaml');
|
|
26
|
+
|
|
27
|
+
const fact = { type: 'transfer', amount: 500 };
|
|
28
|
+
const result = decide(fact);
|
|
29
|
+
console.log(result);
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Examples
|
|
33
|
+
|
|
34
|
+
### Example 1: Single Decision with Implicit Priority
|
|
35
|
+
|
|
36
|
+
Rules are evaluated in the order they appear in the configuration. When rules
|
|
37
|
+
are defined as an object, the key becomes the rule name and serves as the
|
|
38
|
+
implicit priority (alphabetically sorted).
|
|
39
|
+
|
|
40
|
+
- - YAML Configuration
|
|
41
|
+
|
|
42
|
+
```yaml
|
|
43
|
+
rules:
|
|
44
|
+
transfer-approval:
|
|
45
|
+
when: { type: transfer, amount: { max: 1000 } }
|
|
46
|
+
then: { expect: { approved: true, reason: approved } }
|
|
47
|
+
|
|
48
|
+
transfer-rejection:
|
|
49
|
+
when: { type: transfer, amount: { min: 1001 } }
|
|
50
|
+
then: { expect: { approved: false, reason: limit } }
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
- Decision Table
|
|
54
|
+
|
|
55
|
+
| Rule | Condition | Decision |
|
|
56
|
+
|--------------------- |------------------------------------- |----------------------------------------------- |
|
|
57
|
+
|transfer-approval | type=transfer AND amount ≤ 1000 | expect: approved=true, reason=approved |
|
|
58
|
+
|transfer-rejection | type=transfer AND amount ≥ 1001 | expect: approved=false, reason=limit |
|
|
59
|
+
|
|
60
|
+
- Code Example
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
const decision = require('./');
|
|
64
|
+
const { decide } = decision('./transfer-config.yaml');
|
|
65
|
+
|
|
66
|
+
// Test case 1: Approved transfer
|
|
67
|
+
const fact1 = { type: 'transfer', amount: 500 };
|
|
68
|
+
console.log(decide(fact1));
|
|
69
|
+
// Output: [{
|
|
70
|
+
// rule: 'transfer-approval',
|
|
71
|
+
// decision: 'expect',
|
|
72
|
+
// approved: true,
|
|
73
|
+
// reason: 'approved'
|
|
74
|
+
// }]
|
|
75
|
+
|
|
76
|
+
// Test case 2: Rejected transfer
|
|
77
|
+
const fact2 = { type: 'transfer', amount: 1500 };
|
|
78
|
+
console.log(decide(fact2));
|
|
79
|
+
// Output: [{
|
|
80
|
+
// rule: 'transfer-rejection',
|
|
81
|
+
// decision: 'expect',
|
|
82
|
+
// approved: false,
|
|
83
|
+
// reason: 'limit'
|
|
84
|
+
// }]
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Example 2: Single Decision with Explicit Priority
|
|
88
|
+
|
|
89
|
+
When you need specific evaluation order, pass an array of rules with
|
|
90
|
+
the required order.
|
|
91
|
+
|
|
92
|
+
- YAML Configuration
|
|
93
|
+
|
|
94
|
+
```yaml
|
|
95
|
+
rules:
|
|
96
|
+
- rule: high-value-check
|
|
97
|
+
when: { type: transaction, amount: { min: 10000 } }
|
|
98
|
+
then: { require: { manualReview: true, approvers: 2 } }
|
|
99
|
+
|
|
100
|
+
- rule: standard-check
|
|
101
|
+
when: { type: transaction, amount: { max: 9999 } }
|
|
102
|
+
then: { allow: { automated: true, approvers: 0 } }
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
- Decision Table
|
|
106
|
+
|
|
107
|
+
| Rule | Condition | Decision |
|
|
108
|
+
|-------------------|--------------------------------------|-----------------------------------------------|
|
|
109
|
+
| high-value-check | type=transaction AND amount ≥ 10000 | require: manualReview=true, approvers=2 |
|
|
110
|
+
| standard-check | type=transaction AND amount ≤ 9999 | allow: automated=true, approvers=0 |
|
|
111
|
+
|
|
112
|
+
- Code Example
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
const decision = require('./');
|
|
116
|
+
const { decide, rules } = decision('./priority-config.yaml');
|
|
117
|
+
|
|
118
|
+
console.log('Rules in evaluation order:', rules.map(r => ({ rule: r.rule })));
|
|
119
|
+
// Output: [
|
|
120
|
+
// { rule: 'high-value-check' },
|
|
121
|
+
// { rule: 'standard-check }
|
|
122
|
+
// ]
|
|
123
|
+
|
|
124
|
+
const fact1 = { type: 'transaction', amount: 15000 };
|
|
125
|
+
console.log(decide(fact1));
|
|
126
|
+
// Output: [{
|
|
127
|
+
// rule: 'high-value-check',
|
|
128
|
+
// decision: 'require',
|
|
129
|
+
// manualReview: true,
|
|
130
|
+
// approvers: 2
|
|
131
|
+
// }]
|
|
132
|
+
|
|
133
|
+
const fact2 = { type: 'transaction', amount: 500 };
|
|
134
|
+
console.log(decide(fact2));
|
|
135
|
+
// Output: [{
|
|
136
|
+
// rule: 'standard-check',
|
|
137
|
+
// decision: 'allow',
|
|
138
|
+
// automated: true,
|
|
139
|
+
// approvers: 0
|
|
140
|
+
// }]
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Example 3: Multiple Decisions
|
|
144
|
+
|
|
145
|
+
A single fact can trigger multiple decisions from one rule. This is useful for
|
|
146
|
+
scenarios where you need to take multiple actions based on a single condition.
|
|
147
|
+
|
|
148
|
+
- YAML Configuration
|
|
149
|
+
|
|
150
|
+
```yaml
|
|
151
|
+
rules:
|
|
152
|
+
withdrawal-high-amount:
|
|
153
|
+
when: { type: withdrawal, amount: { min: 501 } }
|
|
154
|
+
then:
|
|
155
|
+
expect: { approved: false, reason: large }
|
|
156
|
+
notification: { type: alert, recipient: manager }
|
|
157
|
+
audit: { level: warning, message: "Large withdrawal attempted" }
|
|
158
|
+
|
|
159
|
+
withdrawal-normal:
|
|
160
|
+
when: { type: withdrawal, amount: { max: 500 } }
|
|
161
|
+
then:
|
|
162
|
+
expect: { approved: true, reason: small }
|
|
163
|
+
audit: { level: info, message: "Withdrawal approved" }
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
- Decision Table
|
|
167
|
+
|
|
168
|
+
| Rule | Condition | Decisions |
|
|
169
|
+
|------------------------|----------------------------------|-------------------------------------------------------------------------------------------------------------------------------------|
|
|
170
|
+
| withdrawal-high-amount | type=withdrawal AND amount ≥ 501 | 1. expect: approved=false, reason=large<br>2. notification: type=alert, recipient=manager<br>3. audit: level=warning, message=... |
|
|
171
|
+
| withdrawal-normal | type=withdrawal AND amount ≤ 500 | 1. expect: approved=true, reason=small<br>2. audit: level=info, message=... |
|
|
172
|
+
|
|
173
|
+
- Code Example
|
|
174
|
+
|
|
175
|
+
```javascript
|
|
176
|
+
const decision = require('./');
|
|
177
|
+
const { decide } = decision('./withdrawal-config.yaml');
|
|
178
|
+
|
|
179
|
+
// Large withdrawal - triggers multiple decisions
|
|
180
|
+
const fact1 = { type: 'withdrawal', amount: 700 };
|
|
181
|
+
console.log(decide(fact1));
|
|
182
|
+
// Output: [
|
|
183
|
+
// {
|
|
184
|
+
// rule: 'withdrawal-high-amount',
|
|
185
|
+
// decision: 'expect',
|
|
186
|
+
// approved: false,
|
|
187
|
+
// reason: 'large'
|
|
188
|
+
// }, {
|
|
189
|
+
// rule: 'withdrawal-high-amount',
|
|
190
|
+
// decision: 'notification',
|
|
191
|
+
// type: 'alert',
|
|
192
|
+
// recipient: 'manager'
|
|
193
|
+
// }, {
|
|
194
|
+
// rule: 'withdrawal-high-amount',
|
|
195
|
+
// decision: 'audit',
|
|
196
|
+
// level: 'warning',
|
|
197
|
+
// message: 'Large withdrawal attempted'
|
|
198
|
+
// }
|
|
199
|
+
// ]
|
|
200
|
+
|
|
201
|
+
// Normal withdrawal
|
|
202
|
+
const fact2 = { type: 'withdrawal', amount: 300 };
|
|
203
|
+
console.log(decide(fact2));
|
|
204
|
+
// Output: [
|
|
205
|
+
// {
|
|
206
|
+
// rule: 'withdrawal-normal',
|
|
207
|
+
// decision: 'expect',
|
|
208
|
+
// approved: true,
|
|
209
|
+
// reason: 'small'
|
|
210
|
+
// }, {
|
|
211
|
+
// rule: 'withdrawal-normal',
|
|
212
|
+
// decision: 'audit',
|
|
213
|
+
// level: 'info',
|
|
214
|
+
// message: 'Withdrawal approved'
|
|
215
|
+
// }
|
|
216
|
+
// ]
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Example 4: All Matching Rules
|
|
220
|
+
|
|
221
|
+
By default, `decide()` returns only the first matching rule. Use the `all`
|
|
222
|
+
parameter to get all matching rules.
|
|
223
|
+
|
|
224
|
+
- YAML Configuration
|
|
225
|
+
|
|
226
|
+
```yaml
|
|
227
|
+
rules:
|
|
228
|
+
fraud-check:
|
|
229
|
+
when: { type: transaction, amount: { min: 5000 } }
|
|
230
|
+
then: { verify: { fraudCheck: true } }
|
|
231
|
+
|
|
232
|
+
compliance-check:
|
|
233
|
+
when: { type: transaction, amount: { min: 3000 } }
|
|
234
|
+
then: { verify: { amlCheck: true } }
|
|
235
|
+
|
|
236
|
+
standard-process:
|
|
237
|
+
when: { type: transaction }
|
|
238
|
+
then: { process: { standard: true } }
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
- Decision Table
|
|
242
|
+
|
|
243
|
+
| Rule | Condition | Decision |
|
|
244
|
+
|-------------------|--------------------------------------|-------------------------------------|
|
|
245
|
+
| fraud-check | type=transaction AND amount ≥ 5000 | verify: fraudCheck=true |
|
|
246
|
+
| compliance-check | type=transaction AND amount ≥ 3000 | verify: amlCheck=true |
|
|
247
|
+
| standard-process | type=transaction | process: standard=true |
|
|
248
|
+
|
|
249
|
+
- Code Example
|
|
250
|
+
|
|
251
|
+
```javascript
|
|
252
|
+
const decision = require('./');
|
|
253
|
+
const { decide } = decision('./all-rules-config.yaml');
|
|
254
|
+
|
|
255
|
+
const fact = { type: 'transaction', amount: 6000 };
|
|
256
|
+
|
|
257
|
+
// Get only first matching rule (default)
|
|
258
|
+
console.log(decide(fact));
|
|
259
|
+
// Output: [{ rule: 'fraud-check', decision: 'verify', fraudCheck: true }]
|
|
260
|
+
|
|
261
|
+
// Get all matching rules
|
|
262
|
+
console.log(decide(fact, true));
|
|
263
|
+
// Output: [
|
|
264
|
+
// { rule: 'fraud-check', decision: 'verify', fraudCheck: true },
|
|
265
|
+
// { rule: 'compliance-check', decision: 'verify', amlCheck: true },
|
|
266
|
+
// { rule: 'standard-process', decision: 'process', standard: true }
|
|
267
|
+
// ]
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## YAML Configuration Format
|
|
271
|
+
|
|
272
|
+
### Basic Structure
|
|
273
|
+
|
|
274
|
+
```yaml
|
|
275
|
+
rules:
|
|
276
|
+
rule-name:
|
|
277
|
+
when: <condition>
|
|
278
|
+
then: <decision>
|
|
279
|
+
priority: <number or string> # Optional, defaults to rule name if omitted
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Or as an array:
|
|
283
|
+
|
|
284
|
+
```yaml
|
|
285
|
+
rules:
|
|
286
|
+
- rule: rule-name
|
|
287
|
+
when: <condition>
|
|
288
|
+
then: <decision>
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Components
|
|
292
|
+
|
|
293
|
+
- `rules`
|
|
294
|
+
|
|
295
|
+
Can be either:
|
|
296
|
+
|
|
297
|
+
- **Object**: Keys are rule names, values are rule definitions. Rules are sorted
|
|
298
|
+
alphabetically by name (implicit priority) or by `priority` field if present.
|
|
299
|
+
- **Array**: Rules definitions with explicit order.
|
|
300
|
+
When an array is used, the processing order is the order of items in the array.
|
|
301
|
+
|
|
302
|
+
- `when` (Condition)
|
|
303
|
+
|
|
304
|
+
A pattern matching object that defines when a rule applies. Supports:
|
|
305
|
+
|
|
306
|
+
- **Exact match**: `{ type: transfer }`
|
|
307
|
+
- **Range match**: `{ amount: { min: 100, max: 1000 } }`
|
|
308
|
+
- **Minimum**: `{ amount: { min: 1000 } }`
|
|
309
|
+
- **Maximum**: `{ amount: { max: 1000 } }`
|
|
310
|
+
- **Complex patterns**: Nested objects, arrays, and any pattern supported by `@infitx/match`
|
|
311
|
+
|
|
312
|
+
- `then` (Decision)
|
|
313
|
+
|
|
314
|
+
Defines the outcomes when a rule matches. Structure:
|
|
315
|
+
|
|
316
|
+
```yaml
|
|
317
|
+
then:
|
|
318
|
+
<decision-type>: <decision-value>
|
|
319
|
+
<another-decision>: <another-value>
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
Each decision becomes an object in the result array:
|
|
323
|
+
|
|
324
|
+
```javascript
|
|
325
|
+
{ rule: 'rule-name', decision: 'decision-type', ...decision-value }
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
- `priority` (Optional)
|
|
329
|
+
|
|
330
|
+
- **Numeric**: Lower numbers evaluated first
|
|
331
|
+
- **String**: Lexicographic ordering
|
|
332
|
+
- **Implicit**: If omitted, rule name is used as priority
|
|
333
|
+
|
|
334
|
+
### Complete Example
|
|
335
|
+
|
|
336
|
+
```yaml
|
|
337
|
+
# Object format with implicit priority
|
|
338
|
+
rules:
|
|
339
|
+
high-priority-rule:
|
|
340
|
+
when: { urgent: true }
|
|
341
|
+
then: { action: { escalate: true } }
|
|
342
|
+
|
|
343
|
+
low-priority-rule:
|
|
344
|
+
when: { urgent: false }
|
|
345
|
+
then: { action: { queue: true } }
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
# Array format with explicit priority
|
|
350
|
+
rules:
|
|
351
|
+
- rule: critical
|
|
352
|
+
when: { severity: critical }
|
|
353
|
+
then:
|
|
354
|
+
alert: { immediate: true }
|
|
355
|
+
notify: { team: on call }
|
|
356
|
+
- rule: warning
|
|
357
|
+
when: { severity: warning }
|
|
358
|
+
then:
|
|
359
|
+
alert: { delayed: true }
|
|
360
|
+
- rule: info
|
|
361
|
+
when: { severity: info }
|
|
362
|
+
then:
|
|
363
|
+
log: { level: info }
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## API Reference
|
|
367
|
+
|
|
368
|
+
### `decision(config)`
|
|
369
|
+
|
|
370
|
+
Creates a decision engine instance.
|
|
371
|
+
|
|
372
|
+
**Parameters:**
|
|
373
|
+
|
|
374
|
+
- `config` (String | Object): Path to YAML file or configuration object
|
|
375
|
+
|
|
376
|
+
**Returns:**
|
|
377
|
+
Object with:
|
|
378
|
+
|
|
379
|
+
- `rules`: Array of rules in evaluation order
|
|
380
|
+
- `decide(fact, all)`: Function to evaluate facts
|
|
381
|
+
- `tests`: Test cases from configuration (if present)
|
|
382
|
+
|
|
383
|
+
### `decide(fact, all = false)`
|
|
384
|
+
|
|
385
|
+
Evaluates a fact against configured rules.
|
|
386
|
+
|
|
387
|
+
**Parameters:**
|
|
388
|
+
|
|
389
|
+
- `fact` (Object): The fact to evaluate
|
|
390
|
+
- `all` (Boolean): If true, returns all matching rules; if false, returns
|
|
391
|
+
only first match
|
|
392
|
+
|
|
393
|
+
**Returns:**
|
|
394
|
+
Array of decision objects:
|
|
395
|
+
|
|
396
|
+
```javascript
|
|
397
|
+
[
|
|
398
|
+
{ rule: 'rule-name', decision: 'decision-type', ...decision-value }
|
|
399
|
+
]
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
Returns `null` (or empty array if `all=true`) if no rules match.
|
|
403
|
+
|
|
404
|
+
## Testing
|
|
405
|
+
|
|
406
|
+
The library supports inline test definitions in YAML:
|
|
407
|
+
|
|
408
|
+
```yaml
|
|
409
|
+
rules:
|
|
410
|
+
# ... rule definitions
|
|
411
|
+
|
|
412
|
+
tests:
|
|
413
|
+
- fact: { type: transfer, amount: 500 }
|
|
414
|
+
expected:
|
|
415
|
+
- approved: true
|
|
416
|
+
reason: approved
|
|
417
|
+
rule: transfer-approval
|
|
418
|
+
decision: expect
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
Run tests with Jest:
|
|
422
|
+
|
|
423
|
+
```javascript
|
|
424
|
+
const decision = require('./');
|
|
425
|
+
const { decide, tests } = decision('./config.yaml');
|
|
426
|
+
|
|
427
|
+
tests.forEach(({ fact, expected }) => {
|
|
428
|
+
test(`fact: ${JSON.stringify(fact)}`, () => {
|
|
429
|
+
expect(decide(fact)).toEqual(expected);
|
|
430
|
+
});
|
|
431
|
+
});
|
|
432
|
+
```
|
package/index.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const match = require('@infitx/match');
|
|
2
|
+
const yaml = require('yaml');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
|
|
5
|
+
module.exports = function decision(config) {
|
|
6
|
+
if (typeof config === 'string') {
|
|
7
|
+
config = yaml.parse(fs.readFileSync(config, 'utf8'), { customTags: ['timestamp'] });
|
|
8
|
+
}
|
|
9
|
+
let rules = config.rules ?? config;
|
|
10
|
+
if (!Array.isArray(rules)) rules = Object.entries(rules).map(([rule, value]) => ({ rule, ...value })).sort((a, b) => {
|
|
11
|
+
const aPriority = a.priority ?? a.rule;
|
|
12
|
+
const bPriority = b.priority ?? b.rule;
|
|
13
|
+
if (aPriority < bPriority) return -1;
|
|
14
|
+
if (aPriority > bPriority) return 1;
|
|
15
|
+
return 0;
|
|
16
|
+
});
|
|
17
|
+
return {
|
|
18
|
+
...config,
|
|
19
|
+
rules,
|
|
20
|
+
decide: (fact, all) => {
|
|
21
|
+
const decisions = all ? [] : null;
|
|
22
|
+
for (const index in rules) {
|
|
23
|
+
const { rule = index, when, then } = rules[index];
|
|
24
|
+
if (match(fact, when)) {
|
|
25
|
+
if (all) {
|
|
26
|
+
Object.entries(typeof then === 'function' ? then(fact) : then).forEach(([decision, value]) => decisions.push({ rule, decision, ...value }));
|
|
27
|
+
} else {
|
|
28
|
+
return Object.entries(typeof then === 'function' ? then(fact) : then).map(([decision, value]) => ({ rule, decision, ...value }));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return decisions;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
package/package.json
CHANGED
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@infitx/decision",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "",
|
|
5
|
-
"license": "ISC",
|
|
6
|
-
"author": "",
|
|
7
|
-
"type": "commonjs",
|
|
3
|
+
"version": "1.3.2",
|
|
4
|
+
"description": "Decision tables engine",
|
|
8
5
|
"main": "index.js",
|
|
9
6
|
"scripts": {
|
|
10
|
-
"
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
"build": "true",
|
|
8
|
+
"ci-unit": "JEST_JUNIT_OUTPUT_DIR=coverage jest --ci --reporters=default --reporters=jest-junit --outputFile=./coverage/junit.xml",
|
|
9
|
+
"ci-publish": "npm publish --access public --provenance",
|
|
10
|
+
"watch": "jest --watchAll"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@infitx/match": "workspace:*",
|
|
14
|
+
"yaml": "^2.8.1"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"jest": "^30.2.0",
|
|
18
|
+
"jest-junit": "^16.0.0"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"url": "git+https://github.com/infitx-org/release-cd.git"
|
|
22
|
+
},
|
|
23
|
+
"author": "Kalin Krustev",
|
|
24
|
+
"license": "Apache-2.0"
|
|
25
|
+
}
|