@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
package/src/index.ts CHANGED
@@ -6,31 +6,16 @@
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  */
8
8
 
9
- // Re-export types from @objectstack packages for API compatibility
10
- export type { ObjectKernel } from '@objectstack/runtime';
11
- export type { ObjectStackProtocolImplementation } from '@objectstack/objectql';
12
- // Note: @objectstack/objectql types temporarily commented out due to type incompatibilities
13
- // in the published package. Will be re-enabled when package is updated.
14
- // export type { ObjectQL as ObjectQLEngine, SchemaRegistry } from '@objectstack/objectql';
9
+ // ── Convenience factory ──
10
+ export { createObjectQLKernel, type ObjectQLKernelOptions } from './kernel-factory';
15
11
 
16
- // Export ObjectStack spec types for driver development
17
- import { Data, System } from '@objectstack/spec';
18
- export type QueryAST = Data.QueryAST;
19
- export type DriverInterface = Data.DriverInterface;
20
- export type DriverOptions = Data.DriverOptions;
12
+ // ── Re-export bridge engine (extends upstream with MetadataRegistry + legacy config) ──
13
+ export { ObjectQL, type ObjectQLConfig } from './app';
14
+ export { ObjectRepository, ScopedContext, SchemaRegistry } from '@objectstack/objectql';
15
+ export type { HookHandler, HookEntry, OperationContext, EngineMiddleware, ObjectQLHostContext } from '@objectstack/objectql';
21
16
 
22
- export * from './gateway';
23
-
24
- // Export our enhanced runtime components (actual implementations)
25
- export * from './repository';
26
- export * from './app';
17
+ // ── Plugin orchestration ──
27
18
  export * from './plugin';
28
19
 
29
- // Export query-specific modules (ObjectQL core competency)
30
- export * from './query';
31
-
32
- // Export utilities
20
+ // ── Utilities ──
33
21
  export * from './util';
34
-
35
- // Export kernel optimizations
36
- export * from './optimizations';
@@ -0,0 +1,47 @@
1
+ /**
2
+ * ObjectQL Kernel Factory
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 { ObjectKernel } from '@objectstack/runtime';
10
+ import { ObjectQLPlugin as UpstreamObjectQLPlugin } from '@objectstack/objectql';
11
+ import type { Plugin } from '@objectstack/core';
12
+
13
+ /**
14
+ * Options for creating an ObjectQL Kernel
15
+ */
16
+ export interface ObjectQLKernelOptions {
17
+ /**
18
+ * Additional plugins to register with the kernel
19
+ */
20
+ plugins?: Plugin[];
21
+ }
22
+
23
+ /**
24
+ * Convenience factory for creating an ObjectQL-ready kernel.
25
+ *
26
+ * Creates an ObjectStackKernel pre-configured with the upstream ObjectQLPlugin
27
+ * (data engine, schema registry, protocol implementation) plus any additional
28
+ * plugins provided.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * import { createObjectQLKernel } from '@objectql/core';
33
+ * import { QueryPlugin } from '@objectql/plugin-query';
34
+ * import { OptimizationsPlugin } from '@objectql/plugin-optimizations';
35
+ *
36
+ * const kernel = createObjectQLKernel({
37
+ * plugins: [new QueryPlugin(), new OptimizationsPlugin()],
38
+ * });
39
+ * await kernel.start();
40
+ * ```
41
+ */
42
+ export function createObjectQLKernel(options: ObjectQLKernelOptions = {}): ObjectKernel {
43
+ return new (ObjectKernel as any)([
44
+ new UpstreamObjectQLPlugin(),
45
+ ...(options.plugins || []),
46
+ ]);
47
+ }
package/src/plugin.ts CHANGED
@@ -7,29 +7,13 @@
7
7
  */
8
8
 
9
9
  import type { RuntimePlugin, RuntimeContext } from '@objectql/types';
10
+ import { ConsoleLogger, ObjectQLError } from '@objectql/types';
11
+ import type { Logger } from '@objectql/types';
10
12
  import { ValidatorPlugin, ValidatorPluginConfig } from '@objectql/plugin-validator';
11
13
  import { FormulaPlugin, FormulaPluginConfig } from '@objectql/plugin-formula';
12
- import { QueryService } from './query/query-service';
13
- import { QueryAnalyzer } from './query/query-analyzer';
14
- import { ObjectStackProtocolImplementation } from './protocol';
14
+ import { QueryPlugin } from '@objectql/plugin-query';
15
15
  import type { Driver } from '@objectql/types';
16
-
17
- /**
18
- * Extended kernel with ObjectQL services
19
- */
20
- interface ExtendedKernel {
21
- metadata?: any;
22
- actions?: any;
23
- hooks?: any;
24
- getAllDrivers?: () => Driver[];
25
- create?: (objectName: string, data: any) => Promise<any>;
26
- update?: (objectName: string, id: string, data: any) => Promise<any>;
27
- delete?: (objectName: string, id: string) => Promise<any>;
28
- find?: (objectName: string, query: any) => Promise<any>;
29
- get?: (objectName: string, id: string) => Promise<any>;
30
- queryService?: QueryService;
31
- queryAnalyzer?: QueryAnalyzer;
32
- }
16
+ import { SchemaRegistry } from '@objectstack/objectql';
33
17
 
34
18
  /**
35
19
  * Configuration for the ObjectQL Plugin
@@ -65,12 +49,6 @@ export interface ObjectQLPluginConfig {
65
49
  */
66
50
  formulaConfig?: FormulaPluginConfig;
67
51
 
68
- /**
69
- * Enable AI integration
70
- * @default true
71
- */
72
- enableAI?: boolean;
73
-
74
52
  /**
75
53
  * Enable query service and analyzer
76
54
  * @default true
@@ -87,23 +65,27 @@ export interface ObjectQLPluginConfig {
87
65
  /**
88
66
  * ObjectQL Plugin
89
67
  *
90
- * Implements the RuntimePlugin interface to provide ObjectQL's enhanced features
91
- * (Repository, Validator, Formula, AI) on top of the microkernel.
68
+ * Thin orchestrator that composes ObjectQL's extension plugins
69
+ * (QueryPlugin, ValidatorPlugin, FormulaPlugin, AI) on top of the microkernel.
70
+ *
71
+ * Delegates query execution to @objectql/plugin-query and provides
72
+ * repository-pattern CRUD bridging to the kernel.
92
73
  */
93
74
  export class ObjectQLPlugin implements RuntimePlugin {
94
75
  name = '@objectql/core';
95
- version = '4.0.2';
76
+ version = '4.2.0';
77
+ private logger: Logger;
96
78
 
97
- constructor(private config: ObjectQLPluginConfig = {}, ql?: any) {
79
+ constructor(private config: ObjectQLPluginConfig = {}, _ql?: any) {
98
80
  // Set defaults
99
81
  this.config = {
100
82
  enableRepository: true,
101
83
  enableValidator: true,
102
84
  enableFormulas: true,
103
- enableAI: true,
104
85
  enableQueryService: true,
105
86
  ...config
106
87
  };
88
+ this.logger = new ConsoleLogger({ name: '@objectql/core/plugin', level: 'info' });
107
89
  }
108
90
 
109
91
  /**
@@ -111,9 +93,9 @@ export class ObjectQLPlugin implements RuntimePlugin {
111
93
  * This is called during kernel initialization
112
94
  */
113
95
  async install(ctx: RuntimeContext): Promise<void> {
114
- console.log(`[${this.name}] Installing plugin...`);
96
+ this.logger.info('Installing plugin...');
115
97
 
116
- const kernel = ctx.engine as ExtendedKernel;
98
+ const kernel = ctx.engine as any;
117
99
 
118
100
  // Get datasources - either from config or from kernel drivers
119
101
  let datasources = this.config.datasources;
@@ -127,27 +109,19 @@ export class ObjectQLPlugin implements RuntimePlugin {
127
109
  const driverName = driver.name || (index === 0 ? 'default' : `driver_${index + 1}`);
128
110
  datasources![driverName] = driver;
129
111
  });
130
- console.log(`[${this.name}] Using drivers from kernel:`, Object.keys(datasources));
112
+ this.logger.info('Using drivers from kernel', {
113
+ drivers: Object.keys(datasources),
114
+ });
131
115
  } else {
132
- console.warn(`[${this.name}] No datasources configured and no drivers found in kernel. Repository and QueryService will not be available.`);
116
+ this.logger.warn('No datasources configured and no drivers found in kernel. Repository and QueryService will not be available.');
133
117
  }
134
118
  }
135
119
 
136
- // Register QueryService and QueryAnalyzer if enabled
120
+ // Delegate query service registration to QueryPlugin
137
121
  if (this.config.enableQueryService !== false && datasources) {
138
- const queryService = new QueryService(
139
- datasources,
140
- kernel.metadata
141
- );
142
- kernel.queryService = queryService;
143
-
144
- const queryAnalyzer = new QueryAnalyzer(
145
- queryService,
146
- kernel.metadata
147
- );
148
- kernel.queryAnalyzer = queryAnalyzer;
149
-
150
- console.log(`[${this.name}] QueryService and QueryAnalyzer registered`);
122
+ const queryPlugin = new QueryPlugin({ datasources });
123
+ await queryPlugin.install(ctx);
124
+ this.logger.info('QueryPlugin installed (QueryService + QueryAnalyzer)');
151
125
  }
152
126
 
153
127
  // Register components based on configuration
@@ -167,49 +141,41 @@ export class ObjectQLPlugin implements RuntimePlugin {
167
141
  await formulaPlugin.install?.(ctx);
168
142
  }
169
143
 
170
- if (this.config.enableAI !== false) {
171
- await this.registerAI(kernel);
144
+ // Register system service aliases
145
+ if (typeof (ctx as any).registerService === 'function') {
146
+ const registerService = (ctx as any).registerService.bind(ctx);
147
+
148
+ // 1. Metadata service
149
+ if (kernel.metadata) {
150
+ registerService('metadata', kernel.metadata);
151
+ this.logger.debug('Registered metadata service alias');
152
+ }
153
+
154
+ // 2. Data service (prefer QueryService, fallback to kernel)
155
+ const dataService = kernel.queryService || kernel;
156
+ registerService('data', dataService);
157
+ this.logger.debug('Registered data service alias');
158
+
159
+ // 3. Analytics service (via QueryService)
160
+ if (kernel.queryService) {
161
+ registerService('analytics', kernel.queryService);
162
+ this.logger.debug('Registered analytics service alias');
163
+ }
172
164
  }
173
-
174
- console.log(`[${this.name}] Plugin installed successfully`);
165
+
166
+ this.logger.info('Plugin installed successfully');
175
167
  }
176
168
 
177
169
  /**
178
170
  * Called when the kernel starts
179
171
  * This is the initialization phase
180
172
  */
181
- async onStart(ctx: RuntimeContext): Promise<void> {
182
- console.log(`[${this.name}] Starting plugin...`);
173
+ async onStart(_ctx: RuntimeContext): Promise<void> {
174
+ this.logger.debug('Starting plugin...');
183
175
  // Additional startup logic can be added here
184
176
  }
185
177
 
186
178
  // --- Adapter for @objectstack/core compatibility ---
187
- async init(kernel: any): Promise<void> {
188
- // The new core passes the kernel instance directly
189
- // We wrap it to match the old RuntimeContext interface
190
- const ctx = {
191
- engine: kernel,
192
- getKernel: () => kernel
193
- };
194
-
195
- // Register Protocol Service
196
- // If kernel supports service registration (PluginContext or ExtendedKernel with custom registry)
197
- if (kernel && typeof kernel.registerService === 'function') {
198
- console.log(`[${this.name}] Registering protocol service...`);
199
- const protocolShim = new ObjectStackProtocolImplementation(kernel as any);
200
- kernel.registerService('protocol', protocolShim);
201
- }
202
-
203
- return this.install(ctx);
204
- }
205
-
206
- async start(kernel: any): Promise<void> {
207
- const ctx = {
208
- engine: kernel,
209
- getKernel: () => kernel
210
- };
211
- return this.onStart(ctx);
212
- }
213
179
  // ---------------------------------------------------
214
180
 
215
181
  /**
@@ -223,7 +189,7 @@ export class ObjectQLPlugin implements RuntimePlugin {
223
189
  const datasourceName = objectConfig?.datasource || 'default';
224
190
  const driver = datasources[datasourceName];
225
191
  if (!driver) {
226
- throw new Error(`Datasource '${datasourceName}' not found for object '${objectName}'`);
192
+ throw new ObjectQLError({ code: 'NOT_FOUND', message: `Datasource '${datasourceName}' not found for object '${objectName}'` });
227
193
  }
228
194
  return driver;
229
195
  };
@@ -276,8 +242,6 @@ export class ObjectQLPlugin implements RuntimePlugin {
276
242
  kernel.count = async (objectName: string, filters?: any): Promise<number> => {
277
243
  // Use QueryService if available
278
244
  if ((kernel as any).queryService) {
279
- // QueryService.count expects a UnifiedQuery filter or just filter object?
280
- // Looking at QueryService.count signature: count(objectName: string, where?: Filter, options?: QueryOptions)
281
245
  const result = await (kernel as any).queryService.count(objectName, filters);
282
246
  return result.value;
283
247
  }
@@ -286,16 +250,74 @@ export class ObjectQLPlugin implements RuntimePlugin {
286
250
  return await driver.count(objectName, filters || {}, {});
287
251
  };
288
252
 
289
- console.log(`[${this.name}] Repository pattern registered`);
253
+ this.logger.info('Repository pattern registered');
290
254
  }
291
255
 
292
- /**
293
- * Register AI integration
294
- * @private
295
- */
296
- private async registerAI(kernel: any): Promise<void> {
297
- // TODO: Implement AI registration
298
- // For now, this is a placeholder to establish the structure
299
- console.log(`[${this.name}] AI integration registered`);
300
- }
256
+ // --- Adapter for @objectstack/core compatibility ---
257
+ init = async (pluginCtx: any): Promise<void> => {
258
+ // The @objectstack/core kernel passes a PluginContext (with registerService, getKernel, etc.)
259
+ // We extract the actual kernel and build a RuntimeContext wrapper that proxies registerService.
260
+ const actualKernel = typeof pluginCtx.getKernel === 'function'
261
+ ? pluginCtx.getKernel()
262
+ : pluginCtx;
263
+
264
+ // Create metadata facade on the kernel if not already present.
265
+ // The raw ObjectKernel from @objectstack/core has no .metadata property;
266
+ // it's normally created by the ObjectQL wrapper (app.ts).
267
+ // When running via `objectstack serve`, we must create it here.
268
+ if (!actualKernel.metadata) {
269
+ const unwrapContent = (item: any) => (item && item.content) ? item.content : item;
270
+ actualKernel.metadata = {
271
+ register: (type: string, item: any) => SchemaRegistry.registerItem(type, item, item.id ? 'id' : 'name'),
272
+ get: (type: string, name: string) => {
273
+ const item = SchemaRegistry.getItem(type, name) as any;
274
+ return unwrapContent(item);
275
+ },
276
+ getEntry: (type: string, name: string) => SchemaRegistry.getItem(type, name),
277
+ list: (type: string) => {
278
+ const items = SchemaRegistry.listItems(type);
279
+ return items.map(unwrapContent);
280
+ },
281
+ unregister: (type: string, name: string) => {
282
+ if (typeof SchemaRegistry.unregisterItem === 'function') {
283
+ SchemaRegistry.unregisterItem(type, name);
284
+ }
285
+ },
286
+ unregisterPackage: (packageName: string) => {
287
+ if (typeof (SchemaRegistry as any).unregisterObjectsByPackage === 'function') {
288
+ (SchemaRegistry as any).unregisterObjectsByPackage(packageName);
289
+ }
290
+ },
291
+ };
292
+ this.logger.info('Created metadata facade on kernel');
293
+ }
294
+
295
+ const ctx: any = {
296
+ engine: actualKernel,
297
+ getKernel: () => actualKernel,
298
+ // Proxy registerService from PluginContext so install() can register metadata/data/analytics
299
+ registerService: typeof pluginCtx.registerService === 'function'
300
+ ? pluginCtx.registerService.bind(pluginCtx)
301
+ : undefined,
302
+ };
303
+
304
+ // Register 'objectql' service for AppPlugin compatibility
305
+ if (typeof pluginCtx.registerService === 'function') {
306
+ pluginCtx.registerService('objectql', this);
307
+ this.logger.debug('Registered objectql service');
308
+ }
309
+
310
+ return this.install(ctx);
311
+ }
312
+
313
+ start = async (pluginCtx: any): Promise<void> => {
314
+ const actualKernel = typeof pluginCtx.getKernel === 'function'
315
+ ? pluginCtx.getKernel()
316
+ : pluginCtx;
317
+ const ctx: any = {
318
+ engine: actualKernel,
319
+ getKernel: () => actualKernel,
320
+ };
321
+ return this.onStart(ctx);
322
+ }
301
323
  }