@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/dist/index.cjs CHANGED
@@ -37,7 +37,6 @@ __export(exports_src, {
37
37
  validateRule: () => validateRule,
38
38
  validateConditions: () => validateConditions,
39
39
  updateRule: () => updateRule,
40
- tap: () => tap,
41
40
  str: () => str,
42
41
  sortRules: () => sortRules,
43
42
  sortByUpdatedAt: () => sortByUpdatedAt,
@@ -55,16 +54,18 @@ __export(exports_src, {
55
54
  removeRuleSet: () => removeRuleSet,
56
55
  removeRule: () => removeRule,
57
56
  pruneOldVersions: () => pruneOldVersions,
58
- pipe: () => pipe,
57
+ parseVersioningConfig: () => parseVersioningConfig,
58
+ parseValidationConfig: () => parseValidationConfig,
59
59
  parseRule: () => parseRule,
60
+ parseCacheConfig: () => parseCacheConfig,
60
61
  or: () => or,
61
62
  num: () => num,
62
63
  mergeRuleSets: () => mergeRuleSets,
63
64
  measureTimeAsync: () => measureTimeAsync,
64
65
  measureTime: () => measureTime,
66
+ isConditionGroup: () => import_condition_evaluator7.isConditionGroup,
65
67
  importRules: () => importRules,
66
68
  importFromJson: () => importFromJson,
67
- identity: () => identity,
68
69
  hashRules: () => hashRules,
69
70
  hashContext: () => hashContext,
70
71
  hasErrors: () => hasErrors,
@@ -95,6 +96,11 @@ __export(exports_src, {
95
96
  getLatestVersion: () => getLatestVersion,
96
97
  getIndexStats: () => getIndexStats,
97
98
  getHistory: () => getHistory,
99
+ getDefaultVersioningConfig: () => getDefaultVersioningConfig,
100
+ getDefaultValidationConfig: () => getDefaultValidationConfig,
101
+ getDefaultLogLevel: () => getDefaultLogLevel,
102
+ getDefaultConflictResolution: () => getDefaultConflictResolution,
103
+ getDefaultCacheConfig: () => getDefaultCacheConfig,
98
104
  getConflictsByType: () => getConflictsByType,
99
105
  getConflictsBySeverity: () => getConflictsBySeverity,
100
106
  getAllVersions: () => getAllVersions,
@@ -123,7 +129,6 @@ __export(exports_src, {
123
129
  detectConflicts: () => detectConflicts,
124
130
  deserializeRuleSet: () => deserializeRuleSet,
125
131
  deserializeRule: () => deserializeRule,
126
- delay: () => delay,
127
132
  date: () => date,
128
133
  createVersionStore: () => createVersionStore,
129
134
  createRuleValidator: () => createRuleValidator,
@@ -135,7 +140,6 @@ __export(exports_src, {
135
140
  createEngine: () => createEngine,
136
141
  createCache: () => createCache,
137
142
  conditions: () => conditions,
138
- compose: () => compose,
139
143
  compareVersions: () => compareVersions,
140
144
  cloneState: () => cloneState,
141
145
  cloneRule: () => cloneRule,
@@ -154,23 +158,50 @@ __export(exports_src, {
154
158
  analyzeOperatorUsage: () => analyzeOperatorUsage,
155
159
  analyzeFieldUsage: () => analyzeFieldUsage,
156
160
  analyzeConsequenceUsage: () => analyzeConsequenceUsage,
157
- always: () => always,
158
161
  all: () => all,
159
162
  addVersion: () => addVersion,
160
163
  addRules: () => addRules,
161
164
  addRuleSet: () => addRuleSet,
162
165
  addRule: () => addRule,
166
+ VersioningConfigSchema: () => VersioningConfigSchema,
167
+ ValidationResultSchema: () => ValidationResultSchema,
168
+ ValidationOptionsSchema: () => ValidationOptionsSchema,
169
+ ValidationErrorSchema: () => ValidationErrorSchema,
170
+ ValidationConfigSchema: () => ValidationConfigSchema,
171
+ RuleStatsSchema: () => RuleStatsSchema,
163
172
  RuleSetSchema: () => RuleSetSchema,
164
173
  RuleSchema: () => RuleSchema,
165
- DEFAULT_VERSIONING_CONFIG: () => DEFAULT_VERSIONING_CONFIG,
166
- DEFAULT_VALIDATION_CONFIG: () => DEFAULT_VALIDATION_CONFIG,
167
- DEFAULT_ENGINE_CONFIG: () => DEFAULT_ENGINE_CONFIG,
168
- DEFAULT_CACHE_CONFIG: () => DEFAULT_CACHE_CONFIG
174
+ LogLevelSchema: () => LogLevelSchema,
175
+ EvaluateOptionsSchema: () => EvaluateOptionsSchema,
176
+ EvaluateConfigSchema: () => EvaluateConfigSchema,
177
+ EngineStatsSchema: () => EngineStatsSchema,
178
+ ConflictResolutionStrategySchema: () => ConflictResolutionStrategySchema,
179
+ ConditionGroupSchema: () => import_condition_evaluator7.ConditionGroup,
180
+ CacheStatsSchema: () => CacheStatsSchema,
181
+ CacheConfigSchema: () => CacheConfigSchema
169
182
  });
170
183
  module.exports = __toCommonJS(exports_src);
184
+ var import_condition_evaluator7 = require("@f-o-t/condition-evaluator");
171
185
 
172
186
  // src/analyzer/analysis.ts
187
+ var import_condition_evaluator2 = require("@f-o-t/condition-evaluator");
188
+
189
+ // src/utils/conditions.ts
173
190
  var import_condition_evaluator = require("@f-o-t/condition-evaluator");
191
+ var collectConditionFields = (condition) => {
192
+ const fields = new Set;
193
+ const traverse = (c) => {
194
+ if (import_condition_evaluator.isConditionGroup(c)) {
195
+ for (const child of c.conditions) {
196
+ traverse(child);
197
+ }
198
+ } else {
199
+ fields.add(c.field);
200
+ }
201
+ };
202
+ traverse(condition);
203
+ return fields;
204
+ };
174
205
  var countConditions = (condition) => {
175
206
  if (import_condition_evaluator.isConditionGroup(condition)) {
176
207
  return condition.conditions.reduce((sum, c) => sum + countConditions(c), 0);
@@ -185,30 +216,18 @@ var calculateMaxDepth = (condition, currentDepth = 1) => {
185
216
  }
186
217
  return currentDepth;
187
218
  };
188
- var countGroups = (condition) => {
219
+ var countConditionGroups = (condition) => {
189
220
  if (import_condition_evaluator.isConditionGroup(condition)) {
190
- return 1 + condition.conditions.reduce((sum, c) => sum + countGroups(c), 0);
221
+ return 1 + condition.conditions.reduce((sum, c) => sum + countConditionGroups(c), 0);
191
222
  }
192
223
  return 0;
193
224
  };
194
- var collectFields = (condition) => {
195
- const fields = new Set;
196
- const traverse = (c) => {
197
- if (import_condition_evaluator.isConditionGroup(c)) {
198
- for (const child of c.conditions) {
199
- traverse(child);
200
- }
201
- } else {
202
- fields.add(c.field);
203
- }
204
- };
205
- traverse(condition);
206
- return fields;
207
- };
225
+
226
+ // src/analyzer/analysis.ts
208
227
  var collectOperators = (condition) => {
209
228
  const operators = new Set;
210
229
  const traverse = (c) => {
211
- if (import_condition_evaluator.isConditionGroup(c)) {
230
+ if (import_condition_evaluator2.isConditionGroup(c)) {
212
231
  operators.add(c.operator);
213
232
  for (const child of c.conditions) {
214
233
  traverse(child);
@@ -226,8 +245,8 @@ var calculateComplexityScore = (totalConditions, maxDepth, groupCount, uniqueFie
226
245
  var analyzeRuleComplexity = (rule) => {
227
246
  const totalConditions = countConditions(rule.conditions);
228
247
  const maxDepth = calculateMaxDepth(rule.conditions);
229
- const groupCount = countGroups(rule.conditions);
230
- const uniqueFields = collectFields(rule.conditions).size;
248
+ const groupCount = countConditionGroups(rule.conditions);
249
+ const uniqueFields = collectConditionFields(rule.conditions).size;
231
250
  const uniqueOperators = collectOperators(rule.conditions).size;
232
251
  const consequenceCount = rule.consequences.length;
233
252
  const complexityScore = calculateComplexityScore(totalConditions, maxDepth, groupCount, uniqueFields);
@@ -264,7 +283,7 @@ var analyzeRuleSet = (rules) => {
264
283
  maxPriority = rule.priority;
265
284
  if (rule.enabled)
266
285
  enabledCount++;
267
- for (const field of collectFields(rule.conditions)) {
286
+ for (const field of collectConditionFields(rule.conditions)) {
268
287
  allFields.add(field);
269
288
  }
270
289
  for (const operator of collectOperators(rule.conditions)) {
@@ -308,7 +327,7 @@ var analyzeFieldUsage = (rules) => {
308
327
  const fieldMap = new Map;
309
328
  for (const rule of rules) {
310
329
  const traverse = (c) => {
311
- if (import_condition_evaluator.isConditionGroup(c)) {
330
+ if (import_condition_evaluator2.isConditionGroup(c)) {
312
331
  for (const child of c.conditions) {
313
332
  traverse(child);
314
333
  }
@@ -340,7 +359,7 @@ var analyzeOperatorUsage = (rules) => {
340
359
  const operatorMap = new Map;
341
360
  for (const rule of rules) {
342
361
  const traverse = (c) => {
343
- if (import_condition_evaluator.isConditionGroup(c)) {
362
+ if (import_condition_evaluator2.isConditionGroup(c)) {
344
363
  for (const child of c.conditions) {
345
364
  traverse(child);
346
365
  }
@@ -358,12 +377,15 @@ var analyzeOperatorUsage = (rules) => {
358
377
  };
359
378
  traverse(rule.conditions);
360
379
  }
361
- return [...operatorMap.entries()].map(([key, data]) => ({
362
- operator: key.split(":")[1],
363
- type: data.type,
364
- count: data.rules.length,
365
- rules: data.rules
366
- })).sort((a, b) => b.count - a.count);
380
+ return [...operatorMap.entries()].map(([key, data]) => {
381
+ const parts = key.split(":");
382
+ return {
383
+ operator: parts[1] ?? "",
384
+ type: data.type,
385
+ count: data.rules.length,
386
+ rules: data.rules
387
+ };
388
+ }).sort((a, b) => b.count - a.count);
367
389
  };
368
390
  var analyzeConsequenceUsage = (rules) => {
369
391
  const consequenceMap = new Map;
@@ -652,15 +674,8 @@ var createCache = (options) => {
652
674
  const evictOldest = () => {
653
675
  if (entries.size === 0)
654
676
  return;
655
- let oldestKey;
656
- let oldestTime = Number.POSITIVE_INFINITY;
657
- for (const [key, entry] of entries) {
658
- if (entry.createdAt < oldestTime) {
659
- oldestTime = entry.createdAt;
660
- oldestKey = key;
661
- }
662
- }
663
- if (oldestKey) {
677
+ const oldestKey = entries.keys().next().value;
678
+ if (oldestKey !== undefined) {
664
679
  const entry = entries.get(oldestKey);
665
680
  entries.delete(oldestKey);
666
681
  evictions++;
@@ -756,7 +771,7 @@ var createNoopCache = () => {
756
771
  };
757
772
  };
758
773
  // src/core/evaluate.ts
759
- var import_condition_evaluator2 = require("@f-o-t/condition-evaluator");
774
+ var import_condition_evaluator3 = require("@f-o-t/condition-evaluator");
760
775
 
761
776
  // src/utils/time.ts
762
777
  var measureTime = (fn) => {
@@ -785,9 +800,6 @@ var withTimeout = (promise, timeoutMs, errorMessage = "Operation timed out") =>
785
800
  });
786
801
  });
787
802
  };
788
- var delay = (ms) => {
789
- return new Promise((resolve) => setTimeout(resolve, ms));
790
- };
791
803
 
792
804
  // src/core/evaluate.ts
793
805
  var evaluateRule = (rule2, context, options = {}) => {
@@ -809,7 +821,7 @@ var evaluateRule = (rule2, context, options = {}) => {
809
821
  data: context.data,
810
822
  metadata: context.metadata
811
823
  };
812
- return import_condition_evaluator2.evaluateConditionGroup(rule2.conditions, evalContext);
824
+ return import_condition_evaluator3.evaluateConditionGroup(rule2.conditions, evalContext);
813
825
  } catch (error) {
814
826
  return {
815
827
  error,
@@ -1021,30 +1033,67 @@ var sortByUpdatedAt = (direction = "desc") => {
1021
1033
  return sortRules({ field: "updatedAt", direction });
1022
1034
  };
1023
1035
  // src/types/config.ts
1024
- var DEFAULT_CACHE_CONFIG = {
1025
- enabled: true,
1026
- ttl: 60000,
1027
- maxSize: 1000
1028
- };
1029
- var DEFAULT_VALIDATION_CONFIG = {
1030
- enabled: true,
1031
- strict: false
1032
- };
1033
- var DEFAULT_VERSIONING_CONFIG = {
1034
- enabled: false,
1035
- maxVersions: 10
1036
- };
1037
- var DEFAULT_ENGINE_CONFIG = {
1038
- conflictResolution: "priority",
1039
- cache: DEFAULT_CACHE_CONFIG,
1040
- validation: DEFAULT_VALIDATION_CONFIG,
1041
- versioning: DEFAULT_VERSIONING_CONFIG,
1042
- logLevel: "warn",
1043
- continueOnError: true,
1044
- slowRuleThresholdMs: 10
1045
- };
1036
+ var import_zod = require("zod");
1037
+ var LogLevelSchema = import_zod.z.enum([
1038
+ "none",
1039
+ "error",
1040
+ "warn",
1041
+ "info",
1042
+ "debug"
1043
+ ]);
1044
+ var CacheConfigSchema = import_zod.z.object({
1045
+ enabled: import_zod.z.boolean().default(true),
1046
+ ttl: import_zod.z.number().int().positive().default(60000),
1047
+ maxSize: import_zod.z.number().int().positive().default(1000)
1048
+ });
1049
+ var ValidationConfigSchema = import_zod.z.object({
1050
+ enabled: import_zod.z.boolean().default(true),
1051
+ strict: import_zod.z.boolean().default(false)
1052
+ });
1053
+ var VersioningConfigSchema = import_zod.z.object({
1054
+ enabled: import_zod.z.boolean().default(false),
1055
+ maxVersions: import_zod.z.number().int().positive().default(10)
1056
+ });
1057
+ var parseCacheConfig = (input) => CacheConfigSchema.parse(input ?? {});
1058
+ var parseValidationConfig = (input) => ValidationConfigSchema.parse(input ?? {});
1059
+ var parseVersioningConfig = (input) => VersioningConfigSchema.parse(input ?? {});
1060
+ var getDefaultCacheConfig = () => CacheConfigSchema.parse({});
1061
+ var getDefaultValidationConfig = () => ValidationConfigSchema.parse({});
1062
+ var getDefaultVersioningConfig = () => VersioningConfigSchema.parse({});
1063
+ var getDefaultLogLevel = () => "warn";
1064
+ var getDefaultConflictResolution = () => "priority";
1046
1065
 
1047
1066
  // src/types/state.ts
1067
+ var import_zod2 = require("zod");
1068
+ var RuleStatsSchema = import_zod2.z.object({
1069
+ evaluations: import_zod2.z.number().int().nonnegative(),
1070
+ matches: import_zod2.z.number().int().nonnegative(),
1071
+ errors: import_zod2.z.number().int().nonnegative(),
1072
+ totalTimeMs: import_zod2.z.number().nonnegative(),
1073
+ avgTimeMs: import_zod2.z.number().nonnegative(),
1074
+ lastEvaluated: import_zod2.z.date().optional()
1075
+ });
1076
+ var CacheStatsSchema = import_zod2.z.object({
1077
+ size: import_zod2.z.number().int().nonnegative(),
1078
+ maxSize: import_zod2.z.number().int().positive(),
1079
+ hits: import_zod2.z.number().int().nonnegative(),
1080
+ misses: import_zod2.z.number().int().nonnegative(),
1081
+ hitRate: import_zod2.z.number().min(0).max(1),
1082
+ evictions: import_zod2.z.number().int().nonnegative()
1083
+ });
1084
+ var EngineStatsSchema = import_zod2.z.object({
1085
+ totalRules: import_zod2.z.number().int().nonnegative(),
1086
+ enabledRules: import_zod2.z.number().int().nonnegative(),
1087
+ disabledRules: import_zod2.z.number().int().nonnegative(),
1088
+ totalRuleSets: import_zod2.z.number().int().nonnegative(),
1089
+ totalEvaluations: import_zod2.z.number().int().nonnegative(),
1090
+ totalMatches: import_zod2.z.number().int().nonnegative(),
1091
+ totalErrors: import_zod2.z.number().int().nonnegative(),
1092
+ avgEvaluationTimeMs: import_zod2.z.number().nonnegative(),
1093
+ cacheHits: import_zod2.z.number().int().nonnegative(),
1094
+ cacheMisses: import_zod2.z.number().int().nonnegative(),
1095
+ cacheHitRate: import_zod2.z.number().min(0).max(1)
1096
+ });
1048
1097
  var createInitialState = () => ({
1049
1098
  rules: new Map,
1050
1099
  ruleSets: new Map,
@@ -1101,82 +1150,73 @@ var generateId = () => {
1101
1150
  };
1102
1151
 
1103
1152
  // src/engine/hooks.ts
1104
- var executeBeforeEvaluation = async (hooks, context, rules) => {
1153
+ var toError = (error) => error instanceof Error ? error : new Error(String(error));
1154
+ var executeWithTimeout = async (hookName, hookFn, hooks, timeoutMs) => {
1155
+ try {
1156
+ const promise = Promise.resolve(hookFn());
1157
+ if (timeoutMs !== undefined && timeoutMs > 0) {
1158
+ await withTimeout(promise, timeoutMs, `Hook '${hookName}' timed out after ${timeoutMs}ms`);
1159
+ } else {
1160
+ await promise;
1161
+ }
1162
+ } catch (error) {
1163
+ hooks.onHookError?.(hookName, toError(error));
1164
+ }
1165
+ };
1166
+ var executeBeforeEvaluation = async (hooks, context, rules, timeoutMs) => {
1105
1167
  if (!hooks.beforeEvaluation)
1106
1168
  return;
1107
- try {
1108
- await hooks.beforeEvaluation(context, rules);
1109
- } catch {}
1169
+ await executeWithTimeout("beforeEvaluation", () => hooks.beforeEvaluation(context, rules), hooks, timeoutMs);
1110
1170
  };
1111
- var executeAfterEvaluation = async (hooks, result) => {
1171
+ var executeAfterEvaluation = async (hooks, result, timeoutMs) => {
1112
1172
  if (!hooks.afterEvaluation)
1113
1173
  return;
1114
- try {
1115
- await hooks.afterEvaluation(result);
1116
- } catch {}
1174
+ await executeWithTimeout("afterEvaluation", () => hooks.afterEvaluation(result), hooks, timeoutMs);
1117
1175
  };
1118
- var executeBeforeRuleEvaluation = async (hooks, rule2, context) => {
1176
+ var executeBeforeRuleEvaluation = async (hooks, rule2, context, timeoutMs) => {
1119
1177
  if (!hooks.beforeRuleEvaluation)
1120
1178
  return;
1121
- try {
1122
- await hooks.beforeRuleEvaluation(rule2, context);
1123
- } catch {}
1179
+ await executeWithTimeout("beforeRuleEvaluation", () => hooks.beforeRuleEvaluation(rule2, context), hooks, timeoutMs);
1124
1180
  };
1125
- var executeAfterRuleEvaluation = async (hooks, rule2, result) => {
1181
+ var executeAfterRuleEvaluation = async (hooks, rule2, result, timeoutMs) => {
1126
1182
  if (!hooks.afterRuleEvaluation)
1127
1183
  return;
1128
- try {
1129
- await hooks.afterRuleEvaluation(rule2, result);
1130
- } catch {}
1184
+ await executeWithTimeout("afterRuleEvaluation", () => hooks.afterRuleEvaluation(rule2, result), hooks, timeoutMs);
1131
1185
  };
1132
- var executeOnRuleMatch = async (hooks, rule2, context) => {
1186
+ var executeOnRuleMatch = async (hooks, rule2, context, timeoutMs) => {
1133
1187
  if (!hooks.onRuleMatch)
1134
1188
  return;
1135
- try {
1136
- await hooks.onRuleMatch(rule2, context);
1137
- } catch {}
1189
+ await executeWithTimeout("onRuleMatch", () => hooks.onRuleMatch(rule2, context), hooks, timeoutMs);
1138
1190
  };
1139
- var executeOnRuleSkip = async (hooks, rule2, reason) => {
1191
+ var executeOnRuleSkip = async (hooks, rule2, reason, timeoutMs) => {
1140
1192
  if (!hooks.onRuleSkip)
1141
1193
  return;
1142
- try {
1143
- await hooks.onRuleSkip(rule2, reason);
1144
- } catch {}
1194
+ await executeWithTimeout("onRuleSkip", () => hooks.onRuleSkip(rule2, reason), hooks, timeoutMs);
1145
1195
  };
1146
- var executeOnRuleError = async (hooks, rule2, error) => {
1196
+ var executeOnRuleError = async (hooks, rule2, ruleError, timeoutMs) => {
1147
1197
  if (!hooks.onRuleError)
1148
1198
  return;
1149
- try {
1150
- await hooks.onRuleError(rule2, error);
1151
- } catch {}
1199
+ await executeWithTimeout("onRuleError", () => hooks.onRuleError(rule2, ruleError), hooks, timeoutMs);
1152
1200
  };
1153
- var executeOnConsequenceCollected = async (hooks, rule2, consequence) => {
1201
+ var executeOnConsequenceCollected = async (hooks, rule2, consequence, timeoutMs) => {
1154
1202
  if (!hooks.onConsequenceCollected)
1155
1203
  return;
1156
- try {
1157
- await hooks.onConsequenceCollected(rule2, consequence);
1158
- } catch {}
1204
+ await executeWithTimeout("onConsequenceCollected", () => hooks.onConsequenceCollected(rule2, consequence), hooks, timeoutMs);
1159
1205
  };
1160
- var executeOnCacheHit = async (hooks, key, result) => {
1206
+ var executeOnCacheHit = async (hooks, key, result, timeoutMs) => {
1161
1207
  if (!hooks.onCacheHit)
1162
1208
  return;
1163
- try {
1164
- await hooks.onCacheHit(key, result);
1165
- } catch {}
1209
+ await executeWithTimeout("onCacheHit", () => hooks.onCacheHit(key, result), hooks, timeoutMs);
1166
1210
  };
1167
- var executeOnCacheMiss = async (hooks, key) => {
1211
+ var executeOnCacheMiss = async (hooks, key, timeoutMs) => {
1168
1212
  if (!hooks.onCacheMiss)
1169
1213
  return;
1170
- try {
1171
- await hooks.onCacheMiss(key);
1172
- } catch {}
1214
+ await executeWithTimeout("onCacheMiss", () => hooks.onCacheMiss(key), hooks, timeoutMs);
1173
1215
  };
1174
- var executeOnSlowRule = async (hooks, rule2, timeMs, threshold) => {
1216
+ var executeOnSlowRule = async (hooks, rule2, timeMs, threshold, timeoutMs) => {
1175
1217
  if (!hooks.onSlowRule)
1176
1218
  return;
1177
- try {
1178
- await hooks.onSlowRule(rule2, timeMs, threshold);
1179
- } catch {}
1219
+ await executeWithTimeout("onSlowRule", () => hooks.onSlowRule(rule2, timeMs, threshold), hooks, timeoutMs);
1180
1220
  };
1181
1221
 
1182
1222
  // src/engine/state.ts
@@ -1361,24 +1401,25 @@ var cloneState = (state) => {
1361
1401
  var resolveConfig = (config) => {
1362
1402
  return {
1363
1403
  consequences: config.consequences,
1364
- conflictResolution: config.conflictResolution ?? DEFAULT_ENGINE_CONFIG.conflictResolution,
1404
+ conflictResolution: config.conflictResolution ?? getDefaultConflictResolution(),
1365
1405
  cache: {
1366
- ...DEFAULT_CACHE_CONFIG,
1406
+ ...getDefaultCacheConfig(),
1367
1407
  ...config.cache
1368
1408
  },
1369
1409
  validation: {
1370
- ...DEFAULT_VALIDATION_CONFIG,
1410
+ ...getDefaultValidationConfig(),
1371
1411
  ...config.validation
1372
1412
  },
1373
1413
  versioning: {
1374
- ...DEFAULT_VERSIONING_CONFIG,
1414
+ ...getDefaultVersioningConfig(),
1375
1415
  ...config.versioning
1376
1416
  },
1377
1417
  hooks: config.hooks ?? {},
1378
- logLevel: config.logLevel ?? DEFAULT_ENGINE_CONFIG.logLevel,
1418
+ logLevel: config.logLevel ?? getDefaultLogLevel(),
1379
1419
  logger: config.logger ?? console,
1380
- continueOnError: config.continueOnError ?? DEFAULT_ENGINE_CONFIG.continueOnError,
1381
- slowRuleThresholdMs: config.slowRuleThresholdMs ?? DEFAULT_ENGINE_CONFIG.slowRuleThresholdMs
1420
+ continueOnError: config.continueOnError ?? true,
1421
+ slowRuleThresholdMs: config.slowRuleThresholdMs ?? 10,
1422
+ hookTimeoutMs: config.hookTimeoutMs
1382
1423
  };
1383
1424
  };
1384
1425
  var createEngine = (config = {}) => {
@@ -1410,12 +1451,6 @@ var createEngine = (config = {}) => {
1410
1451
  const ruleSetIds = new Set(ruleSetRules.map((r) => r.id));
1411
1452
  rulesToEvaluate = rulesToEvaluate.filter((r) => ruleSetIds.has(r.id));
1412
1453
  }
1413
- rulesToEvaluate = [
1414
- ...sortRules({
1415
- field: "priority",
1416
- direction: "desc"
1417
- })(rulesToEvaluate)
1418
- ];
1419
1454
  if (options.maxRules && options.maxRules > 0) {
1420
1455
  rulesToEvaluate = rulesToEvaluate.slice(0, options.maxRules);
1421
1456
  }
@@ -1424,15 +1459,15 @@ var createEngine = (config = {}) => {
1424
1459
  const cached = cache.get(cacheKey);
1425
1460
  if (cached) {
1426
1461
  cacheHits++;
1427
- await executeOnCacheHit(resolvedConfig.hooks, cacheKey, cached);
1462
+ await executeOnCacheHit(resolvedConfig.hooks, cacheKey, cached, resolvedConfig.hookTimeoutMs);
1428
1463
  return { ...cached, cacheHit: true };
1429
1464
  }
1430
1465
  }
1431
1466
  if (cacheKey) {
1432
1467
  cacheMisses++;
1433
- await executeOnCacheMiss(resolvedConfig.hooks, cacheKey);
1468
+ await executeOnCacheMiss(resolvedConfig.hooks, cacheKey, resolvedConfig.hookTimeoutMs);
1434
1469
  }
1435
- await executeBeforeEvaluation(resolvedConfig.hooks, context, rulesToEvaluate);
1470
+ await executeBeforeEvaluation(resolvedConfig.hooks, context, rulesToEvaluate, resolvedConfig.hookTimeoutMs);
1436
1471
  const { result: evaluationResult, durationMs } = measureTime(() => {
1437
1472
  const results = [];
1438
1473
  for (const rule2 of rulesToEvaluate) {
@@ -1449,29 +1484,29 @@ var createEngine = (config = {}) => {
1449
1484
  let rulesErrored = 0;
1450
1485
  const conflictResolution = options.conflictResolution ?? resolvedConfig.conflictResolution;
1451
1486
  for (const { rule: rule2, result } of evaluationResult) {
1452
- await executeBeforeRuleEvaluation(resolvedConfig.hooks, rule2, context);
1487
+ await executeBeforeRuleEvaluation(resolvedConfig.hooks, rule2, context, resolvedConfig.hookTimeoutMs);
1453
1488
  ruleResults.push(result);
1454
1489
  if (result.error) {
1455
1490
  rulesErrored++;
1456
- await executeOnRuleError(resolvedConfig.hooks, rule2, result.error);
1491
+ await executeOnRuleError(resolvedConfig.hooks, rule2, result.error, resolvedConfig.hookTimeoutMs);
1457
1492
  if (!resolvedConfig.continueOnError) {
1458
1493
  break;
1459
1494
  }
1460
1495
  }
1461
1496
  if (result.skipped) {
1462
- await executeOnRuleSkip(resolvedConfig.hooks, rule2, result.skipReason ?? "Unknown");
1497
+ await executeOnRuleSkip(resolvedConfig.hooks, rule2, result.skipReason ?? "Unknown", resolvedConfig.hookTimeoutMs);
1463
1498
  }
1464
1499
  if (result.evaluationTimeMs > resolvedConfig.slowRuleThresholdMs) {
1465
- await executeOnSlowRule(resolvedConfig.hooks, rule2, result.evaluationTimeMs, resolvedConfig.slowRuleThresholdMs);
1500
+ await executeOnSlowRule(resolvedConfig.hooks, rule2, result.evaluationTimeMs, resolvedConfig.slowRuleThresholdMs, resolvedConfig.hookTimeoutMs);
1466
1501
  }
1467
- await executeAfterRuleEvaluation(resolvedConfig.hooks, rule2, result);
1502
+ await executeAfterRuleEvaluation(resolvedConfig.hooks, rule2, result, resolvedConfig.hookTimeoutMs);
1468
1503
  if (result.matched) {
1469
1504
  matchedRules.push(rule2);
1470
1505
  for (const consequence of result.consequences) {
1471
1506
  consequences.push(consequence);
1472
- await executeOnConsequenceCollected(resolvedConfig.hooks, rule2, consequence);
1507
+ await executeOnConsequenceCollected(resolvedConfig.hooks, rule2, consequence, resolvedConfig.hookTimeoutMs);
1473
1508
  }
1474
- await executeOnRuleMatch(resolvedConfig.hooks, rule2, context);
1509
+ await executeOnRuleMatch(resolvedConfig.hooks, rule2, context, resolvedConfig.hookTimeoutMs);
1475
1510
  if (rule2.stopOnMatch) {
1476
1511
  stoppedEarly = true;
1477
1512
  stoppedByRuleId = rule2.id;
@@ -1505,7 +1540,7 @@ var createEngine = (config = {}) => {
1505
1540
  if (cacheKey) {
1506
1541
  cache.set(cacheKey, executionResult);
1507
1542
  }
1508
- await executeAfterEvaluation(resolvedConfig.hooks, executionResult);
1543
+ await executeAfterEvaluation(resolvedConfig.hooks, executionResult, resolvedConfig.hookTimeoutMs);
1509
1544
  return executionResult;
1510
1545
  };
1511
1546
  return {
@@ -1555,7 +1590,7 @@ var createEngine = (config = {}) => {
1555
1590
  }),
1556
1591
  getStats: () => {
1557
1592
  const enabledRules = Array.from(state.rules.values()).filter((r) => r.enabled).length;
1558
- const cacheStats = cache.getStats();
1593
+ const _cacheStats = cache.getStats();
1559
1594
  return {
1560
1595
  totalRules: state.rules.size,
1561
1596
  enabledRules,
@@ -1573,27 +1608,12 @@ var createEngine = (config = {}) => {
1573
1608
  };
1574
1609
  };
1575
1610
  // src/optimizer/index-builder.ts
1576
- var import_condition_evaluator3 = require("@f-o-t/condition-evaluator");
1577
1611
  var DEFAULT_OPTIONS = {
1578
1612
  indexByField: true,
1579
1613
  indexByTag: true,
1580
1614
  indexByCategory: true,
1581
1615
  indexByPriority: true
1582
1616
  };
1583
- var collectFields2 = (condition) => {
1584
- const fields = new Set;
1585
- const traverse = (c) => {
1586
- if (import_condition_evaluator3.isConditionGroup(c)) {
1587
- for (const child of c.conditions) {
1588
- traverse(child);
1589
- }
1590
- } else {
1591
- fields.add(c.field);
1592
- }
1593
- };
1594
- traverse(condition);
1595
- return fields;
1596
- };
1597
1617
  var buildIndex = (rules, options = {}) => {
1598
1618
  const opts = { ...DEFAULT_OPTIONS, ...options };
1599
1619
  const byId = new Map;
@@ -1604,7 +1624,7 @@ var buildIndex = (rules, options = {}) => {
1604
1624
  for (const rule2 of rules) {
1605
1625
  byId.set(rule2.id, rule2);
1606
1626
  if (opts.indexByField) {
1607
- const fields = collectFields2(rule2.conditions);
1627
+ const fields = collectConditionFields(rule2.conditions);
1608
1628
  for (const field of fields) {
1609
1629
  const existing = byField.get(field) ?? [];
1610
1630
  existing.push(rule2);
@@ -1709,7 +1729,7 @@ var analyzeOptimizations = (rules) => {
1709
1729
  const suggestions = [];
1710
1730
  const fieldUsage = new Map;
1711
1731
  for (const rule2 of rules) {
1712
- const fields = collectFields2(rule2.conditions);
1732
+ const fields = collectConditionFields(rule2.conditions);
1713
1733
  for (const field of fields) {
1714
1734
  fieldUsage.set(field, (fieldUsage.get(field) ?? 0) + 1);
1715
1735
  }
@@ -1862,6 +1882,8 @@ var importRules = (data, options = {}) => {
1862
1882
  for (let i = 0;i < data.rules.length; i++) {
1863
1883
  try {
1864
1884
  const serialized = data.rules[i];
1885
+ if (!serialized)
1886
+ continue;
1865
1887
  const rule2 = deserializeRule(serialized, options);
1866
1888
  idMapping.set(serialized.id, rule2.id);
1867
1889
  rules.push(rule2);
@@ -1877,6 +1899,8 @@ var importRules = (data, options = {}) => {
1877
1899
  for (let i = 0;i < data.ruleSets.length; i++) {
1878
1900
  try {
1879
1901
  const serialized = data.ruleSets[i];
1902
+ if (!serialized)
1903
+ continue;
1880
1904
  const ruleSet = deserializeRuleSet(serialized, idMapping, options);
1881
1905
  ruleSets.push(ruleSet);
1882
1906
  } catch (error) {
@@ -1888,12 +1912,25 @@ var importRules = (data, options = {}) => {
1888
1912
  }
1889
1913
  }
1890
1914
  }
1915
+ const importedRuleIds = new Set(rules.map((r) => r.id));
1916
+ const orphanedReferences = [];
1917
+ for (const ruleSet of ruleSets) {
1918
+ const missingRuleIds = ruleSet.ruleIds.filter((id) => !importedRuleIds.has(id));
1919
+ if (missingRuleIds.length > 0) {
1920
+ orphanedReferences.push({
1921
+ ruleSetId: ruleSet.id,
1922
+ ruleSetName: ruleSet.name,
1923
+ missingRuleIds
1924
+ });
1925
+ }
1926
+ }
1891
1927
  return {
1892
1928
  success: errors.length === 0,
1893
1929
  rules,
1894
1930
  ruleSets,
1895
1931
  errors,
1896
- idMapping
1932
+ idMapping,
1933
+ orphanedReferences
1897
1934
  };
1898
1935
  };
1899
1936
  var importFromJson = (json, options = {}) => {
@@ -1912,7 +1949,8 @@ var importFromJson = (json, options = {}) => {
1912
1949
  message: `Invalid JSON: ${error instanceof Error ? error.message : String(error)}`
1913
1950
  }
1914
1951
  ],
1915
- idMapping: new Map
1952
+ idMapping: new Map,
1953
+ orphanedReferences: []
1916
1954
  };
1917
1955
  }
1918
1956
  };
@@ -2049,8 +2087,8 @@ var whatIf = (originalRules, modifiedRules, context) => {
2049
2087
  const [ruleId, consequenceType] = key.split(":");
2050
2088
  consequenceChanges.push({
2051
2089
  type: "added",
2052
- consequenceType,
2053
- ruleId
2090
+ consequenceType: consequenceType ?? "",
2091
+ ruleId: ruleId ?? ""
2054
2092
  });
2055
2093
  }
2056
2094
  }
@@ -2059,8 +2097,8 @@ var whatIf = (originalRules, modifiedRules, context) => {
2059
2097
  const [ruleId, consequenceType] = key.split(":");
2060
2098
  consequenceChanges.push({
2061
2099
  type: "removed",
2062
- consequenceType,
2063
- ruleId
2100
+ consequenceType: consequenceType ?? "",
2101
+ ruleId: ruleId ?? ""
2064
2102
  });
2065
2103
  }
2066
2104
  }
@@ -2149,49 +2187,59 @@ var formatSimulationResult = (result) => {
2149
2187
  return lines.join(`
2150
2188
  `);
2151
2189
  };
2190
+ // src/types/evaluation.ts
2191
+ var import_zod3 = require("zod");
2192
+ var ConflictResolutionStrategySchema = import_zod3.z.enum([
2193
+ "priority",
2194
+ "first-match",
2195
+ "all",
2196
+ "most-specific"
2197
+ ]);
2198
+ var EvaluateOptionsSchema = import_zod3.z.object({
2199
+ conflictResolution: ConflictResolutionStrategySchema.optional(),
2200
+ maxRules: import_zod3.z.number().int().positive().optional(),
2201
+ timeout: import_zod3.z.number().int().positive().optional(),
2202
+ skipDisabled: import_zod3.z.boolean().optional(),
2203
+ tags: import_zod3.z.array(import_zod3.z.string()).optional(),
2204
+ category: import_zod3.z.string().optional(),
2205
+ ruleSetId: import_zod3.z.string().optional(),
2206
+ bypassCache: import_zod3.z.boolean().optional()
2207
+ });
2208
+ var EvaluateConfigSchema = import_zod3.z.object({
2209
+ conflictResolution: ConflictResolutionStrategySchema,
2210
+ continueOnError: import_zod3.z.boolean(),
2211
+ collectAllConsequences: import_zod3.z.boolean()
2212
+ });
2152
2213
  // src/types/rule.ts
2153
- var import_zod = require("zod");
2154
- var RuleSchema = import_zod.z.object({
2155
- id: import_zod.z.string().min(1),
2156
- name: import_zod.z.string().min(1),
2157
- description: import_zod.z.string().optional(),
2158
- conditions: import_zod.z.custom((val) => {
2214
+ var import_zod4 = require("zod");
2215
+ var RuleSchema = import_zod4.z.object({
2216
+ id: import_zod4.z.string().min(1),
2217
+ name: import_zod4.z.string().min(1),
2218
+ description: import_zod4.z.string().optional(),
2219
+ conditions: import_zod4.z.custom((val) => {
2159
2220
  return typeof val === "object" && val !== null && "id" in val && "operator" in val;
2160
2221
  }, "Invalid condition group"),
2161
- consequences: import_zod.z.array(import_zod.z.object({
2162
- type: import_zod.z.string(),
2163
- payload: import_zod.z.unknown()
2222
+ consequences: import_zod4.z.array(import_zod4.z.object({
2223
+ type: import_zod4.z.string(),
2224
+ payload: import_zod4.z.unknown()
2164
2225
  })),
2165
- priority: import_zod.z.number().int().default(0),
2166
- enabled: import_zod.z.boolean().default(true),
2167
- stopOnMatch: import_zod.z.boolean().default(false),
2168
- tags: import_zod.z.array(import_zod.z.string()).default([]),
2169
- category: import_zod.z.string().optional(),
2170
- metadata: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional(),
2171
- createdAt: import_zod.z.date().default(() => new Date),
2172
- updatedAt: import_zod.z.date().default(() => new Date)
2226
+ priority: import_zod4.z.number().int().default(0),
2227
+ enabled: import_zod4.z.boolean().default(true),
2228
+ stopOnMatch: import_zod4.z.boolean().default(false),
2229
+ tags: import_zod4.z.array(import_zod4.z.string()).default([]),
2230
+ category: import_zod4.z.string().optional(),
2231
+ metadata: import_zod4.z.record(import_zod4.z.string(), import_zod4.z.unknown()).optional(),
2232
+ createdAt: import_zod4.z.date().default(() => new Date),
2233
+ updatedAt: import_zod4.z.date().default(() => new Date)
2173
2234
  });
2174
- var RuleSetSchema = import_zod.z.object({
2175
- id: import_zod.z.string().min(1),
2176
- name: import_zod.z.string().min(1),
2177
- description: import_zod.z.string().optional(),
2178
- ruleIds: import_zod.z.array(import_zod.z.string()),
2179
- enabled: import_zod.z.boolean().default(true),
2180
- metadata: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional()
2235
+ var RuleSetSchema = import_zod4.z.object({
2236
+ id: import_zod4.z.string().min(1),
2237
+ name: import_zod4.z.string().min(1),
2238
+ description: import_zod4.z.string().optional(),
2239
+ ruleIds: import_zod4.z.array(import_zod4.z.string()),
2240
+ enabled: import_zod4.z.boolean().default(true),
2241
+ metadata: import_zod4.z.record(import_zod4.z.string(), import_zod4.z.unknown()).optional()
2181
2242
  });
2182
- // src/utils/pipe.ts
2183
- function pipe(...fns) {
2184
- return (value) => fns.reduce((acc, fn) => fn(acc), value);
2185
- }
2186
- function compose(...fns) {
2187
- return (value) => fns.reduceRight((acc, fn) => fn(acc), value);
2188
- }
2189
- var identity = (value) => value;
2190
- var always = (value) => () => value;
2191
- var tap = (fn) => (value) => {
2192
- fn(value);
2193
- return value;
2194
- };
2195
2243
  // src/validation/conflicts.ts
2196
2244
  var import_condition_evaluator4 = require("@f-o-t/condition-evaluator");
2197
2245
  var DEFAULT_OPTIONS2 = {
@@ -2201,11 +2249,11 @@ var DEFAULT_OPTIONS2 = {
2201
2249
  checkPriorityCollisions: true,
2202
2250
  checkUnreachableRules: true
2203
2251
  };
2204
- var collectConditionFields = (condition) => {
2252
+ var collectConditionFields2 = (condition) => {
2205
2253
  const fields = new Set;
2206
2254
  if (import_condition_evaluator4.isConditionGroup(condition)) {
2207
2255
  for (const child of condition.conditions) {
2208
- const childFields = collectConditionFields(child);
2256
+ const childFields = collectConditionFields2(child);
2209
2257
  for (const field of childFields) {
2210
2258
  fields.add(field);
2211
2259
  }
@@ -2240,8 +2288,8 @@ var getConditionOperatorValues = (condition, field) => {
2240
2288
  return results;
2241
2289
  };
2242
2290
  var areConditionsOverlapping = (conditions1, conditions2) => {
2243
- const fields1 = collectConditionFields(conditions1);
2244
- const fields2 = collectConditionFields(conditions2);
2291
+ const fields1 = collectConditionFields2(conditions1);
2292
+ const fields2 = collectConditionFields2(conditions2);
2245
2293
  const commonFields = new Set([...fields1].filter((f) => fields2.has(f)));
2246
2294
  if (commonFields.size === 0)
2247
2295
  return false;
@@ -2324,6 +2372,8 @@ var findOverlappingConditions = (rules) => {
2324
2372
  for (let j = i + 1;j < rules.length; j++) {
2325
2373
  const rule1 = rules[i];
2326
2374
  const rule2 = rules[j];
2375
+ if (!rule1 || !rule2)
2376
+ continue;
2327
2377
  const key = [rule1.id, rule2.id].sort().join(":");
2328
2378
  if (checked.has(key))
2329
2379
  continue;
@@ -2336,8 +2386,8 @@ var findOverlappingConditions = (rules) => {
2336
2386
  ruleIds: [rule1.id, rule2.id],
2337
2387
  rules: [rule1, rule2],
2338
2388
  details: {
2339
- rule1Fields: [...collectConditionFields(rule1.conditions)],
2340
- rule2Fields: [...collectConditionFields(rule2.conditions)]
2389
+ rule1Fields: [...collectConditionFields2(rule1.conditions)],
2390
+ rule2Fields: [...collectConditionFields2(rule2.conditions)]
2341
2391
  }
2342
2392
  });
2343
2393
  }
@@ -2360,6 +2410,8 @@ var findPriorityCollisions = (rules) => {
2360
2410
  for (let j = i + 1;j < rulesWithPriority.length; j++) {
2361
2411
  const r1 = rulesWithPriority[i];
2362
2412
  const r2 = rulesWithPriority[j];
2413
+ if (!r1 || !r2)
2414
+ continue;
2363
2415
  if (areConditionsOverlapping(r1.conditions, r2.conditions)) {
2364
2416
  overlappingPairs.add(r1.id);
2365
2417
  overlappingPairs.add(r2.id);
@@ -2386,10 +2438,14 @@ var findUnreachableRules = (rules) => {
2386
2438
  const sortedRules = [...rules].sort((a, b) => b.priority - a.priority);
2387
2439
  for (let i = 0;i < sortedRules.length; i++) {
2388
2440
  const rule2 = sortedRules[i];
2441
+ if (!rule2)
2442
+ continue;
2389
2443
  if (!rule2.enabled)
2390
2444
  continue;
2391
2445
  for (let j = 0;j < i; j++) {
2392
2446
  const higherPriorityRule = sortedRules[j];
2447
+ if (!higherPriorityRule)
2448
+ continue;
2393
2449
  if (!higherPriorityRule.enabled || !higherPriorityRule.stopOnMatch) {
2394
2450
  continue;
2395
2451
  }
@@ -2528,7 +2584,7 @@ var checkRuleIntegrity = (rule2, options) => {
2528
2584
  }
2529
2585
  }
2530
2586
  if (options.allowedTags) {
2531
- const invalidTags = rule2.tags.filter((t) => !options.allowedTags.includes(t));
2587
+ const invalidTags = rule2.tags.filter((t) => !options.allowedTags?.includes(t));
2532
2588
  if (invalidTags.length > 0) {
2533
2589
  issues.push(createIssue("INVALID_TAGS", `Rule "${rule2.name}" has invalid tags: ${invalidTags.join(", ")}`, "warning", {
2534
2590
  ruleId: rule2.id,
@@ -2701,11 +2757,22 @@ ${severity.toUpperCase()}S (${issues.length}):`);
2701
2757
  };
2702
2758
  // src/validation/schema.ts
2703
2759
  var import_condition_evaluator6 = require("@f-o-t/condition-evaluator");
2704
- var DEFAULT_OPTIONS4 = {
2705
- validateConditions: true,
2706
- validateConsequences: true,
2707
- strictMode: false
2708
- };
2760
+ var import_zod5 = require("zod");
2761
+ var ValidationErrorSchema = import_zod5.z.object({
2762
+ path: import_zod5.z.string(),
2763
+ message: import_zod5.z.string(),
2764
+ code: import_zod5.z.string()
2765
+ });
2766
+ var ValidationResultSchema = import_zod5.z.object({
2767
+ valid: import_zod5.z.boolean(),
2768
+ errors: import_zod5.z.array(ValidationErrorSchema)
2769
+ });
2770
+ var ValidationOptionsSchema = import_zod5.z.object({
2771
+ validateConditions: import_zod5.z.boolean().optional(),
2772
+ validateConsequences: import_zod5.z.boolean().optional(),
2773
+ strictMode: import_zod5.z.boolean().optional()
2774
+ });
2775
+ var DEFAULT_OPTIONS4 = ValidationOptionsSchema.parse({});
2709
2776
  var createError = (path, message, code) => ({
2710
2777
  path,
2711
2778
  message,
@@ -2717,7 +2784,7 @@ var validResult = () => ({
2717
2784
  });
2718
2785
  var invalidResult = (errors) => ({
2719
2786
  valid: false,
2720
- errors
2787
+ errors: [...errors]
2721
2788
  });
2722
2789
  var validateConditionStructure = (condition, path) => {
2723
2790
  const errors = [];
@@ -2758,6 +2825,8 @@ var validateConsequenceStructure = (consequences, consequenceSchemas, strictMode
2758
2825
  const errors = [];
2759
2826
  for (let i = 0;i < consequences.length; i++) {
2760
2827
  const consequence = consequences[i];
2828
+ if (!consequence)
2829
+ continue;
2761
2830
  const path = `consequences[${i}]`;
2762
2831
  if (!consequence.type || typeof consequence.type !== "string") {
2763
2832
  errors.push(createError(`${path}.type`, "Consequence must have a type", "MISSING_CONSEQUENCE_TYPE"));
@@ -2794,8 +2863,8 @@ var validateRule = (rule2, options = {}) => {
2794
2863
  const conditionErrors = validateConditionStructure(validRule.conditions, "conditions");
2795
2864
  errors.push(...conditionErrors);
2796
2865
  }
2797
- if (opts.validateConsequences) {
2798
- const consequenceErrors = validateConsequenceStructure(validRule.consequences, opts.consequenceSchemas, opts.strictMode);
2866
+ if (opts.validateConsequences || opts.strictMode) {
2867
+ const consequenceErrors = validateConsequenceStructure(validRule.consequences, opts.consequenceSchemas, opts.strictMode ?? false);
2799
2868
  errors.push(...consequenceErrors);
2800
2869
  }
2801
2870
  return errors.length > 0 ? invalidResult(errors) : validResult();