@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,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
- }