@objectql/core 4.1.0 → 4.2.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 (107) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +42 -0
  3. package/dist/app.d.ts +61 -51
  4. package/dist/app.js +101 -431
  5. package/dist/app.js.map +1 -1
  6. package/dist/index.d.ts +4 -11
  7. package/dist/index.js +13 -9
  8. package/dist/index.js.map +1 -1
  9. package/dist/kernel-factory.d.ts +38 -0
  10. package/dist/kernel-factory.js +38 -0
  11. package/dist/kernel-factory.js.map +1 -0
  12. package/dist/plugin.d.ts +10 -16
  13. package/dist/plugin.js +104 -58
  14. package/dist/plugin.js.map +1 -1
  15. package/dist/repository.d.ts +4 -31
  16. package/dist/repository.js +7 -275
  17. package/dist/repository.js.map +1 -1
  18. package/dist/util.js +4 -2
  19. package/dist/util.js.map +1 -1
  20. package/package.json +19 -11
  21. package/src/app.ts +157 -531
  22. package/src/index.ts +8 -23
  23. package/src/kernel-factory.ts +47 -0
  24. package/src/plugin.ts +116 -94
  25. package/src/repository.ts +4 -313
  26. package/src/util.ts +5 -3
  27. package/test/__mocks__/@objectstack/core.ts +250 -1
  28. package/test/__mocks__/@objectstack/objectql.ts +127 -0
  29. package/test/__mocks__/@objectstack/runtime.ts +14 -5
  30. package/test/introspection.test.ts +1 -1
  31. package/test/mock-driver.ts +5 -5
  32. package/test/optimizations.test.ts +2 -2
  33. package/test/plugin-integration.test.ts +4 -5
  34. package/test/utils.ts +6 -6
  35. package/tsconfig.json +3 -1
  36. package/tsconfig.tsbuildinfo +1 -1
  37. package/dist/gateway.d.ts +0 -36
  38. package/dist/gateway.js +0 -89
  39. package/dist/gateway.js.map +0 -1
  40. package/dist/optimizations/CompiledHookManager.d.ts +0 -55
  41. package/dist/optimizations/CompiledHookManager.js +0 -164
  42. package/dist/optimizations/CompiledHookManager.js.map +0 -1
  43. package/dist/optimizations/DependencyGraph.d.ts +0 -82
  44. package/dist/optimizations/DependencyGraph.js +0 -211
  45. package/dist/optimizations/DependencyGraph.js.map +0 -1
  46. package/dist/optimizations/GlobalConnectionPool.d.ts +0 -89
  47. package/dist/optimizations/GlobalConnectionPool.js +0 -193
  48. package/dist/optimizations/GlobalConnectionPool.js.map +0 -1
  49. package/dist/optimizations/LazyMetadataLoader.d.ts +0 -75
  50. package/dist/optimizations/LazyMetadataLoader.js +0 -149
  51. package/dist/optimizations/LazyMetadataLoader.js.map +0 -1
  52. package/dist/optimizations/OptimizedMetadataRegistry.d.ts +0 -26
  53. package/dist/optimizations/OptimizedMetadataRegistry.js +0 -117
  54. package/dist/optimizations/OptimizedMetadataRegistry.js.map +0 -1
  55. package/dist/optimizations/OptimizedValidationEngine.d.ts +0 -73
  56. package/dist/optimizations/OptimizedValidationEngine.js +0 -141
  57. package/dist/optimizations/OptimizedValidationEngine.js.map +0 -1
  58. package/dist/optimizations/QueryCompiler.d.ts +0 -51
  59. package/dist/optimizations/QueryCompiler.js +0 -216
  60. package/dist/optimizations/QueryCompiler.js.map +0 -1
  61. package/dist/optimizations/SQLQueryOptimizer.d.ts +0 -96
  62. package/dist/optimizations/SQLQueryOptimizer.js +0 -265
  63. package/dist/optimizations/SQLQueryOptimizer.js.map +0 -1
  64. package/dist/optimizations/index.d.ts +0 -32
  65. package/dist/optimizations/index.js +0 -44
  66. package/dist/optimizations/index.js.map +0 -1
  67. package/dist/protocol.d.ts +0 -180
  68. package/dist/protocol.js +0 -260
  69. package/dist/protocol.js.map +0 -1
  70. package/dist/query/filter-translator.d.ts +0 -27
  71. package/dist/query/filter-translator.js +0 -38
  72. package/dist/query/filter-translator.js.map +0 -1
  73. package/dist/query/index.d.ts +0 -22
  74. package/dist/query/index.js +0 -39
  75. package/dist/query/index.js.map +0 -1
  76. package/dist/query/query-analyzer.d.ts +0 -188
  77. package/dist/query/query-analyzer.js +0 -348
  78. package/dist/query/query-analyzer.js.map +0 -1
  79. package/dist/query/query-builder.d.ts +0 -35
  80. package/dist/query/query-builder.js +0 -61
  81. package/dist/query/query-builder.js.map +0 -1
  82. package/dist/query/query-service.d.ts +0 -153
  83. package/dist/query/query-service.js +0 -272
  84. package/dist/query/query-service.js.map +0 -1
  85. package/jest.config.js +0 -29
  86. package/src/gateway.ts +0 -101
  87. package/src/optimizations/CompiledHookManager.ts +0 -185
  88. package/src/optimizations/DependencyGraph.ts +0 -255
  89. package/src/optimizations/GlobalConnectionPool.ts +0 -251
  90. package/src/optimizations/LazyMetadataLoader.ts +0 -180
  91. package/src/optimizations/OptimizedMetadataRegistry.ts +0 -132
  92. package/src/optimizations/OptimizedValidationEngine.ts +0 -172
  93. package/src/optimizations/QueryCompiler.ts +0 -242
  94. package/src/optimizations/SQLQueryOptimizer.ts +0 -329
  95. package/src/optimizations/index.ts +0 -34
  96. package/src/protocol.ts +0 -291
  97. package/src/query/filter-translator.ts +0 -41
  98. package/src/query/index.ts +0 -24
  99. package/src/query/query-analyzer.ts +0 -533
  100. package/src/query/query-builder.ts +0 -64
  101. package/src/query/query-service.ts +0 -398
  102. package/test/app.test.ts +0 -578
  103. package/test/filter-syntax.test.ts +0 -233
  104. package/test/gateway.test.ts +0 -88
  105. package/test/protocol.test.ts +0 -143
  106. package/test/repository-validation.test.ts +0 -351
  107. package/test/repository.test.ts +0 -151
@@ -1,329 +0,0 @@
1
- /**
2
- * ObjectQL
3
- * Copyright (c) 2026-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
- * Index metadata
11
- */
12
- export interface IndexMetadata {
13
- name: string;
14
- fields: string[];
15
- unique: boolean;
16
- type?: 'btree' | 'hash' | 'fulltext';
17
- }
18
-
19
- /**
20
- * Schema with index information
21
- */
22
- export interface SchemaWithIndexes {
23
- name: string;
24
- fields: Record<string, any>;
25
- indexes?: IndexMetadata[];
26
- }
27
-
28
- /**
29
- * Query AST for optimization
30
- */
31
- export interface OptimizableQueryAST {
32
- object: string;
33
- fields?: string[];
34
- filters?: any;
35
- sort?: Array<{ field: string; order: 'asc' | 'desc' }>;
36
- joins?: Array<{ type: 'left' | 'inner'; table: string; on: any }>;
37
- limit?: number;
38
- offset?: number;
39
- }
40
-
41
- /**
42
- * SQL Query Optimizer
43
- *
44
- * Improvement: SQL-aware optimization with index hints and join reordering.
45
- * Analyzes query patterns and schema to generate optimal SQL.
46
- *
47
- * Expected: 2-5x faster queries on large datasets
48
- */
49
- export class SQLQueryOptimizer {
50
- private schemas = new Map<string, SchemaWithIndexes>();
51
-
52
- /**
53
- * Register a schema with index information
54
- */
55
- registerSchema(schema: SchemaWithIndexes): void {
56
- this.schemas.set(schema.name, schema);
57
- }
58
-
59
- /**
60
- * Check if a field has an index
61
- */
62
- private hasIndex(objectName: string, fieldName: string): boolean {
63
- const schema = this.schemas.get(objectName);
64
- if (!schema || !schema.indexes) return false;
65
-
66
- return schema.indexes.some(index =>
67
- index.fields.includes(fieldName)
68
- );
69
- }
70
-
71
- /**
72
- * Get the best index for given filter fields
73
- */
74
- private getBestIndex(objectName: string, filterFields: string[]): IndexMetadata | null {
75
- const schema = this.schemas.get(objectName);
76
- if (!schema || !schema.indexes) return null;
77
-
78
- // Find indexes that cover the filter fields
79
- const candidateIndexes = schema.indexes.filter(index => {
80
- // Check if index covers any of the filter fields
81
- return filterFields.some(field => index.fields.includes(field));
82
- });
83
-
84
- if (candidateIndexes.length === 0) return null;
85
-
86
- // Prefer indexes that match more filter fields
87
- candidateIndexes.sort((a, b) => {
88
- const aMatches = a.fields.filter(f => filterFields.includes(f)).length;
89
- const bMatches = b.fields.filter(f => filterFields.includes(f)).length;
90
- return bMatches - aMatches;
91
- });
92
-
93
- return candidateIndexes[0];
94
- }
95
-
96
- /**
97
- * Extract filter fields from filter conditions
98
- */
99
- private extractFilterFields(filters: any): string[] {
100
- const fields: string[] = [];
101
-
102
- const extract = (obj: any) => {
103
- if (!obj || typeof obj !== 'object') return;
104
-
105
- for (const key of Object.keys(obj)) {
106
- if (!key.startsWith('$')) {
107
- fields.push(key);
108
- }
109
- if (typeof obj[key] === 'object') {
110
- extract(obj[key]);
111
- }
112
- }
113
- };
114
-
115
- extract(filters);
116
- return [...new Set(fields)]; // Remove duplicates
117
- }
118
-
119
- /**
120
- * Optimize join type based on query characteristics
121
- *
122
- * Note: This method expects filter fields in one of two formats:
123
- * 1. Table-prefixed: "tableName.fieldName" (e.g., "accounts.type")
124
- * 2. Simple field name: "fieldName" (checked against joined table schema)
125
- *
126
- * Multi-level qualification (e.g., "schema.table.field") is not currently supported.
127
- */
128
- private optimizeJoinType(
129
- join: { type: 'left' | 'inner'; table: string; on: any },
130
- ast: OptimizableQueryAST
131
- ): 'left' | 'inner' {
132
- // If we're filtering on the joined table, we can use INNER JOIN
133
- if (ast.filters) {
134
- const filterFields = this.extractFilterFields(ast.filters);
135
-
136
- // Check if any filter field references the joined table
137
- const hasFilterOnJoinTable = filterFields.some(field => {
138
- // Handle table-prefixed fields like "accounts.type"
139
- if (field.includes('.')) {
140
- const parts = field.split('.');
141
- // Only consider the first part as table name for simplicity
142
- // This assumes format: "table.field" not "schema.table.field"
143
- if (parts.length === 2 && parts[0] === join.table) {
144
- return true;
145
- }
146
- // If more than 2 parts or table doesn't match, skip this field
147
- return false;
148
- }
149
-
150
- // Also check if the field exists in the joined table schema (non-prefixed)
151
- const schema = this.schemas.get(join.table);
152
- if (schema) {
153
- return schema.fields[field] !== undefined;
154
- }
155
-
156
- return false;
157
- });
158
-
159
- if (hasFilterOnJoinTable) {
160
- return 'inner'; // Convert LEFT to INNER for better performance
161
- }
162
- }
163
-
164
- return join.type;
165
- }
166
-
167
- /**
168
- * Optimize a query AST to SQL
169
- */
170
- optimize(ast: OptimizableQueryAST): string {
171
- const schema = this.schemas.get(ast.object);
172
- if (!schema) {
173
- // Fallback to basic SQL generation
174
- return this.generateBasicSQL(ast);
175
- }
176
-
177
- let sql = 'SELECT ';
178
-
179
- // Fields
180
- if (ast.fields && ast.fields.length > 0) {
181
- sql += ast.fields.join(', ');
182
- } else {
183
- sql += '*';
184
- }
185
-
186
- sql += ` FROM ${ast.object}`;
187
-
188
- // Index hints
189
- if (ast.filters) {
190
- const filterFields = this.extractFilterFields(ast.filters);
191
- const bestIndex = this.getBestIndex(ast.object, filterFields);
192
-
193
- if (bestIndex) {
194
- // Add index hint for MySQL/MariaDB
195
- sql += ` USE INDEX (${bestIndex.name})`;
196
- }
197
- }
198
-
199
- // Optimized joins
200
- if (ast.joins && ast.joins.length > 0) {
201
- for (const join of ast.joins) {
202
- const optimizedType = this.optimizeJoinType(join, ast);
203
- sql += ` ${optimizedType.toUpperCase()} JOIN ${join.table}`;
204
-
205
- // Simplified join condition
206
- if (typeof join.on === 'string') {
207
- sql += ` ON ${join.on}`;
208
- }
209
- }
210
- }
211
-
212
- // WHERE clause
213
- if (ast.filters) {
214
- sql += ' WHERE ' + this.filtersToSQL(ast.filters);
215
- }
216
-
217
- // ORDER BY
218
- if (ast.sort && ast.sort.length > 0) {
219
- sql += ' ORDER BY ';
220
- sql += ast.sort.map(s => `${s.field} ${s.order.toUpperCase()}`).join(', ');
221
- }
222
-
223
- // LIMIT and OFFSET
224
- if (ast.limit !== undefined) {
225
- sql += ` LIMIT ${ast.limit}`;
226
- }
227
- if (ast.offset !== undefined) {
228
- sql += ` OFFSET ${ast.offset}`;
229
- }
230
-
231
- return sql;
232
- }
233
-
234
- /**
235
- * Convert filter object to SQL WHERE clause
236
- */
237
- private filtersToSQL(filters: any): string {
238
- if (typeof filters === 'string') {
239
- return filters;
240
- }
241
-
242
- // Simplified filter conversion
243
- const conditions: string[] = [];
244
-
245
- for (const [key, value] of Object.entries(filters)) {
246
- if (key === '$and') {
247
- const subconditions = (value as any[]).map(f => this.filtersToSQL(f));
248
- conditions.push(`(${subconditions.join(' AND ')})`);
249
- } else if (key === '$or') {
250
- const subconditions = (value as any[]).map(f => this.filtersToSQL(f));
251
- conditions.push(`(${subconditions.join(' OR ')})`);
252
- } else if (!key.startsWith('$')) {
253
- // Field condition
254
- if (typeof value === 'object' && value !== null) {
255
- for (const [op, val] of Object.entries(value)) {
256
- switch (op) {
257
- case '$eq':
258
- conditions.push(`${key} = '${val}'`);
259
- break;
260
- case '$ne':
261
- conditions.push(`${key} != '${val}'`);
262
- break;
263
- case '$gt':
264
- conditions.push(`${key} > '${val}'`);
265
- break;
266
- case '$gte':
267
- conditions.push(`${key} >= '${val}'`);
268
- break;
269
- case '$lt':
270
- conditions.push(`${key} < '${val}'`);
271
- break;
272
- case '$lte':
273
- conditions.push(`${key} <= '${val}'`);
274
- break;
275
- case '$in':
276
- const inValues = (val as any[]).map(v => `'${v}'`).join(', ');
277
- conditions.push(`${key} IN (${inValues})`);
278
- break;
279
- }
280
- }
281
- } else {
282
- conditions.push(`${key} = '${value}'`);
283
- }
284
- }
285
- }
286
-
287
- return conditions.join(' AND ');
288
- }
289
-
290
- /**
291
- * Fallback: generate basic SQL without optimizations
292
- */
293
- private generateBasicSQL(ast: OptimizableQueryAST): string {
294
- let sql = 'SELECT ';
295
-
296
- if (ast.fields && ast.fields.length > 0) {
297
- sql += ast.fields.join(', ');
298
- } else {
299
- sql += '*';
300
- }
301
-
302
- sql += ` FROM ${ast.object}`;
303
-
304
- if (ast.filters) {
305
- sql += ' WHERE ' + this.filtersToSQL(ast.filters);
306
- }
307
-
308
- if (ast.sort && ast.sort.length > 0) {
309
- sql += ' ORDER BY ';
310
- sql += ast.sort.map(s => `${s.field} ${s.order.toUpperCase()}`).join(', ');
311
- }
312
-
313
- if (ast.limit !== undefined) {
314
- sql += ` LIMIT ${ast.limit}`;
315
- }
316
- if (ast.offset !== undefined) {
317
- sql += ` OFFSET ${ast.offset}`;
318
- }
319
-
320
- return sql;
321
- }
322
-
323
- /**
324
- * Clear all registered schemas
325
- */
326
- clearSchemas(): void {
327
- this.schemas.clear();
328
- }
329
- }
@@ -1,34 +0,0 @@
1
- /**
2
- * ObjectQL
3
- * Copyright (c) 2026-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
- * Kernel Optimizations Module
11
- *
12
- * This module contains 10 key optimizations for the ObjectQL kernel:
13
- *
14
- * 1. OptimizedMetadataRegistry - O(k) package uninstall with secondary indexes
15
- * 2. QueryCompiler - LRU cache for compiled query plans
16
- * 3. CompiledHookManager - Pre-compiled hook pipelines
17
- * 4. GlobalConnectionPool - Kernel-level connection pooling
18
- * 5. OptimizedValidationEngine - Compiled validation rules
19
- * 6. LazyMetadataLoader - On-demand metadata loading with predictive preload
20
- * 7. DependencyGraph - DAG-based dependency resolution
21
- * 8. SQLQueryOptimizer - SQL-aware query optimization with index hints
22
- *
23
- * Note: TypeScript type generation optimization (#7) and memory-mapped storage (#10)
24
- * are not included in this release for compatibility and complexity reasons.
25
- */
26
-
27
- export { OptimizedMetadataRegistry } from './OptimizedMetadataRegistry';
28
- export { QueryCompiler, type CompiledQuery } from './QueryCompiler';
29
- export { CompiledHookManager, type Hook } from './CompiledHookManager';
30
- export { GlobalConnectionPool, type Connection, type PoolLimits } from './GlobalConnectionPool';
31
- export { OptimizedValidationEngine, type ValidatorFunction, type ValidationSchema } from './OptimizedValidationEngine';
32
- export { LazyMetadataLoader, type ObjectMetadata, type MetadataLoader } from './LazyMetadataLoader';
33
- export { DependencyGraph, type DependencyEdge, type DependencyType } from './DependencyGraph';
34
- export { SQLQueryOptimizer, type IndexMetadata, type SchemaWithIndexes, type OptimizableQueryAST } from './SQLQueryOptimizer';
package/src/protocol.ts DELETED
@@ -1,291 +0,0 @@
1
- /**
2
- * ObjectStack Protocol Implementation
3
- * Copyright (c) 2026-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
- import { ObjectStackProtocol } from '@objectstack/spec/api';
10
- import { IObjectQL } from '@objectql/types';
11
-
12
- /**
13
- * Bridges the ObjectStack Protocol (Specification) to the ObjectQL Engine (Implementation)
14
- */
15
- export class ObjectStackProtocolImplementation implements ObjectStackProtocol {
16
- constructor(private engine: IObjectQL) {}
17
-
18
- /**
19
- * Get API Discovery Document
20
- */
21
- async getDiscovery(args: any): Promise<any> {
22
- return {
23
- name: 'ObjectQL Engine',
24
- version: '4.0.0',
25
- protocols: ['rest', 'graphql', 'json-rpc', 'odata'],
26
- auth: {
27
- type: 'bearer',
28
- url: '/auth/token'
29
- }
30
- };
31
- }
32
-
33
- /**
34
- * Get Metadata Types (e.g., ['object', 'action'])
35
- */
36
- async getMetaTypes(args: any): Promise<{ types: string[] }> {
37
- let types = ['object'];
38
- if (this.engine.metadata && typeof this.engine.metadata.getTypes === 'function') {
39
- types = this.engine.metadata.getTypes();
40
- }
41
- return { types };
42
- }
43
-
44
- /**
45
- * Get Metadata Items for a Type
46
- */
47
- async getMetaItems(args: { type: string }): Promise<{ type: string; items: any[] }> {
48
- const { type } = args;
49
- let items: any[] = [];
50
- if (this.engine.metadata && typeof this.engine.metadata.list === 'function') {
51
- items = this.engine.metadata.list(type);
52
- }
53
- return { type, items };
54
- }
55
-
56
- /**
57
- * Get Metadata Item
58
- */
59
- async getMetaItem(args: { type: string; name: string }): Promise<any> {
60
- const { type, name } = args;
61
- if (this.engine.metadata && typeof this.engine.metadata.get === 'function') {
62
- return this.engine.metadata.get(type, name);
63
- }
64
- return null;
65
- }
66
-
67
- /**
68
- * Get Cached Metadata Item
69
- */
70
- async getMetaItemCached(args: { type: string; name: string }): Promise<any> {
71
- // Fallback to non-cached version for now
72
- return this.getMetaItem(args);
73
- }
74
-
75
- /**
76
- * Get UI View
77
- */
78
- async getUiView(args: { object: string; type: 'list' | 'form' }): Promise<any> {
79
- return null;
80
- }
81
-
82
- /**
83
- * Find Data Records
84
- */
85
- async findData(args: { object: string; query?: any }): Promise<any> {
86
- const { object, query } = args;
87
-
88
- // Use direct kernel method if available (preferred)
89
- if (typeof (this.engine as any).find === 'function') {
90
- const result = await (this.engine as any).find(object, query || {});
91
- return result;
92
- }
93
-
94
- // Fallback to createContext (if engine is IObjectQL)
95
- if (typeof (this.engine as any).createContext === 'function') {
96
- const ctx = (this.engine as any).createContext({ isSystem: true });
97
- try {
98
- const repo = ctx.object(object);
99
- return await repo.find(query || {});
100
- } catch (error: any) {
101
- throw new Error(`Data access failed: ${error.message}`);
102
- }
103
- }
104
-
105
- throw new Error('Engine does not support find operation');
106
- }
107
-
108
- /**
109
- * Count Data Records
110
- */
111
- async countData(args: { object: string; query?: any }): Promise<number> {
112
- const { object, query } = args;
113
- // Basic fallback
114
- const result = await this.findData(args);
115
- return Array.isArray(result) ? result.length : (result.value ? result.value.length : 0);
116
- }
117
-
118
-
119
- /**
120
- * Get Single Data Record
121
- */
122
- async getData(args: { object: string; id: string }): Promise<any> {
123
- const { object, id } = args;
124
-
125
- if (typeof (this.engine as any).get === 'function') {
126
- return await (this.engine as any).get(object, id);
127
- }
128
-
129
- if (typeof (this.engine as any).createContext === 'function') {
130
- const ctx = (this.engine as any).createContext({ isSystem: true });
131
- try {
132
- const repo = ctx.object(object);
133
- return await repo.findOne(id);
134
- } catch (error: any) {
135
- throw new Error(`Data retrieval failed: ${error.message}`);
136
- }
137
- }
138
-
139
- throw new Error('Engine does not support get operation');
140
- }
141
-
142
- /**
143
- * Create Data Record
144
- */
145
- async createData(args: { object: string; data: any }): Promise<any> {
146
- const { object, data } = args;
147
-
148
- if (typeof (this.engine as any).create === 'function') {
149
- return await (this.engine as any).create(object, data);
150
- }
151
-
152
- if (typeof (this.engine as any).createContext === 'function') {
153
- const ctx = (this.engine as any).createContext({ isSystem: true });
154
- try {
155
- const repo = ctx.object(object);
156
- // Protocol expects returned data
157
- return await repo.create(data);
158
- } catch (error: any) {
159
- throw new Error(`Data creation failed: ${error.message}`);
160
- }
161
- }
162
-
163
- throw new Error('Engine does not support create operation');
164
- }
165
-
166
- /**
167
- * Update Data Record
168
- */
169
- async updateData(args: { object: string; id: string; data: any }): Promise<any> {
170
- const { object, id, data } = args;
171
-
172
- if (typeof (this.engine as any).update === 'function') {
173
- return await (this.engine as any).update(object, id, data);
174
- }
175
-
176
- if (typeof (this.engine as any).createContext === 'function') {
177
- const ctx = (this.engine as any).createContext({ isSystem: true });
178
- try {
179
- const repo = ctx.object(object);
180
- return await repo.update(id, data);
181
- } catch (error: any) {
182
- throw new Error(`Data update failed: ${error.message}`);
183
- }
184
- }
185
-
186
- throw new Error('Engine does not support update operation');
187
- }
188
-
189
- /**
190
- * Delete Data Record
191
- */
192
- async deleteData(args: { object: string; id: string }): Promise<{ object: string; id: string; success: boolean }> {
193
- const { object, id } = args;
194
-
195
- if (typeof (this.engine as any).delete === 'function') {
196
- const success = await (this.engine as any).delete(object, id);
197
- return { object, id, success: !!success };
198
- }
199
-
200
- if (typeof (this.engine as any).createContext === 'function') {
201
- const ctx = (this.engine as any).createContext({ isSystem: true });
202
- try {
203
- const repo = ctx.object(object);
204
- await repo.delete(id);
205
- return { object, id, success: true };
206
- } catch (error: any) {
207
- throw new Error(`Data deletion failed: ${error.message}`);
208
- }
209
- }
210
-
211
- throw new Error('Engine does not support delete operation');
212
- }
213
-
214
- /**
215
- * Create Many Data Records
216
- */
217
- async createManyData(args: { object: string; records: any[]; options?: any }): Promise<any> {
218
- throw new Error('createManyData not implemented');
219
- }
220
-
221
- /**
222
- * Update Many Data Records
223
- */
224
- async updateManyData(args: { object: string; records: { id: string; data: any }[]; options?: any }): Promise<any> {
225
- throw new Error('updateManyData not implemented');
226
- }
227
-
228
- /**
229
- * Delete Many Data Records
230
- */
231
- async deleteManyData(args: { object: string; ids: string[]; options?: any }): Promise<any> {
232
- throw new Error('deleteManyData not implemented');
233
- }
234
-
235
- /**
236
- * Batch Operations
237
- */
238
- async batchData(args: { object: string; request: { operation: 'create' | 'update' | 'delete' | 'upsert'; records: any[] } }): Promise<any> {
239
- throw new Error('batchData not implemented');
240
- }
241
-
242
- /**
243
- * Execute Action/Operation
244
- */
245
- async performAction(args: { object: string; id?: string; action: string; args?: any }): Promise<any> {
246
- // Not implemented in this shim yet
247
- throw new Error('Action execution not implemented in protocol shim');
248
- }
249
-
250
- /**
251
- * Analytics Query - Execute analytics query
252
- */
253
- async analyticsQuery(args: any): Promise<any> {
254
- throw new Error('analyticsQuery not implemented');
255
- }
256
-
257
- /**
258
- * Get Analytics Metadata
259
- */
260
- async getAnalyticsMeta(args: any): Promise<any> {
261
- throw new Error('getAnalyticsMeta not implemented');
262
- }
263
-
264
- /**
265
- * Trigger Automation
266
- */
267
- async triggerAutomation(args: { trigger: string; payload: Record<string, any> }): Promise<{ success: boolean; jobId?: string; result?: any }> {
268
- throw new Error('triggerAutomation not implemented');
269
- }
270
-
271
- /**
272
- * List Spaces (Hub/Workspace Management)
273
- */
274
- async listSpaces(args: any): Promise<any> {
275
- throw new Error('listSpaces not implemented');
276
- }
277
-
278
- /**
279
- * Create Space (Hub/Workspace Management)
280
- */
281
- async createSpace(args: any): Promise<any> {
282
- throw new Error('createSpace not implemented');
283
- }
284
-
285
- /**
286
- * Install Plugin (Hub/Extension Management)
287
- */
288
- async installPlugin(args: any): Promise<any> {
289
- throw new Error('installPlugin not implemented');
290
- }
291
- }
@@ -1,41 +0,0 @@
1
- /**
2
- * ObjectQL
3
- * Copyright (c) 2026-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
- import type { Filter } from '@objectql/types';
10
- import { Data } from '@objectstack/spec';
11
- type FilterCondition = Data.FilterCondition;
12
- import { ObjectQLError } from '@objectql/types';
13
-
14
- /**
15
- * Filter Translator
16
- *
17
- * Translates ObjectQL Filter to ObjectStack FilterCondition format.
18
- * Since both now use the same format, this is mostly a pass-through.
19
- *
20
- * @example
21
- * Input: { age: { $gte: 18 }, $or: [{ status: "active" }, { role: "admin" }] }
22
- * Output: { age: { $gte: 18 }, $or: [{ status: "active" }, { role: "admin" }] }
23
- */
24
- export class FilterTranslator {
25
- /**
26
- * Translate filters from ObjectQL format to ObjectStack FilterCondition format
27
- */
28
- translate(filters?: Filter): FilterCondition | undefined {
29
- if (!filters) {
30
- return undefined;
31
- }
32
-
33
- // If it's an empty object, return undefined
34
- if (typeof filters === 'object' && Object.keys(filters).length === 0) {
35
- return undefined;
36
- }
37
-
38
- // Both ObjectQL Filter and ObjectStack FilterCondition use the same format now
39
- return filters as unknown as FilterCondition;
40
- }
41
- }