@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,398 +0,0 @@
1
- /**
2
- * ObjectQL Query Service
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 {
10
- Driver,
11
- ObjectConfig,
12
- UnifiedQuery,
13
- Filter,
14
- MetadataRegistry
15
- } from '@objectql/types';
16
- import { Data } from '@objectstack/spec';
17
- type QueryAST = Data.QueryAST;
18
- import { QueryBuilder } from './query-builder';
19
- import { QueryCompiler } from '../optimizations/QueryCompiler';
20
-
21
- /**
22
- * Options for query execution
23
- */
24
- export interface QueryOptions {
25
- /**
26
- * Transaction handle for transactional queries
27
- */
28
- transaction?: any;
29
-
30
- /**
31
- * Skip validation (for system operations)
32
- */
33
- skipValidation?: boolean;
34
-
35
- /**
36
- * Include profiling information
37
- */
38
- profile?: boolean;
39
-
40
- /**
41
- * Custom driver options
42
- */
43
- driverOptions?: Record<string, unknown>;
44
- }
45
-
46
- /**
47
- * Result of a query execution with optional profiling data
48
- */
49
- export interface QueryResult<T = any> {
50
- /**
51
- * The query results
52
- */
53
- value: T;
54
-
55
- /**
56
- * Total count (for paginated queries)
57
- */
58
- count?: number;
59
-
60
- /**
61
- * Profiling information (if profile option was enabled)
62
- */
63
- profile?: QueryProfile;
64
- }
65
-
66
- /**
67
- * Profiling information for a query
68
- */
69
- export interface QueryProfile {
70
- /**
71
- * Execution time in milliseconds
72
- */
73
- executionTime: number;
74
-
75
- /**
76
- * Number of rows scanned
77
- */
78
- rowsScanned?: number;
79
-
80
- /**
81
- * Whether an index was used
82
- */
83
- indexUsed?: boolean;
84
-
85
- /**
86
- * The generated QueryAST
87
- */
88
- ast?: QueryAST;
89
- }
90
-
91
- /**
92
- * Query Service
93
- *
94
- * Handles all query execution logic, separating query concerns from
95
- * the repository pattern. This service is responsible for:
96
- * - Building QueryAST from UnifiedQuery
97
- * - Executing queries via drivers
98
- * - Optional query profiling and analysis
99
- *
100
- * The QueryService is registered as a service in the ObjectQLPlugin
101
- * and can be used by Repository for all read operations.
102
- */
103
- export class QueryService {
104
- private queryBuilder: QueryBuilder;
105
- private queryCompiler: QueryCompiler;
106
-
107
- constructor(
108
- private datasources: Record<string, Driver>,
109
- private metadata: MetadataRegistry
110
- ) {
111
- this.queryBuilder = new QueryBuilder();
112
- this.queryCompiler = new QueryCompiler(1000);
113
- }
114
-
115
- /**
116
- * Get the driver for a specific object
117
- * @private
118
- */
119
- private getDriver(objectName: string): Driver {
120
- const obj = this.getSchema(objectName);
121
- const datasourceName = obj.datasource || 'default';
122
- const driver = this.datasources[datasourceName];
123
-
124
- if (!driver) {
125
- throw new Error(`Datasource '${datasourceName}' not found for object '${objectName}'`);
126
- }
127
-
128
- return driver;
129
- }
130
-
131
- /**
132
- * Get the schema for an object
133
- * @private
134
- */
135
- private getSchema(objectName: string): ObjectConfig {
136
- const obj = this.metadata.get('object', objectName);
137
- if (!obj) {
138
- throw new Error(`Object '${objectName}' not found in metadata`);
139
- }
140
- return obj;
141
- }
142
-
143
- /**
144
- * Build QueryAST from UnifiedQuery
145
- * @private
146
- */
147
- private buildQueryAST(objectName: string, query: UnifiedQuery): QueryAST {
148
- const ast = this.queryBuilder.build(objectName, query);
149
- const compiled = this.queryCompiler.compile(objectName, ast);
150
- return compiled.ast;
151
- }
152
-
153
- /**
154
- * Execute a find query
155
- *
156
- * @param objectName - The object to query
157
- * @param query - The unified query
158
- * @param options - Query execution options
159
- * @returns Array of matching records
160
- */
161
- async find(
162
- objectName: string,
163
- query: UnifiedQuery = {},
164
- options: QueryOptions = {}
165
- ): Promise<QueryResult<any[]>> {
166
- const driver = this.getDriver(objectName);
167
- const startTime = options.profile ? Date.now() : 0;
168
-
169
- // Build QueryAST
170
- const ast = this.buildQueryAST(objectName, query);
171
-
172
- // Execute query via driver
173
- const driverOptions = {
174
- transaction: options.transaction,
175
- ...options.driverOptions
176
- };
177
-
178
- let results: any[];
179
- let count: number | undefined;
180
-
181
- if (driver.find) {
182
- // Legacy driver interface
183
- const result: any = await driver.find(objectName, query, driverOptions);
184
- results = Array.isArray(result) ? result : (result?.value || []);
185
- count = (typeof result === 'object' && !Array.isArray(result) && result?.count !== undefined) ? result.count : undefined;
186
- } else if (driver.executeQuery) {
187
- // New DriverInterface
188
- const result = await driver.executeQuery(ast, driverOptions);
189
- results = result.value || [];
190
- count = result.count;
191
- } else {
192
- throw new Error(`Driver does not support query execution`);
193
- }
194
-
195
- const executionTime = options.profile ? Date.now() - startTime : 0;
196
-
197
- return {
198
- value: results,
199
- count,
200
- profile: options.profile ? {
201
- executionTime,
202
- ast,
203
- rowsScanned: results.length,
204
- } : undefined
205
- };
206
- }
207
-
208
- /**
209
- * Execute a findOne query by ID
210
- *
211
- * @param objectName - The object to query
212
- * @param id - The record ID
213
- * @param options - Query execution options
214
- * @returns The matching record or undefined
215
- */
216
- async findOne(
217
- objectName: string,
218
- id: string | number,
219
- options: QueryOptions = {}
220
- ): Promise<QueryResult<any>> {
221
- const driver = this.getDriver(objectName);
222
- const startTime = options.profile ? Date.now() : 0;
223
-
224
- const driverOptions = {
225
- transaction: options.transaction,
226
- ...options.driverOptions
227
- };
228
-
229
- let result: any;
230
-
231
- if (driver.findOne) {
232
- // Legacy driver interface
233
- result = await driver.findOne(objectName, id, driverOptions);
234
- } else if (driver.get) {
235
- // Alternative method name
236
- result = await driver.get(objectName, String(id), driverOptions);
237
- } else if (driver.executeQuery) {
238
- // Fallback to query with ID filter
239
- const query: UnifiedQuery = {
240
- where: { _id: id }
241
- };
242
- const ast = this.buildQueryAST(objectName, query);
243
- const queryResult = await driver.executeQuery(ast, driverOptions);
244
- result = queryResult.value?.[0];
245
- } else {
246
- throw new Error(`Driver does not support findOne operation`);
247
- }
248
-
249
- const executionTime = options.profile ? Date.now() - startTime : 0;
250
-
251
- return {
252
- value: result,
253
- profile: options.profile ? {
254
- executionTime,
255
- rowsScanned: result ? 1 : 0,
256
- } : undefined
257
- };
258
- }
259
-
260
- /**
261
- * Execute a count query
262
- *
263
- * @param objectName - The object to query
264
- * @param where - Optional filter condition
265
- * @param options - Query execution options
266
- * @returns Count of matching records
267
- */
268
- async count(
269
- objectName: string,
270
- where?: Filter,
271
- options: QueryOptions = {}
272
- ): Promise<QueryResult<number>> {
273
- const driver = this.getDriver(objectName);
274
- const startTime = options.profile ? Date.now() : 0;
275
-
276
- const query: UnifiedQuery = where ? { where } : {};
277
- const ast = this.buildQueryAST(objectName, query);
278
-
279
- const driverOptions = {
280
- transaction: options.transaction,
281
- ...options.driverOptions
282
- };
283
-
284
- let count: number;
285
-
286
- if (driver.count) {
287
- // Legacy driver interface
288
- count = await driver.count(objectName, where || {}, driverOptions);
289
- } else if (driver.executeQuery) {
290
- // Use executeQuery and count results
291
- // Note: This is inefficient for large datasets
292
- // Ideally, driver should support count-specific optimization
293
- const result = await driver.executeQuery(ast, driverOptions);
294
- count = result.count ?? result.value?.length ?? 0;
295
- } else {
296
- throw new Error(`Driver does not support count operation`);
297
- }
298
-
299
- const executionTime = options.profile ? Date.now() - startTime : 0;
300
-
301
- return {
302
- value: count,
303
- profile: options.profile ? {
304
- executionTime,
305
- ast,
306
- } : undefined
307
- };
308
- }
309
-
310
- /**
311
- * Execute an aggregate query
312
- *
313
- * @param objectName - The object to query
314
- * @param query - The aggregation query using UnifiedQuery format
315
- * @param options - Query execution options
316
- * @returns Aggregation results
317
- */
318
- async aggregate(
319
- objectName: string,
320
- query: UnifiedQuery,
321
- options: QueryOptions = {}
322
- ): Promise<QueryResult<any[]>> {
323
- const driver = this.getDriver(objectName);
324
- const startTime = options.profile ? Date.now() : 0;
325
-
326
- const driverOptions = {
327
- transaction: options.transaction,
328
- ...options.driverOptions
329
- };
330
-
331
- let results: any[];
332
-
333
- if (driver.aggregate) {
334
- // Driver supports aggregation
335
- results = await driver.aggregate(objectName, query, driverOptions);
336
- } else {
337
- // Driver doesn't support aggregation
338
- throw new Error(`Driver does not support aggregate operations. Consider using a driver that supports aggregation.`);
339
- }
340
-
341
- const executionTime = options.profile ? Date.now() - startTime : 0;
342
-
343
- return {
344
- value: results,
345
- profile: options.profile ? {
346
- executionTime,
347
- rowsScanned: results.length,
348
- } : undefined
349
- };
350
- }
351
-
352
- /**
353
- * Execute a direct SQL/query passthrough
354
- *
355
- * This bypasses ObjectQL's query builder and executes raw queries.
356
- * Use with caution as it bypasses security and validation.
357
- *
358
- * @param objectName - The object (determines which datasource to use)
359
- * @param queryString - Raw query string (SQL, MongoDB query, etc.)
360
- * @param params - Query parameters (for parameterized queries)
361
- * @param options - Query execution options
362
- * @returns Query results
363
- */
364
- async directQuery(
365
- objectName: string,
366
- queryString: string,
367
- params?: any[],
368
- options: QueryOptions = {}
369
- ): Promise<QueryResult<any>> {
370
- const driver = this.getDriver(objectName);
371
- const startTime = options.profile ? Date.now() : 0;
372
-
373
- const driverOptions = {
374
- transaction: options.transaction,
375
- ...options.driverOptions
376
- };
377
-
378
- let results: any;
379
-
380
- if (driver.directQuery) {
381
- results = await driver.directQuery(queryString, params);
382
- } else if (driver.query) {
383
- // Alternative method name
384
- results = await driver.query(queryString, params);
385
- } else {
386
- throw new Error(`Driver does not support direct query execution`);
387
- }
388
-
389
- const executionTime = options.profile ? Date.now() - startTime : 0;
390
-
391
- return {
392
- value: results,
393
- profile: options.profile ? {
394
- executionTime,
395
- } : undefined
396
- };
397
- }
398
- }