@ram_28/kf-ai-sdk 1.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.
Files changed (126) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +840 -0
  3. package/dist/api/client.d.ts +78 -0
  4. package/dist/api/client.d.ts.map +1 -0
  5. package/dist/api/datetime.d.ts +21 -0
  6. package/dist/api/datetime.d.ts.map +1 -0
  7. package/dist/api/index.d.ts +7 -0
  8. package/dist/api/index.d.ts.map +1 -0
  9. package/dist/api/metadata.d.ts +75 -0
  10. package/dist/api/metadata.d.ts.map +1 -0
  11. package/dist/components/hooks/index.d.ts +8 -0
  12. package/dist/components/hooks/index.d.ts.map +1 -0
  13. package/dist/components/hooks/useFilter/index.d.ts +5 -0
  14. package/dist/components/hooks/useFilter/index.d.ts.map +1 -0
  15. package/dist/components/hooks/useFilter/payloadBuilder.utils.d.ts +33 -0
  16. package/dist/components/hooks/useFilter/payloadBuilder.utils.d.ts.map +1 -0
  17. package/dist/components/hooks/useFilter/types.d.ts +137 -0
  18. package/dist/components/hooks/useFilter/types.d.ts.map +1 -0
  19. package/dist/components/hooks/useFilter/useFilter.d.ts +3 -0
  20. package/dist/components/hooks/useFilter/useFilter.d.ts.map +1 -0
  21. package/dist/components/hooks/useFilter/validation.utils.d.ts +38 -0
  22. package/dist/components/hooks/useFilter/validation.utils.d.ts.map +1 -0
  23. package/dist/components/hooks/useForm/apiClient.d.ts +71 -0
  24. package/dist/components/hooks/useForm/apiClient.d.ts.map +1 -0
  25. package/dist/components/hooks/useForm/expressionValidator.utils.d.ts +28 -0
  26. package/dist/components/hooks/useForm/expressionValidator.utils.d.ts.map +1 -0
  27. package/dist/components/hooks/useForm/index.d.ts +6 -0
  28. package/dist/components/hooks/useForm/index.d.ts.map +1 -0
  29. package/dist/components/hooks/useForm/optimizedExpressionValidator.utils.d.ts +88 -0
  30. package/dist/components/hooks/useForm/optimizedExpressionValidator.utils.d.ts.map +1 -0
  31. package/dist/components/hooks/useForm/ruleClassifier.utils.d.ts +28 -0
  32. package/dist/components/hooks/useForm/ruleClassifier.utils.d.ts.map +1 -0
  33. package/dist/components/hooks/useForm/schemaParser.utils.d.ts +29 -0
  34. package/dist/components/hooks/useForm/schemaParser.utils.d.ts.map +1 -0
  35. package/dist/components/hooks/useForm/types.d.ts +412 -0
  36. package/dist/components/hooks/useForm/types.d.ts.map +1 -0
  37. package/dist/components/hooks/useForm/useForm.d.ts +3 -0
  38. package/dist/components/hooks/useForm/useForm.d.ts.map +1 -0
  39. package/dist/components/hooks/useKanban/apiClient.d.ts +99 -0
  40. package/dist/components/hooks/useKanban/apiClient.d.ts.map +1 -0
  41. package/dist/components/hooks/useKanban/context.d.ts +4 -0
  42. package/dist/components/hooks/useKanban/context.d.ts.map +1 -0
  43. package/dist/components/hooks/useKanban/dragDropManager.d.ts +27 -0
  44. package/dist/components/hooks/useKanban/dragDropManager.d.ts.map +1 -0
  45. package/dist/components/hooks/useKanban/index.d.ts +6 -0
  46. package/dist/components/hooks/useKanban/index.d.ts.map +1 -0
  47. package/dist/components/hooks/useKanban/types.d.ts +438 -0
  48. package/dist/components/hooks/useKanban/types.d.ts.map +1 -0
  49. package/dist/components/hooks/useKanban/useKanban.d.ts +3 -0
  50. package/dist/components/hooks/useKanban/useKanban.d.ts.map +1 -0
  51. package/dist/components/hooks/useKanban/useKanbanSimple.d.ts +62 -0
  52. package/dist/components/hooks/useKanban/useKanbanSimple.d.ts.map +1 -0
  53. package/dist/components/hooks/useTable/index.d.ts +3 -0
  54. package/dist/components/hooks/useTable/index.d.ts.map +1 -0
  55. package/dist/components/hooks/useTable/types.d.ts +107 -0
  56. package/dist/components/hooks/useTable/types.d.ts.map +1 -0
  57. package/dist/components/hooks/useTable/useTable.d.ts +8 -0
  58. package/dist/components/hooks/useTable/useTable.d.ts.map +1 -0
  59. package/dist/components/index.d.ts +3 -0
  60. package/dist/components/index.d.ts.map +1 -0
  61. package/dist/components/ui/index.d.ts +2 -0
  62. package/dist/components/ui/index.d.ts.map +1 -0
  63. package/dist/components/ui/kanban/Kanban.d.ts +12 -0
  64. package/dist/components/ui/kanban/Kanban.d.ts.map +1 -0
  65. package/dist/components/ui/kanban/index.d.ts +2 -0
  66. package/dist/components/ui/kanban/index.d.ts.map +1 -0
  67. package/dist/index.cjs +45 -0
  68. package/dist/index.d.ts +5 -0
  69. package/dist/index.d.ts.map +1 -0
  70. package/dist/index.mjs +6522 -0
  71. package/dist/types/base-fields.d.ts +182 -0
  72. package/dist/types/base-fields.d.ts.map +1 -0
  73. package/dist/types/common.d.ts +238 -0
  74. package/dist/types/common.d.ts.map +1 -0
  75. package/dist/types/index.d.ts +3 -0
  76. package/dist/types/index.d.ts.map +1 -0
  77. package/dist/utils/cn.d.ts +7 -0
  78. package/dist/utils/cn.d.ts.map +1 -0
  79. package/dist/utils/formatting.d.ts +52 -0
  80. package/dist/utils/formatting.d.ts.map +1 -0
  81. package/dist/utils/index.d.ts +3 -0
  82. package/dist/utils/index.d.ts.map +1 -0
  83. package/package.json +98 -0
  84. package/sdk/api/client.ts +447 -0
  85. package/sdk/api/datetime.ts +33 -0
  86. package/sdk/api/index.ts +61 -0
  87. package/sdk/api/metadata.ts +148 -0
  88. package/sdk/components/hooks/index.ts +34 -0
  89. package/sdk/components/hooks/useFilter/index.ts +37 -0
  90. package/sdk/components/hooks/useFilter/payloadBuilder.utils.ts +298 -0
  91. package/sdk/components/hooks/useFilter/types.ts +158 -0
  92. package/sdk/components/hooks/useFilter/useFilter.llm.txt +497 -0
  93. package/sdk/components/hooks/useFilter/useFilter.ts +494 -0
  94. package/sdk/components/hooks/useFilter/validation.utils.ts +401 -0
  95. package/sdk/components/hooks/useForm/apiClient.ts +441 -0
  96. package/sdk/components/hooks/useForm/expressionValidator.utils.ts +444 -0
  97. package/sdk/components/hooks/useForm/index.ts +64 -0
  98. package/sdk/components/hooks/useForm/optimizedExpressionValidator.utils.ts +482 -0
  99. package/sdk/components/hooks/useForm/ruleClassifier.utils.ts +424 -0
  100. package/sdk/components/hooks/useForm/schemaParser.utils.ts +519 -0
  101. package/sdk/components/hooks/useForm/types.ts +630 -0
  102. package/sdk/components/hooks/useForm/useForm.llm.txt +340 -0
  103. package/sdk/components/hooks/useForm/useForm.ts +821 -0
  104. package/sdk/components/hooks/useKanban/apiClient.ts +494 -0
  105. package/sdk/components/hooks/useKanban/context.ts +14 -0
  106. package/sdk/components/hooks/useKanban/dragDropManager.ts +529 -0
  107. package/sdk/components/hooks/useKanban/index.ts +63 -0
  108. package/sdk/components/hooks/useKanban/types.ts +606 -0
  109. package/sdk/components/hooks/useKanban/useKanban.llm.txt +482 -0
  110. package/sdk/components/hooks/useKanban/useKanban.ts +725 -0
  111. package/sdk/components/hooks/useKanban/useKanbanSimple.ts +389 -0
  112. package/sdk/components/hooks/useTable/index.ts +5 -0
  113. package/sdk/components/hooks/useTable/types.ts +154 -0
  114. package/sdk/components/hooks/useTable/useTable.llm.txt +344 -0
  115. package/sdk/components/hooks/useTable/useTable.ts +413 -0
  116. package/sdk/components/index.ts +15 -0
  117. package/sdk/components/ui/index.ts +2 -0
  118. package/sdk/components/ui/kanban/Kanban.tsx +134 -0
  119. package/sdk/components/ui/kanban/index.ts +11 -0
  120. package/sdk/index.ts +13 -0
  121. package/sdk/types/base-fields.ts +221 -0
  122. package/sdk/types/common.ts +306 -0
  123. package/sdk/types/index.ts +5 -0
  124. package/sdk/utils/cn.ts +10 -0
  125. package/sdk/utils/formatting.ts +212 -0
  126. package/sdk/utils/index.ts +5 -0
@@ -0,0 +1,482 @@
1
+ // ============================================================
2
+ // OPTIMIZED EXPRESSION VALIDATOR
3
+ // ============================================================
4
+ // Enhanced expression evaluator with caching, dependency tracking, and performance optimizations
5
+
6
+ import type {
7
+ ExpressionTree,
8
+ ValidationResult,
9
+ ValidationRule,
10
+ } from "./types";
11
+
12
+ // ============================================================
13
+ // CACHING SYSTEM
14
+ // ============================================================
15
+
16
+ /**
17
+ * LRU Cache for expression results
18
+ */
19
+ class LRUCache<T> {
20
+ private cache = new Map<string, T>();
21
+ private maxSize: number;
22
+
23
+ constructor(maxSize = 1000) {
24
+ this.maxSize = maxSize;
25
+ }
26
+
27
+ get(key: string): T | undefined {
28
+ const value = this.cache.get(key);
29
+ if (value !== undefined) {
30
+ // Move to end (most recently used)
31
+ this.cache.delete(key);
32
+ this.cache.set(key, value);
33
+ }
34
+ return value;
35
+ }
36
+
37
+ set(key: string, value: T): void {
38
+ if (this.cache.has(key)) {
39
+ this.cache.delete(key);
40
+ } else if (this.cache.size >= this.maxSize) {
41
+ // Remove least recently used (first entry)
42
+ const firstKey = this.cache.keys().next().value as string;
43
+ this.cache.delete(firstKey);
44
+ }
45
+ this.cache.set(key, value);
46
+ }
47
+
48
+ clear(): void {
49
+ this.cache.clear();
50
+ }
51
+ }
52
+
53
+ // ============================================================
54
+ // EXPRESSION DEPENDENCY ANALYZER
55
+ // ============================================================
56
+
57
+ /**
58
+ * Analyze expression dependencies for optimized watching
59
+ */
60
+ export function analyzeExpressionDependencies(
61
+ expression: ExpressionTree
62
+ ): Set<string> {
63
+ const dependencies = new Set<string>();
64
+
65
+ function traverse(node: ExpressionTree): void {
66
+ switch (node.Type) {
67
+ case "Identifier":
68
+ if (node.Name && !node.Name.startsWith("$")) {
69
+ dependencies.add(node.Name);
70
+ }
71
+ break;
72
+
73
+ case "MemberExpression":
74
+ if (node.Arguments) {
75
+ node.Arguments.forEach(traverse);
76
+ }
77
+ break;
78
+
79
+ case "CallExpression":
80
+ case "BinaryExpression":
81
+ case "LogicalExpression":
82
+ if (node.Arguments) {
83
+ node.Arguments.forEach(traverse);
84
+ }
85
+ break;
86
+ }
87
+ }
88
+
89
+ traverse(expression);
90
+ return dependencies;
91
+ }
92
+
93
+ /**
94
+ * Build dependency graph for multiple expressions
95
+ */
96
+ export function buildDependencyGraph(
97
+ rules: Record<string, ValidationRule>
98
+ ): Map<string, Set<string>> {
99
+ const graph = new Map<string, Set<string>>();
100
+
101
+ Object.entries(rules).forEach(([ruleId, rule]) => {
102
+ const dependencies = analyzeExpressionDependencies(rule.ExpressionTree);
103
+ graph.set(ruleId, dependencies);
104
+ });
105
+
106
+ return graph;
107
+ }
108
+
109
+ // ============================================================
110
+ // OPTIMIZED EXPRESSION EVALUATOR
111
+ // ============================================================
112
+
113
+ /**
114
+ * Optimized expression evaluator with caching and memoization
115
+ */
116
+ export class OptimizedExpressionEvaluator {
117
+ private resultCache = new LRUCache<any>(500);
118
+ private dependencyCache = new LRUCache<Set<string>>(200);
119
+ private compiledExpressions = new Map<string, Function>();
120
+
121
+ /**
122
+ * Create cache key from expression and context
123
+ */
124
+ private createCacheKey(
125
+ expression: ExpressionTree,
126
+ context: Record<string, any>
127
+ ): string {
128
+ const expressionHash = JSON.stringify(expression);
129
+ const contextHash = JSON.stringify(context);
130
+ return `${expressionHash}:${contextHash}`;
131
+ }
132
+
133
+ /**
134
+ * Get expression dependencies (cached)
135
+ */
136
+ getDependencies(expression: ExpressionTree): Set<string> {
137
+ const expressionKey = JSON.stringify(expression);
138
+
139
+ let dependencies = this.dependencyCache.get(expressionKey);
140
+ if (!dependencies) {
141
+ dependencies = analyzeExpressionDependencies(expression);
142
+ this.dependencyCache.set(expressionKey, dependencies);
143
+ }
144
+
145
+ return dependencies;
146
+ }
147
+
148
+ /**
149
+ * Check if expression result is cached and context hasn't changed
150
+ */
151
+ private getCachedResult(
152
+ expression: ExpressionTree,
153
+ context: Record<string, any>,
154
+ lastContext?: Record<string, any>
155
+ ): any | undefined {
156
+ if (!lastContext) return undefined;
157
+
158
+ const dependencies = this.getDependencies(expression);
159
+
160
+ // Check if any dependency has changed
161
+ for (const dep of dependencies) {
162
+ if (context[dep] !== lastContext[dep]) {
163
+ return undefined; // Dependencies changed, cache invalid
164
+ }
165
+ }
166
+
167
+ // Dependencies unchanged, try cache
168
+ const cacheKey = this.createCacheKey(expression, context);
169
+ return this.resultCache.get(cacheKey);
170
+ }
171
+
172
+ /**
173
+ * Evaluate expression with caching
174
+ */
175
+ evaluate(
176
+ expression: ExpressionTree,
177
+ context: Record<string, any>,
178
+ lastContext?: Record<string, any>
179
+ ): any {
180
+ // Try cached result
181
+ const cached = this.getCachedResult(expression, context, lastContext);
182
+ if (cached !== undefined) {
183
+ return cached;
184
+ }
185
+
186
+ // Evaluate and cache result
187
+ const result = this.evaluateNode(expression, context);
188
+ const cacheKey = this.createCacheKey(expression, context);
189
+ this.resultCache.set(cacheKey, result);
190
+
191
+ return result;
192
+ }
193
+
194
+ /**
195
+ * Core expression evaluation logic
196
+ */
197
+ private evaluateNode(node: ExpressionTree, context: Record<string, any>): any {
198
+ switch (node.Type) {
199
+ case "Literal":
200
+ return node.Value;
201
+
202
+ case "Identifier":
203
+ return this.getIdentifierValue(node, context);
204
+
205
+ case "BinaryExpression":
206
+ return this.evaluateBinaryExpression(node, context);
207
+
208
+ case "LogicalExpression":
209
+ return this.evaluateLogicalExpression(node, context);
210
+
211
+ case "CallExpression":
212
+ return this.evaluateCallExpression(node, context);
213
+
214
+ case "MemberExpression":
215
+ return this.evaluateMemberExpression(node, context);
216
+
217
+ default:
218
+ throw new Error(`Unsupported expression type: ${node.Type}`);
219
+ }
220
+ }
221
+
222
+ /**
223
+ * Get identifier value with system context support
224
+ */
225
+ private getIdentifierValue(node: ExpressionTree, context: Record<string, any>): any {
226
+ if (!node.Name) return undefined;
227
+
228
+ // System identifiers
229
+ if (node.Name === "NOW") return new Date();
230
+ if (node.Name === "TODAY") {
231
+ const today = new Date();
232
+ return new Date(today.getFullYear(), today.getMonth(), today.getDate());
233
+ }
234
+ if (node.Name === "CURRENT_USER_ID") return 1; // Would come from auth context
235
+ if (node.Name === "CURRENT_USER") {
236
+ return {
237
+ EmpId: 1,
238
+ Email: "user@example.com",
239
+ FirstName: "John",
240
+ LastName: "Doe",
241
+ Role: "User",
242
+ };
243
+ }
244
+
245
+ // Form field values
246
+ return context[node.Name];
247
+ }
248
+
249
+ /**
250
+ * Evaluate binary expressions with type coercion
251
+ */
252
+ private evaluateBinaryExpression(node: ExpressionTree, context: Record<string, any>): any {
253
+ if (!node.Arguments || node.Arguments.length !== 2) {
254
+ throw new Error("Binary expression requires exactly 2 arguments");
255
+ }
256
+
257
+ const left = this.evaluateNode(node.Arguments[0], context);
258
+ const right = this.evaluateNode(node.Arguments[1], context);
259
+
260
+ switch (node.Operator) {
261
+ case "==": return left == right;
262
+ case "!=": return left != right;
263
+ case "===": return left === right;
264
+ case "!==": return left !== right;
265
+ case "<": return Number(left) < Number(right);
266
+ case "<=": return Number(left) <= Number(right);
267
+ case ">": return Number(left) > Number(right);
268
+ case ">=": return Number(left) >= Number(right);
269
+ case "+": return Number(left) + Number(right);
270
+ case "-": return Number(left) - Number(right);
271
+ case "*": return Number(left) * Number(right);
272
+ case "/": return Number(left) / Number(right);
273
+ case "%": return Number(left) % Number(right);
274
+ default:
275
+ throw new Error(`Unsupported binary operator: ${node.Operator}`);
276
+ }
277
+ }
278
+
279
+ /**
280
+ * Evaluate logical expressions with short-circuiting
281
+ */
282
+ private evaluateLogicalExpression(node: ExpressionTree, context: Record<string, any>): any {
283
+ if (!node.Arguments || node.Arguments.length < 2) {
284
+ throw new Error("Logical expression requires at least 2 arguments");
285
+ }
286
+
287
+ switch (node.Operator) {
288
+ case "AND":
289
+ // Short-circuit: return false on first falsy value
290
+ for (const arg of node.Arguments) {
291
+ const result = this.evaluateNode(arg, context);
292
+ if (!result) return false;
293
+ }
294
+ return true;
295
+
296
+ case "OR":
297
+ // Short-circuit: return true on first truthy value
298
+ for (const arg of node.Arguments) {
299
+ const result = this.evaluateNode(arg, context);
300
+ if (result) return true;
301
+ }
302
+ return false;
303
+
304
+ default:
305
+ throw new Error(`Unsupported logical operator: ${node.Operator}`);
306
+ }
307
+ }
308
+
309
+ /**
310
+ * Evaluate function calls with built-in functions
311
+ */
312
+ private evaluateCallExpression(node: ExpressionTree, context: Record<string, any>): any {
313
+ if (!node.Callee) {
314
+ throw new Error("Call expression requires a function name");
315
+ }
316
+
317
+ const args = node.Arguments?.map(arg => this.evaluateNode(arg, context)) || [];
318
+
319
+ switch (node.Callee) {
320
+ // String functions
321
+ case "CONCAT": return args.map(a => String(a || "")).join("");
322
+ case "TRIM": return String(args[0] || "").trim();
323
+ case "LENGTH": return String(args[0] || "").length;
324
+ case "UPPER": return String(args[0] || "").toUpperCase();
325
+ case "LOWER": return String(args[0] || "").toLowerCase();
326
+ case "CONTAINS": return String(args[0] || "").includes(String(args[1] || ""));
327
+ case "MATCHES": return new RegExp(String(args[1])).test(String(args[0] || ""));
328
+
329
+ // Math functions
330
+ case "SUM": return args.reduce((sum, val) => sum + (Number(val) || 0), 0);
331
+ case "AVG":
332
+ const nums = args.filter(val => !isNaN(Number(val)));
333
+ return nums.length > 0 ? nums.reduce((sum, val) => sum + Number(val), 0) / nums.length : 0;
334
+ case "MIN": return Math.min(...args.map(val => Number(val) || 0));
335
+ case "MAX": return Math.max(...args.map(val => Number(val) || 0));
336
+ case "ROUND": return Math.round(Number(args[0]) || 0);
337
+ case "FLOOR": return Math.floor(Number(args[0]) || 0);
338
+ case "CEIL": return Math.ceil(Number(args[0]) || 0);
339
+ case "ABS": return Math.abs(Number(args[0]) || 0);
340
+
341
+ // Date functions
342
+ case "YEAR": return new Date(args[0]).getFullYear();
343
+ case "MONTH": return new Date(args[0]).getMonth() + 1;
344
+ case "DAY": return new Date(args[0]).getDate();
345
+ case "DATE_DIFF":
346
+ const d1 = new Date(args[0]);
347
+ const d2 = new Date(args[1]);
348
+ const diffTime = Math.abs(d1.getTime() - d2.getTime());
349
+ return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
350
+
351
+ // Conditional functions
352
+ case "IF": return args[0] ? args[1] : args[2];
353
+ case "AUTO_NUMBER": return Math.floor(Math.random() * 10000);
354
+
355
+ default:
356
+ throw new Error(`Unknown function: ${node.Callee}`);
357
+ }
358
+ }
359
+
360
+ /**
361
+ * Evaluate member expressions
362
+ */
363
+ private evaluateMemberExpression(node: ExpressionTree, context: Record<string, any>): any {
364
+ if (!node.Arguments || node.Arguments.length === 0) {
365
+ throw new Error("Member expression requires arguments");
366
+ }
367
+
368
+ const object = this.evaluateNode(node.Arguments[0], context);
369
+ const propertyName = node.Arguments[0].Property?.Name;
370
+
371
+ if (propertyName && object && typeof object === 'object') {
372
+ return object[propertyName];
373
+ }
374
+
375
+ return object;
376
+ }
377
+
378
+ /**
379
+ * Clear all caches
380
+ */
381
+ clearCache(): void {
382
+ this.resultCache.clear();
383
+ this.dependencyCache.clear();
384
+ this.compiledExpressions.clear();
385
+ }
386
+ }
387
+
388
+ // ============================================================
389
+ // OPTIMIZED VALIDATION FUNCTIONS
390
+ // ============================================================
391
+
392
+ // Global evaluator instance
393
+ const globalEvaluator = new OptimizedExpressionEvaluator();
394
+
395
+ /**
396
+ * Optimized field validation with caching
397
+ */
398
+ export function validateFieldOptimized<T = Record<string, any>>(
399
+ fieldName: string,
400
+ fieldValue: any,
401
+ validationRules: ValidationRule[],
402
+ formValues: T,
403
+ lastFormValues?: T
404
+ ): ValidationResult<T> {
405
+ if (!validationRules || validationRules.length === 0) {
406
+ return { isValid: true };
407
+ }
408
+
409
+ const currentFormValues = { ...formValues, [fieldName]: fieldValue };
410
+
411
+ for (const rule of validationRules) {
412
+ try {
413
+ const isValid = globalEvaluator.evaluate(
414
+ rule.ExpressionTree,
415
+ currentFormValues,
416
+ lastFormValues as any
417
+ );
418
+
419
+ if (!isValid) {
420
+ return {
421
+ isValid: false,
422
+ message: rule.Message || `Validation failed for ${rule.Name}`,
423
+ fieldName: fieldName as keyof T,
424
+ };
425
+ }
426
+ } catch (error) {
427
+ console.warn(`Validation rule ${rule.Id} failed to evaluate:`, error);
428
+ }
429
+ }
430
+
431
+ return { isValid: true };
432
+ }
433
+
434
+ /**
435
+ * Optimized computed value calculation
436
+ */
437
+ export function calculateComputedValueOptimized(
438
+ expression: ExpressionTree,
439
+ formValues: Record<string, any>,
440
+ lastFormValues?: Record<string, any>
441
+ ): any {
442
+ try {
443
+ return globalEvaluator.evaluate(expression, formValues, lastFormValues);
444
+ } catch (error) {
445
+ console.warn("Failed to calculate computed value:", error);
446
+ return undefined;
447
+ }
448
+ }
449
+
450
+ /**
451
+ * Get field dependencies for optimized watching
452
+ */
453
+ export function getFieldDependencies(expression: ExpressionTree): string[] {
454
+ return Array.from(globalEvaluator.getDependencies(expression));
455
+ }
456
+
457
+ /**
458
+ * Batch validate multiple fields efficiently
459
+ */
460
+ export function batchValidateFields<T = Record<string, any>>(
461
+ validations: Array<{
462
+ fieldName: string;
463
+ fieldValue: any;
464
+ rules: ValidationRule[];
465
+ }>,
466
+ formValues: T,
467
+ lastFormValues?: T
468
+ ): Array<ValidationResult<T>> {
469
+ return validations.map(({ fieldName, fieldValue, rules }) =>
470
+ validateFieldOptimized(fieldName, fieldValue, rules, formValues, lastFormValues)
471
+ );
472
+ }
473
+
474
+ /**
475
+ * Clear global expression cache
476
+ */
477
+ export function clearExpressionCache(): void {
478
+ globalEvaluator.clearCache();
479
+ }
480
+
481
+ // Export the evaluator for advanced usage
482
+ export { globalEvaluator as expressionEvaluator };