@f-o-t/rules-engine 1.0.0 → 2.0.0
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/README.md +78 -20
- package/dist/index.cjs +287 -218
- package/dist/index.d.cts +191 -186
- package/dist/index.d.ts +191 -186
- package/dist/index.js +292 -218
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @f-o-t/rules-engine
|
|
2
2
|
|
|
3
|
-
A fully type-safe, functional,
|
|
3
|
+
A fully type-safe, functional, rules orchestration engine for TypeScript. Built on top of `@f-o-t/condition-evaluator` for condition evaluation.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
@@ -219,17 +219,72 @@ const engine = createEngine({
|
|
|
219
219
|
// Performance monitoring
|
|
220
220
|
slowRuleThresholdMs: 100,
|
|
221
221
|
|
|
222
|
+
// Hook timeout (prevents slow hooks from blocking)
|
|
223
|
+
hookTimeoutMs: 5000, // 5 second timeout
|
|
224
|
+
|
|
222
225
|
// Lifecycle hooks
|
|
223
226
|
hooks: {
|
|
224
|
-
|
|
225
|
-
|
|
227
|
+
beforeEvaluation: async (context, rules) => {},
|
|
228
|
+
afterEvaluation: async (result) => {},
|
|
226
229
|
onRuleMatch: async (rule, context) => {},
|
|
227
230
|
onRuleError: async (rule, error) => {},
|
|
228
231
|
onCacheHit: async (key, result) => {},
|
|
232
|
+
onSlowRule: async (rule, timeMs, threshold) => {},
|
|
233
|
+
// Error handler for hook failures
|
|
234
|
+
onHookError: (hookName, error) => {
|
|
235
|
+
console.error(`Hook ${hookName} failed:`, error);
|
|
236
|
+
},
|
|
229
237
|
},
|
|
230
238
|
});
|
|
231
239
|
```
|
|
232
240
|
|
|
241
|
+
## Zod Schemas
|
|
242
|
+
|
|
243
|
+
All configuration types are built from Zod schemas, enabling runtime validation and type inference:
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
import {
|
|
247
|
+
// Config schemas
|
|
248
|
+
CacheConfigSchema,
|
|
249
|
+
ValidationConfigSchema,
|
|
250
|
+
VersioningConfigSchema,
|
|
251
|
+
LogLevelSchema,
|
|
252
|
+
|
|
253
|
+
// Evaluation schemas
|
|
254
|
+
ConflictResolutionStrategySchema,
|
|
255
|
+
EvaluateOptionsSchema,
|
|
256
|
+
|
|
257
|
+
// State schemas
|
|
258
|
+
RuleStatsSchema,
|
|
259
|
+
CacheStatsSchema,
|
|
260
|
+
EngineStatsSchema,
|
|
261
|
+
|
|
262
|
+
// Validation schemas
|
|
263
|
+
ValidationErrorSchema,
|
|
264
|
+
ValidationResultSchema,
|
|
265
|
+
ValidationOptionsSchema,
|
|
266
|
+
|
|
267
|
+
// Helper functions
|
|
268
|
+
getDefaultCacheConfig,
|
|
269
|
+
getDefaultValidationConfig,
|
|
270
|
+
parseCacheConfig,
|
|
271
|
+
} from "@f-o-t/rules-engine";
|
|
272
|
+
|
|
273
|
+
// Parse and validate config with defaults
|
|
274
|
+
const cacheConfig = parseCacheConfig({ ttl: 30000 });
|
|
275
|
+
// Result: { enabled: true, ttl: 30000, maxSize: 1000 }
|
|
276
|
+
|
|
277
|
+
// Get default config
|
|
278
|
+
const defaults = getDefaultCacheConfig();
|
|
279
|
+
// Result: { enabled: true, ttl: 60000, maxSize: 1000 }
|
|
280
|
+
|
|
281
|
+
// Use schemas for custom validation
|
|
282
|
+
const result = CacheConfigSchema.safeParse(userInput);
|
|
283
|
+
if (!result.success) {
|
|
284
|
+
console.error(result.error.issues);
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
233
288
|
## Validation
|
|
234
289
|
|
|
235
290
|
```typescript
|
|
@@ -360,11 +415,26 @@ import {
|
|
|
360
415
|
} from "@f-o-t/rules-engine";
|
|
361
416
|
|
|
362
417
|
// Export/Import
|
|
363
|
-
const json = exportToJson(rules);
|
|
364
|
-
const
|
|
418
|
+
const json = exportToJson(rules, ruleSets);
|
|
419
|
+
const result = importFromJson(json, {
|
|
365
420
|
generateNewIds: true, // Generate new IDs on import
|
|
366
421
|
});
|
|
367
422
|
|
|
423
|
+
if (result.success) {
|
|
424
|
+
console.log("Imported rules:", result.rules);
|
|
425
|
+
console.log("Imported ruleSets:", result.ruleSets);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// Check for orphaned references (ruleSets referencing missing rules)
|
|
429
|
+
if (result.orphanedReferences.length > 0) {
|
|
430
|
+
for (const orphan of result.orphanedReferences) {
|
|
431
|
+
console.warn(
|
|
432
|
+
`RuleSet "${orphan.ruleSetName}" references missing rules:`,
|
|
433
|
+
orphan.missingRuleIds
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
368
438
|
// Clone rule
|
|
369
439
|
const cloned = cloneRule(rule, { generateNewId: true });
|
|
370
440
|
|
|
@@ -431,15 +501,9 @@ import {
|
|
|
431
501
|
generateId,
|
|
432
502
|
hashContext,
|
|
433
503
|
hashRules,
|
|
434
|
-
pipe,
|
|
435
|
-
compose,
|
|
436
|
-
identity,
|
|
437
|
-
always,
|
|
438
|
-
tap,
|
|
439
504
|
measureTime,
|
|
440
505
|
measureTimeAsync,
|
|
441
506
|
withTimeout,
|
|
442
|
-
delay,
|
|
443
507
|
} from "@f-o-t/rules-engine";
|
|
444
508
|
|
|
445
509
|
// Generate unique IDs
|
|
@@ -448,13 +512,6 @@ const id = generateId();
|
|
|
448
512
|
// Hash context for caching
|
|
449
513
|
const hash = hashContext({ amount: 100 });
|
|
450
514
|
|
|
451
|
-
// Functional composition
|
|
452
|
-
const process = pipe(
|
|
453
|
-
(rules) => filterRules(rules, { enabled: true }),
|
|
454
|
-
(rules) => sortByPriority(rules, "desc"),
|
|
455
|
-
(rules) => rules.slice(0, 10)
|
|
456
|
-
);
|
|
457
|
-
|
|
458
515
|
// Measure execution time
|
|
459
516
|
const { result, durationMs } = measureTime(() => expensiveOperation());
|
|
460
517
|
|
|
@@ -465,8 +522,9 @@ const { result: asyncResult, durationMs: asyncTime } = await measureTimeAsync(
|
|
|
465
522
|
|
|
466
523
|
// Timeout wrapper
|
|
467
524
|
const resultWithTimeout = await withTimeout(
|
|
468
|
-
|
|
469
|
-
5000 // 5 second timeout
|
|
525
|
+
slowOperationPromise,
|
|
526
|
+
5000, // 5 second timeout
|
|
527
|
+
"Operation timed out" // optional error message
|
|
470
528
|
);
|
|
471
529
|
```
|
|
472
530
|
|