@object-ui/core 3.3.0 → 3.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.
Files changed (99) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +20 -1
  3. package/dist/actions/ActionRunner.d.ts +9 -0
  4. package/dist/actions/ActionRunner.js +41 -4
  5. package/dist/adapters/ValueDataSource.js +3 -1
  6. package/dist/utils/filter-converter.js +25 -5
  7. package/package.json +32 -8
  8. package/.turbo/turbo-build.log +0 -4
  9. package/src/__benchmarks__/core.bench.ts +0 -64
  10. package/src/__tests__/protocols/DndProtocol.test.ts +0 -186
  11. package/src/__tests__/protocols/KeyboardProtocol.test.ts +0 -177
  12. package/src/__tests__/protocols/NotificationProtocol.test.ts +0 -142
  13. package/src/__tests__/protocols/ResponsiveProtocol.test.ts +0 -176
  14. package/src/__tests__/protocols/SharingProtocol.test.ts +0 -188
  15. package/src/actions/ActionEngine.ts +0 -268
  16. package/src/actions/ActionRunner.ts +0 -717
  17. package/src/actions/TransactionManager.ts +0 -521
  18. package/src/actions/UndoManager.ts +0 -215
  19. package/src/actions/__tests__/ActionEngine.test.ts +0 -206
  20. package/src/actions/__tests__/ActionRunner.params.test.ts +0 -134
  21. package/src/actions/__tests__/ActionRunner.test.ts +0 -711
  22. package/src/actions/__tests__/TransactionManager.test.ts +0 -447
  23. package/src/actions/__tests__/UndoManager.test.ts +0 -320
  24. package/src/actions/index.ts +0 -12
  25. package/src/adapters/ApiDataSource.ts +0 -376
  26. package/src/adapters/README.md +0 -180
  27. package/src/adapters/ValueDataSource.ts +0 -459
  28. package/src/adapters/__tests__/ApiDataSource.test.ts +0 -418
  29. package/src/adapters/__tests__/ValueDataSource.test.ts +0 -571
  30. package/src/adapters/__tests__/resolveDataSource.test.ts +0 -144
  31. package/src/adapters/index.ts +0 -15
  32. package/src/adapters/resolveDataSource.ts +0 -79
  33. package/src/builder/__tests__/schema-builder.test.ts +0 -235
  34. package/src/builder/schema-builder.ts +0 -584
  35. package/src/data-scope/DataScopeManager.ts +0 -269
  36. package/src/data-scope/ViewDataProvider.ts +0 -282
  37. package/src/data-scope/__tests__/DataScopeManager.test.ts +0 -211
  38. package/src/data-scope/__tests__/ViewDataProvider.test.ts +0 -270
  39. package/src/data-scope/index.ts +0 -24
  40. package/src/errors/__tests__/errors.test.ts +0 -292
  41. package/src/errors/index.ts +0 -269
  42. package/src/evaluator/ExpressionCache.ts +0 -206
  43. package/src/evaluator/ExpressionContext.ts +0 -118
  44. package/src/evaluator/ExpressionEvaluator.ts +0 -315
  45. package/src/evaluator/FormulaFunctions.ts +0 -398
  46. package/src/evaluator/SafeExpressionParser.ts +0 -893
  47. package/src/evaluator/__tests__/ExpressionCache.test.ts +0 -135
  48. package/src/evaluator/__tests__/ExpressionContext.test.ts +0 -110
  49. package/src/evaluator/__tests__/ExpressionEvaluator.test.ts +0 -558
  50. package/src/evaluator/__tests__/FormulaFunctions.test.ts +0 -447
  51. package/src/evaluator/index.ts +0 -13
  52. package/src/index.ts +0 -38
  53. package/src/protocols/DndProtocol.ts +0 -168
  54. package/src/protocols/KeyboardProtocol.ts +0 -181
  55. package/src/protocols/NotificationProtocol.ts +0 -150
  56. package/src/protocols/ResponsiveProtocol.ts +0 -210
  57. package/src/protocols/SharingProtocol.ts +0 -185
  58. package/src/protocols/index.ts +0 -13
  59. package/src/query/__tests__/query-ast.test.ts +0 -211
  60. package/src/query/__tests__/window-functions.test.ts +0 -275
  61. package/src/query/index.ts +0 -7
  62. package/src/query/query-ast.ts +0 -341
  63. package/src/registry/PluginScopeImpl.ts +0 -259
  64. package/src/registry/PluginSystem.ts +0 -206
  65. package/src/registry/Registry.ts +0 -219
  66. package/src/registry/WidgetRegistry.ts +0 -316
  67. package/src/registry/__tests__/PluginSystem.test.ts +0 -309
  68. package/src/registry/__tests__/Registry.test.ts +0 -293
  69. package/src/registry/__tests__/WidgetRegistry.test.ts +0 -321
  70. package/src/registry/__tests__/plugin-scope-integration.test.ts +0 -283
  71. package/src/theme/ThemeEngine.ts +0 -530
  72. package/src/theme/__tests__/ThemeEngine.test.ts +0 -668
  73. package/src/theme/index.ts +0 -24
  74. package/src/types/index.ts +0 -21
  75. package/src/utils/__tests__/debug-collector.test.ts +0 -102
  76. package/src/utils/__tests__/debug.test.ts +0 -134
  77. package/src/utils/__tests__/expand-fields.test.ts +0 -120
  78. package/src/utils/__tests__/extract-records.test.ts +0 -50
  79. package/src/utils/__tests__/filter-converter.test.ts +0 -118
  80. package/src/utils/__tests__/merge-views-into-objects.test.ts +0 -110
  81. package/src/utils/__tests__/normalize-quick-filter.test.ts +0 -123
  82. package/src/utils/debug-collector.ts +0 -100
  83. package/src/utils/debug.ts +0 -148
  84. package/src/utils/expand-fields.ts +0 -76
  85. package/src/utils/extract-records.ts +0 -33
  86. package/src/utils/filter-converter.ts +0 -133
  87. package/src/utils/merge-views-into-objects.ts +0 -36
  88. package/src/utils/normalize-quick-filter.ts +0 -78
  89. package/src/validation/__tests__/object-validation-engine.test.ts +0 -567
  90. package/src/validation/__tests__/schema-validator.test.ts +0 -118
  91. package/src/validation/__tests__/validation-engine.test.ts +0 -102
  92. package/src/validation/index.ts +0 -10
  93. package/src/validation/schema-validator.ts +0 -344
  94. package/src/validation/validation-engine.ts +0 -528
  95. package/src/validation/validators/index.ts +0 -25
  96. package/src/validation/validators/object-validation-engine.ts +0 -722
  97. package/tsconfig.json +0 -15
  98. package/tsconfig.tsbuildinfo +0 -1
  99. package/vitest.config.ts +0 -2
@@ -1,398 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
-
9
- /**
10
- * @object-ui/core - Formula Functions
11
- *
12
- * Built-in formula functions for the expression engine.
13
- * Provides aggregation, date, logic, and string functions
14
- * compatible with low-code platform expression evaluation.
15
- *
16
- * @module evaluator
17
- * @packageDocumentation
18
- */
19
-
20
- /**
21
- * A formula function that can be registered with the expression evaluator
22
- */
23
- export type FormulaFunction = (...args: any[]) => any;
24
-
25
- /**
26
- * Registry of built-in formula functions
27
- */
28
- export class FormulaFunctions {
29
- private functions = new Map<string, FormulaFunction>();
30
-
31
- constructor() {
32
- this.registerDefaults();
33
- }
34
-
35
- /**
36
- * Register a custom formula function
37
- */
38
- register(name: string, fn: FormulaFunction): void {
39
- this.functions.set(name.toUpperCase(), fn);
40
- }
41
-
42
- /**
43
- * Get a formula function by name
44
- */
45
- get(name: string): FormulaFunction | undefined {
46
- return this.functions.get(name.toUpperCase());
47
- }
48
-
49
- /**
50
- * Check if a function is registered
51
- */
52
- has(name: string): boolean {
53
- return this.functions.has(name.toUpperCase());
54
- }
55
-
56
- /**
57
- * Get all registered function names
58
- */
59
- getNames(): string[] {
60
- return Array.from(this.functions.keys());
61
- }
62
-
63
- /**
64
- * Get all functions as a plain object (for injection into expression context)
65
- */
66
- toObject(): Record<string, FormulaFunction> {
67
- const result: Record<string, FormulaFunction> = {};
68
- for (const [name, fn] of this.functions) {
69
- result[name] = fn;
70
- }
71
- return result;
72
- }
73
-
74
- /**
75
- * Register all default built-in functions
76
- */
77
- private registerDefaults(): void {
78
- this.registerAggregationFunctions();
79
- this.registerDateFunctions();
80
- this.registerLogicFunctions();
81
- this.registerStringFunctions();
82
- this.registerStringSearchFunctions();
83
- this.registerStatisticalFunctions();
84
- }
85
-
86
- // ==========================================================================
87
- // Aggregation Functions
88
- // ==========================================================================
89
-
90
- private registerAggregationFunctions(): void {
91
- this.register('SUM', (...args: any[]): number => {
92
- const values = flattenNumericArgs(args);
93
- return values.reduce((sum, v) => sum + v, 0);
94
- });
95
-
96
- this.register('AVG', (...args: any[]): number => {
97
- const values = flattenNumericArgs(args);
98
- if (values.length === 0) return 0;
99
- return values.reduce((sum, v) => sum + v, 0) / values.length;
100
- });
101
-
102
- this.register('COUNT', (...args: any[]): number => {
103
- const values = flattenArgs(args);
104
- return values.filter(v => v != null).length;
105
- });
106
-
107
- this.register('MIN', (...args: any[]): number => {
108
- const values = flattenNumericArgs(args);
109
- if (values.length === 0) return 0;
110
- return Math.min(...values);
111
- });
112
-
113
- this.register('MAX', (...args: any[]): number => {
114
- const values = flattenNumericArgs(args);
115
- if (values.length === 0) return 0;
116
- return Math.max(...values);
117
- });
118
- }
119
-
120
- // ==========================================================================
121
- // Date Functions
122
- // ==========================================================================
123
-
124
- private registerDateFunctions(): void {
125
- this.register('TODAY', (): string => {
126
- const now = new Date();
127
- return now.toISOString().split('T')[0];
128
- });
129
-
130
- this.register('NOW', (): string => {
131
- return new Date().toISOString();
132
- });
133
-
134
- this.register('DATEADD', (dateStr: string, amount: number, unit: string): string => {
135
- const date = new Date(dateStr);
136
- if (isNaN(date.getTime())) {
137
- throw new Error(`DATEADD: Invalid date "${dateStr}"`);
138
- }
139
- const normalizedUnit = String(unit).toLowerCase();
140
- switch (normalizedUnit) {
141
- case 'day':
142
- case 'days':
143
- date.setDate(date.getDate() + amount);
144
- break;
145
- case 'month':
146
- case 'months':
147
- date.setMonth(date.getMonth() + amount);
148
- break;
149
- case 'year':
150
- case 'years':
151
- date.setFullYear(date.getFullYear() + amount);
152
- break;
153
- case 'hour':
154
- case 'hours':
155
- date.setHours(date.getHours() + amount);
156
- break;
157
- case 'minute':
158
- case 'minutes':
159
- date.setMinutes(date.getMinutes() + amount);
160
- break;
161
- default:
162
- throw new Error(`DATEADD: Unsupported unit "${unit}"`);
163
- }
164
- return date.toISOString();
165
- });
166
-
167
- this.register('DATEDIFF', (dateStr1: string, dateStr2: string, unit: string): number => {
168
- const date1 = new Date(dateStr1);
169
- const date2 = new Date(dateStr2);
170
- if (isNaN(date1.getTime())) {
171
- throw new Error(`DATEDIFF: Invalid date "${dateStr1}"`);
172
- }
173
- if (isNaN(date2.getTime())) {
174
- throw new Error(`DATEDIFF: Invalid date "${dateStr2}"`);
175
- }
176
- const diffMs = date2.getTime() - date1.getTime();
177
- const normalizedUnit = String(unit).toLowerCase();
178
- switch (normalizedUnit) {
179
- case 'day':
180
- case 'days':
181
- return Math.floor(diffMs / (1000 * 60 * 60 * 24));
182
- case 'month':
183
- case 'months':
184
- return (date2.getFullYear() - date1.getFullYear()) * 12 + (date2.getMonth() - date1.getMonth());
185
- case 'year':
186
- case 'years':
187
- return date2.getFullYear() - date1.getFullYear();
188
- case 'hour':
189
- case 'hours':
190
- return Math.floor(diffMs / (1000 * 60 * 60));
191
- case 'minute':
192
- case 'minutes':
193
- return Math.floor(diffMs / (1000 * 60));
194
- default:
195
- throw new Error(`DATEDIFF: Unsupported unit "${unit}"`);
196
- }
197
- });
198
-
199
- this.register('DATEFORMAT', (dateStr: string, format: string): string => {
200
- const date = new Date(dateStr);
201
- if (isNaN(date.getTime())) {
202
- throw new Error(`DATEFORMAT: Invalid date "${dateStr}"`);
203
- }
204
- const pad = (n: number, len = 2) => String(n).padStart(len, '0');
205
- return format
206
- .replace('YYYY', String(date.getFullYear()))
207
- .replace('YY', String(date.getFullYear()).slice(-2))
208
- .replace('MM', pad(date.getMonth() + 1))
209
- .replace('DD', pad(date.getDate()))
210
- .replace('HH', pad(date.getHours()))
211
- .replace('mm', pad(date.getMinutes()))
212
- .replace('ss', pad(date.getSeconds()));
213
- });
214
- }
215
-
216
- // ==========================================================================
217
- // Logic Functions
218
- // ==========================================================================
219
-
220
- private registerLogicFunctions(): void {
221
- this.register('IF', (condition: any, trueValue: any, falseValue: any): any => {
222
- return condition ? trueValue : falseValue;
223
- });
224
-
225
- this.register('AND', (...args: any[]): boolean => {
226
- return args.every(Boolean);
227
- });
228
-
229
- this.register('OR', (...args: any[]): boolean => {
230
- return args.some(Boolean);
231
- });
232
-
233
- this.register('NOT', (value: any): boolean => {
234
- return !value;
235
- });
236
-
237
- this.register('SWITCH', (expr: any, ...cases: any[]): any => {
238
- // SWITCH(expr, val1, result1, val2, result2, ..., defaultResult)
239
- for (let i = 0; i < cases.length - 1; i += 2) {
240
- if (expr === cases[i]) {
241
- return cases[i + 1];
242
- }
243
- }
244
- // Return default value if odd number of case args
245
- if (cases.length % 2 === 1) {
246
- return cases[cases.length - 1];
247
- }
248
- return undefined;
249
- });
250
- }
251
-
252
- // ==========================================================================
253
- // String Functions
254
- // ==========================================================================
255
-
256
- private registerStringFunctions(): void {
257
- this.register('CONCAT', (...args: any[]): string => {
258
- return args.map(a => String(a ?? '')).join('');
259
- });
260
-
261
- this.register('LEFT', (text: string, count: number): string => {
262
- return String(text ?? '').substring(0, count);
263
- });
264
-
265
- this.register('RIGHT', (text: string, count: number): string => {
266
- const str = String(text ?? '');
267
- return str.substring(Math.max(0, str.length - count));
268
- });
269
-
270
- this.register('TRIM', (text: string): string => {
271
- return String(text ?? '').trim();
272
- });
273
-
274
- this.register('UPPER', (text: string): string => {
275
- return String(text ?? '').toUpperCase();
276
- });
277
-
278
- this.register('LOWER', (text: string): string => {
279
- return String(text ?? '').toLowerCase();
280
- });
281
- }
282
-
283
- // ==========================================================================
284
- // String Search Functions
285
- // ==========================================================================
286
-
287
- private registerStringSearchFunctions(): void {
288
- this.register('FIND', (search: string, text: string, startPos?: number): number => {
289
- const str = String(text ?? '');
290
- const idx = str.indexOf(String(search ?? ''), startPos ?? 0);
291
- return idx;
292
- });
293
-
294
- this.register('REPLACE', (text: string, search: string, replacement: string): string => {
295
- const str = String(text ?? '');
296
- return str.split(String(search ?? '')).join(String(replacement ?? ''));
297
- });
298
-
299
- this.register('SUBSTRING', (text: string, start: number, length?: number): string => {
300
- const str = String(text ?? '');
301
- if (length !== undefined) {
302
- return str.substring(start, start + length);
303
- }
304
- return str.substring(start);
305
- });
306
-
307
- this.register('REGEX', (text: string, pattern: string, flags?: string): boolean => {
308
- const str = String(text ?? '');
309
- const regex = new RegExp(pattern, flags);
310
- return regex.test(str);
311
- });
312
-
313
- this.register('LEN', (text: string): number => {
314
- return String(text ?? '').length;
315
- });
316
- }
317
-
318
- // ==========================================================================
319
- // Statistical Functions
320
- // ==========================================================================
321
-
322
- private registerStatisticalFunctions(): void {
323
- this.register('MEDIAN', (...args: any[]): number => {
324
- const values = flattenNumericArgs(args).sort((a, b) => a - b);
325
- if (values.length === 0) return 0;
326
- const mid = Math.floor(values.length / 2);
327
- return values.length % 2 !== 0
328
- ? values[mid]
329
- : (values[mid - 1] + values[mid]) / 2;
330
- });
331
-
332
- this.register('STDEV', (...args: any[]): number => {
333
- const values = flattenNumericArgs(args);
334
- if (values.length < 2) return 0;
335
- const mean = values.reduce((sum, v) => sum + v, 0) / values.length;
336
- const squaredDiffs = values.map(v => (v - mean) ** 2);
337
- const variance = squaredDiffs.reduce((sum, v) => sum + v, 0) / (values.length - 1);
338
- return Math.sqrt(variance);
339
- });
340
-
341
- this.register('VARIANCE', (...args: any[]): number => {
342
- const values = flattenNumericArgs(args);
343
- if (values.length < 2) return 0;
344
- const mean = values.reduce((sum, v) => sum + v, 0) / values.length;
345
- const squaredDiffs = values.map(v => (v - mean) ** 2);
346
- return squaredDiffs.reduce((sum, v) => sum + v, 0) / (values.length - 1);
347
- });
348
-
349
- this.register('PERCENTILE', (percentile: number, ...args: any[]): number => {
350
- const values = flattenNumericArgs(args).sort((a, b) => a - b);
351
- if (values.length === 0) return 0;
352
- const p = Math.max(0, Math.min(100, percentile)) / 100;
353
- const index = p * (values.length - 1);
354
- const lower = Math.floor(index);
355
- const upper = Math.ceil(index);
356
- if (lower === upper) return values[lower];
357
- const fraction = index - lower;
358
- return values[lower] + fraction * (values[upper] - values[lower]);
359
- });
360
- }
361
- }
362
-
363
- // ==========================================================================
364
- // Helpers
365
- // ==========================================================================
366
-
367
- /**
368
- * Flatten nested arrays and extract numeric values
369
- */
370
- function flattenNumericArgs(args: any[]): number[] {
371
- const result: number[] = [];
372
- for (const arg of args) {
373
- if (Array.isArray(arg)) {
374
- result.push(...flattenNumericArgs(arg));
375
- } else {
376
- const num = Number(arg);
377
- if (!isNaN(num)) {
378
- result.push(num);
379
- }
380
- }
381
- }
382
- return result;
383
- }
384
-
385
- /**
386
- * Flatten nested arrays
387
- */
388
- function flattenArgs(args: any[]): any[] {
389
- const result: any[] = [];
390
- for (const arg of args) {
391
- if (Array.isArray(arg)) {
392
- result.push(...flattenArgs(arg));
393
- } else {
394
- result.push(arg);
395
- }
396
- }
397
- return result;
398
- }