@object-ui/core 3.1.5 → 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 (110) hide show
  1. package/CHANGELOG.md +18 -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.d.ts +5 -1
  6. package/dist/adapters/ValueDataSource.js +30 -1
  7. package/dist/errors/index.js +2 -3
  8. package/dist/evaluator/ExpressionCache.d.ts +9 -10
  9. package/dist/evaluator/ExpressionCache.js +29 -8
  10. package/dist/evaluator/SafeExpressionParser.d.ts +131 -0
  11. package/dist/evaluator/SafeExpressionParser.js +851 -0
  12. package/dist/evaluator/index.d.ts +1 -0
  13. package/dist/evaluator/index.js +1 -0
  14. package/dist/protocols/DndProtocol.js +2 -14
  15. package/dist/protocols/KeyboardProtocol.js +1 -4
  16. package/dist/protocols/NotificationProtocol.js +3 -13
  17. package/dist/utils/debug.js +2 -1
  18. package/dist/utils/filter-converter.js +25 -5
  19. package/package.json +33 -9
  20. package/.turbo/turbo-build.log +0 -4
  21. package/src/__benchmarks__/core.bench.ts +0 -64
  22. package/src/__tests__/protocols/DndProtocol.test.ts +0 -186
  23. package/src/__tests__/protocols/KeyboardProtocol.test.ts +0 -177
  24. package/src/__tests__/protocols/NotificationProtocol.test.ts +0 -142
  25. package/src/__tests__/protocols/ResponsiveProtocol.test.ts +0 -176
  26. package/src/__tests__/protocols/SharingProtocol.test.ts +0 -188
  27. package/src/actions/ActionEngine.ts +0 -268
  28. package/src/actions/ActionRunner.ts +0 -717
  29. package/src/actions/TransactionManager.ts +0 -521
  30. package/src/actions/UndoManager.ts +0 -215
  31. package/src/actions/__tests__/ActionEngine.test.ts +0 -206
  32. package/src/actions/__tests__/ActionRunner.params.test.ts +0 -134
  33. package/src/actions/__tests__/ActionRunner.test.ts +0 -711
  34. package/src/actions/__tests__/TransactionManager.test.ts +0 -447
  35. package/src/actions/__tests__/UndoManager.test.ts +0 -320
  36. package/src/actions/index.ts +0 -12
  37. package/src/adapters/ApiDataSource.ts +0 -376
  38. package/src/adapters/README.md +0 -180
  39. package/src/adapters/ValueDataSource.ts +0 -438
  40. package/src/adapters/__tests__/ApiDataSource.test.ts +0 -418
  41. package/src/adapters/__tests__/ValueDataSource.test.ts +0 -472
  42. package/src/adapters/__tests__/resolveDataSource.test.ts +0 -144
  43. package/src/adapters/index.ts +0 -15
  44. package/src/adapters/resolveDataSource.ts +0 -79
  45. package/src/builder/__tests__/schema-builder.test.ts +0 -235
  46. package/src/builder/schema-builder.ts +0 -584
  47. package/src/data-scope/DataScopeManager.ts +0 -269
  48. package/src/data-scope/ViewDataProvider.ts +0 -282
  49. package/src/data-scope/__tests__/DataScopeManager.test.ts +0 -211
  50. package/src/data-scope/__tests__/ViewDataProvider.test.ts +0 -270
  51. package/src/data-scope/index.ts +0 -24
  52. package/src/errors/__tests__/errors.test.ts +0 -292
  53. package/src/errors/index.ts +0 -270
  54. package/src/evaluator/ExpressionCache.ts +0 -192
  55. package/src/evaluator/ExpressionContext.ts +0 -118
  56. package/src/evaluator/ExpressionEvaluator.ts +0 -315
  57. package/src/evaluator/FormulaFunctions.ts +0 -398
  58. package/src/evaluator/__tests__/ExpressionCache.test.ts +0 -135
  59. package/src/evaluator/__tests__/ExpressionContext.test.ts +0 -110
  60. package/src/evaluator/__tests__/ExpressionEvaluator.test.ts +0 -131
  61. package/src/evaluator/__tests__/FormulaFunctions.test.ts +0 -447
  62. package/src/evaluator/index.ts +0 -12
  63. package/src/index.ts +0 -38
  64. package/src/protocols/DndProtocol.ts +0 -184
  65. package/src/protocols/KeyboardProtocol.ts +0 -185
  66. package/src/protocols/NotificationProtocol.ts +0 -159
  67. package/src/protocols/ResponsiveProtocol.ts +0 -210
  68. package/src/protocols/SharingProtocol.ts +0 -185
  69. package/src/protocols/index.ts +0 -13
  70. package/src/query/__tests__/query-ast.test.ts +0 -211
  71. package/src/query/__tests__/window-functions.test.ts +0 -275
  72. package/src/query/index.ts +0 -7
  73. package/src/query/query-ast.ts +0 -341
  74. package/src/registry/PluginScopeImpl.ts +0 -259
  75. package/src/registry/PluginSystem.ts +0 -206
  76. package/src/registry/Registry.ts +0 -219
  77. package/src/registry/WidgetRegistry.ts +0 -316
  78. package/src/registry/__tests__/PluginSystem.test.ts +0 -309
  79. package/src/registry/__tests__/Registry.test.ts +0 -293
  80. package/src/registry/__tests__/WidgetRegistry.test.ts +0 -321
  81. package/src/registry/__tests__/plugin-scope-integration.test.ts +0 -283
  82. package/src/theme/ThemeEngine.ts +0 -530
  83. package/src/theme/__tests__/ThemeEngine.test.ts +0 -668
  84. package/src/theme/index.ts +0 -24
  85. package/src/types/index.ts +0 -21
  86. package/src/utils/__tests__/debug-collector.test.ts +0 -102
  87. package/src/utils/__tests__/debug.test.ts +0 -134
  88. package/src/utils/__tests__/expand-fields.test.ts +0 -120
  89. package/src/utils/__tests__/extract-records.test.ts +0 -50
  90. package/src/utils/__tests__/filter-converter.test.ts +0 -118
  91. package/src/utils/__tests__/merge-views-into-objects.test.ts +0 -110
  92. package/src/utils/__tests__/normalize-quick-filter.test.ts +0 -123
  93. package/src/utils/debug-collector.ts +0 -100
  94. package/src/utils/debug.ts +0 -147
  95. package/src/utils/expand-fields.ts +0 -76
  96. package/src/utils/extract-records.ts +0 -33
  97. package/src/utils/filter-converter.ts +0 -133
  98. package/src/utils/merge-views-into-objects.ts +0 -36
  99. package/src/utils/normalize-quick-filter.ts +0 -78
  100. package/src/validation/__tests__/object-validation-engine.test.ts +0 -567
  101. package/src/validation/__tests__/schema-validator.test.ts +0 -118
  102. package/src/validation/__tests__/validation-engine.test.ts +0 -102
  103. package/src/validation/index.ts +0 -10
  104. package/src/validation/schema-validator.ts +0 -344
  105. package/src/validation/validation-engine.ts +0 -528
  106. package/src/validation/validators/index.ts +0 -25
  107. package/src/validation/validators/object-validation-engine.ts +0 -722
  108. package/tsconfig.json +0 -15
  109. package/tsconfig.tsbuildinfo +0 -1
  110. package/vitest.config.ts +0 -2
@@ -1,268 +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 - Action Engine
11
- *
12
- * Declarative action dispatch engine. Manages action registration,
13
- * event-to-action mapping, location-based filtering, keyboard shortcuts,
14
- * and bulk operation support.
15
- *
16
- * Replaces callback-based patterns with a schema-driven pipeline:
17
- * ActionSchema[] → ActionEngine → ActionRunner → ActionResult
18
- */
19
-
20
- import { ActionRunner, type ActionDef, type ActionContext, type ActionResult } from './ActionRunner';
21
-
22
- /** Action location types (from @objectstack/spec) */
23
- export type ActionLocation =
24
- | 'list_toolbar'
25
- | 'list_item'
26
- | 'record_header'
27
- | 'record_more'
28
- | 'record_related'
29
- | 'global_nav';
30
-
31
- /** Registered action with metadata */
32
- export interface RegisteredAction {
33
- action: ActionDef;
34
- locations: ActionLocation[];
35
- /** Keyboard shortcut (e.g., 'ctrl+s', 'meta+k') */
36
- shortcut?: string;
37
- /** Whether this action supports bulk operations */
38
- bulkEnabled?: boolean;
39
- /** Priority for ordering (lower = first) */
40
- priority?: number;
41
- }
42
-
43
- /** Event-to-action mapping */
44
- export interface ActionMapping {
45
- /** Event name (e.g., 'row:click', 'toolbar:save', 'keyboard:ctrl+s') */
46
- event: string;
47
- /** Action name to execute */
48
- actionName: string;
49
- /** Optional condition expression */
50
- condition?: string;
51
- }
52
-
53
- /** Keyboard shortcut handler */
54
- export interface ShortcutBinding {
55
- /** Key combination (e.g., 'ctrl+s', 'meta+k', 'shift+n') */
56
- keys: string;
57
- /** Action name to trigger */
58
- actionName: string;
59
- }
60
-
61
- /** Normalize a shortcut string for comparison (lowercase, trimmed, sorted parts) */
62
- function normalizeShortcut(keys: string): string {
63
- return keys.toLowerCase().split('+').map(k => k.trim()).sort().join('+');
64
- }
65
-
66
- export class ActionEngine {
67
- private actions = new Map<string, RegisteredAction>();
68
- private mappings: ActionMapping[] = [];
69
- private shortcuts: ShortcutBinding[] = [];
70
- private normalizedShortcutMap = new Map<string, string>();
71
- private runner: ActionRunner;
72
-
73
- constructor(context: ActionContext = {}) {
74
- this.runner = new ActionRunner(context);
75
- }
76
-
77
- /** Get the underlying ActionRunner for handler configuration */
78
- getRunner(): ActionRunner {
79
- return this.runner;
80
- }
81
-
82
- /** Register a single action */
83
- registerAction(action: ActionDef, options?: {
84
- locations?: ActionLocation[];
85
- shortcut?: string;
86
- bulkEnabled?: boolean;
87
- priority?: number;
88
- }): void {
89
- const name = action.name || action.type || '';
90
- if (!name) throw new Error('Action must have a name or type');
91
-
92
- this.actions.set(name, {
93
- action,
94
- locations: options?.locations || [],
95
- shortcut: options?.shortcut,
96
- bulkEnabled: options?.bulkEnabled ?? false,
97
- priority: options?.priority ?? 100,
98
- });
99
-
100
- // Auto-register keyboard shortcut
101
- if (options?.shortcut) {
102
- this.shortcuts.push({ keys: options.shortcut, actionName: name });
103
- this.normalizedShortcutMap.set(normalizeShortcut(options.shortcut), name);
104
- }
105
- }
106
-
107
- /** Register multiple actions from an ActionSchema array */
108
- registerActions(actions: ActionDef[]): void {
109
- for (const action of actions) {
110
- this.registerAction(action, {
111
- locations: (action as any).locations,
112
- shortcut: (action as any).shortcut,
113
- bulkEnabled: (action as any).bulkEnabled,
114
- });
115
- }
116
- }
117
-
118
- /** Unregister an action by name */
119
- unregisterAction(name: string): void {
120
- const registered = this.actions.get(name);
121
- if (registered?.shortcut) {
122
- this.normalizedShortcutMap.delete(normalizeShortcut(registered.shortcut));
123
- }
124
- this.actions.delete(name);
125
- this.shortcuts = this.shortcuts.filter(s => s.actionName !== name);
126
- this.mappings = this.mappings.filter(m => m.actionName !== name);
127
- }
128
-
129
- /** Add an event-to-action mapping */
130
- addMapping(mapping: ActionMapping): void {
131
- this.mappings.push(mapping);
132
- }
133
-
134
- /** Get actions available at a specific location, sorted by priority */
135
- getActionsForLocation(location: ActionLocation): ActionDef[] {
136
- return Array.from(this.actions.values())
137
- .filter(ra => ra.locations.includes(location))
138
- .sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100))
139
- .map(ra => ra.action);
140
- }
141
-
142
- /** Get actions that support bulk operations */
143
- getBulkActions(): ActionDef[] {
144
- return Array.from(this.actions.values())
145
- .filter(ra => ra.bulkEnabled)
146
- .sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100))
147
- .map(ra => ra.action);
148
- }
149
-
150
- /** Get all registered keyboard shortcuts */
151
- getShortcuts(): ShortcutBinding[] {
152
- return [...this.shortcuts];
153
- }
154
-
155
- /** Get a registered action by name */
156
- getAction(name: string): ActionDef | undefined {
157
- return this.actions.get(name)?.action;
158
- }
159
-
160
- /** Execute an action by name */
161
- async executeAction(name: string, contextOverride?: Partial<ActionContext>): Promise<ActionResult> {
162
- const registered = this.actions.get(name);
163
- if (!registered) {
164
- return { success: false, error: `Action not found: ${name}` };
165
- }
166
-
167
- if (contextOverride) {
168
- this.runner.updateContext(contextOverride);
169
- }
170
-
171
- return this.runner.execute(registered.action);
172
- }
173
-
174
- /** Dispatch an event — finds mapped actions and executes them */
175
- async dispatch(event: string, contextOverride?: Partial<ActionContext>): Promise<ActionResult[]> {
176
- const matchingMappings = this.mappings.filter(m => m.event === event);
177
-
178
- if (matchingMappings.length === 0) {
179
- return [];
180
- }
181
-
182
- const results: ActionResult[] = [];
183
- for (const mapping of matchingMappings) {
184
- // Check condition if present
185
- if (mapping.condition) {
186
- const evaluator = this.runner.getEvaluator();
187
- const shouldRun = evaluator.evaluateCondition(mapping.condition);
188
- if (!shouldRun) continue;
189
- }
190
-
191
- const result = await this.executeAction(mapping.actionName, contextOverride);
192
- results.push(result);
193
- }
194
-
195
- return results;
196
- }
197
-
198
- /** Handle a keyboard shortcut event — returns true if handled */
199
- async handleShortcut(keys: string, contextOverride?: Partial<ActionContext>): Promise<ActionResult | null> {
200
- const actionName = this.normalizedShortcutMap.get(normalizeShortcut(keys));
201
- if (!actionName) return null;
202
-
203
- return this.executeAction(actionName, contextOverride);
204
- }
205
-
206
- /** Execute a bulk operation on multiple records */
207
- async executeBulk(
208
- actionName: string,
209
- records: Record<string, any>[],
210
- options?: { parallel?: boolean; continueOnError?: boolean }
211
- ): Promise<{ total: number; succeeded: number; failed: number; results: ActionResult[] }> {
212
- const registered = this.actions.get(actionName);
213
- if (!registered) {
214
- return { total: 0, succeeded: 0, failed: 0, results: [{ success: false, error: `Action not found: ${actionName}` }] };
215
- }
216
- if (!registered.bulkEnabled) {
217
- return { total: 0, succeeded: 0, failed: 0, results: [{ success: false, error: `Action ${actionName} does not support bulk operations` }] };
218
- }
219
-
220
- const results: ActionResult[] = [];
221
- let succeeded = 0;
222
- let failed = 0;
223
-
224
- if (options?.parallel) {
225
- const promises = records.map(record => {
226
- this.runner.updateContext({ record, selectedRecords: records });
227
- return this.runner.execute(registered.action);
228
- });
229
- const settled = await Promise.allSettled(promises);
230
- for (const r of settled) {
231
- if (r.status === 'fulfilled') {
232
- results.push(r.value);
233
- if (r.value.success) succeeded++;
234
- else failed++;
235
- } else {
236
- results.push({ success: false, error: r.reason?.message || 'Unknown error' });
237
- failed++;
238
- }
239
- }
240
- } else {
241
- for (const record of records) {
242
- this.runner.updateContext({ record, selectedRecords: records });
243
- const result = await this.runner.execute(registered.action);
244
- results.push(result);
245
- if (result.success) succeeded++;
246
- else {
247
- failed++;
248
- if (!options?.continueOnError) break;
249
- }
250
- }
251
- }
252
-
253
- return { total: records.length, succeeded, failed, results };
254
- }
255
-
256
- /** Update the action context */
257
- updateContext(context: Partial<ActionContext>): void {
258
- this.runner.updateContext(context);
259
- }
260
-
261
- /** Clear all registered actions and mappings */
262
- clear(): void {
263
- this.actions.clear();
264
- this.mappings = [];
265
- this.shortcuts = [];
266
- this.normalizedShortcutMap.clear();
267
- }
268
- }