@objectql/core 4.2.0 → 4.2.2
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.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +34 -0
- package/README.md +5 -2
- package/dist/app.d.ts +61 -52
- package/dist/app.js +100 -435
- package/dist/app.js.map +1 -1
- package/dist/index.d.ts +14 -20
- package/dist/index.js +21 -20
- package/dist/index.js.map +1 -1
- package/dist/kernel-factory.d.ts +38 -0
- package/dist/kernel-factory.js +38 -0
- package/dist/kernel-factory.js.map +1 -0
- package/dist/plugin.d.ts +9 -16
- package/dist/plugin.js +71 -48
- package/dist/plugin.js.map +1 -1
- package/dist/repository.d.ts +4 -31
- package/dist/repository.js +7 -283
- package/dist/repository.js.map +1 -1
- package/dist/util.js +4 -2
- package/dist/util.js.map +1 -1
- package/package.json +14 -12
- package/src/app.ts +156 -539
- package/src/index.ts +18 -42
- package/src/kernel-factory.ts +47 -0
- package/src/plugin.ts +77 -85
- package/src/repository.ts +4 -320
- package/src/util.ts +5 -3
- package/test/__mocks__/@objectstack/core.ts +250 -1
- package/test/__mocks__/@objectstack/objectql.ts +273 -0
- package/test/__mocks__/@objectstack/runtime.ts +14 -5
- package/test/introspection.test.ts +1 -1
- package/test/mock-driver.ts +5 -5
- package/test/optimizations.test.ts +2 -2
- package/test/plugin-integration.test.ts +1 -3
- package/test/utils.ts +6 -6
- package/tsconfig.json +3 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/ai/index.d.ts +0 -8
- package/dist/ai/index.js +0 -25
- package/dist/ai/index.js.map +0 -1
- package/dist/ai/registry.d.ts +0 -23
- package/dist/ai/registry.js +0 -78
- package/dist/ai/registry.js.map +0 -1
- package/dist/gateway.d.ts +0 -37
- package/dist/gateway.js +0 -93
- package/dist/gateway.js.map +0 -1
- package/dist/optimizations/CompiledHookManager.d.ts +0 -56
- package/dist/optimizations/CompiledHookManager.js +0 -170
- package/dist/optimizations/CompiledHookManager.js.map +0 -1
- package/dist/optimizations/DependencyGraph.d.ts +0 -82
- package/dist/optimizations/DependencyGraph.js +0 -211
- package/dist/optimizations/DependencyGraph.js.map +0 -1
- package/dist/optimizations/GlobalConnectionPool.d.ts +0 -89
- package/dist/optimizations/GlobalConnectionPool.js +0 -193
- package/dist/optimizations/GlobalConnectionPool.js.map +0 -1
- package/dist/optimizations/LazyMetadataLoader.d.ts +0 -75
- package/dist/optimizations/LazyMetadataLoader.js +0 -149
- package/dist/optimizations/LazyMetadataLoader.js.map +0 -1
- package/dist/optimizations/OptimizedMetadataRegistry.d.ts +0 -26
- package/dist/optimizations/OptimizedMetadataRegistry.js +0 -117
- package/dist/optimizations/OptimizedMetadataRegistry.js.map +0 -1
- package/dist/optimizations/OptimizedValidationEngine.d.ts +0 -73
- package/dist/optimizations/OptimizedValidationEngine.js +0 -141
- package/dist/optimizations/OptimizedValidationEngine.js.map +0 -1
- package/dist/optimizations/QueryCompiler.d.ts +0 -51
- package/dist/optimizations/QueryCompiler.js +0 -216
- package/dist/optimizations/QueryCompiler.js.map +0 -1
- package/dist/optimizations/SQLQueryOptimizer.d.ts +0 -96
- package/dist/optimizations/SQLQueryOptimizer.js +0 -265
- package/dist/optimizations/SQLQueryOptimizer.js.map +0 -1
- package/dist/optimizations/index.d.ts +0 -32
- package/dist/optimizations/index.js +0 -44
- package/dist/optimizations/index.js.map +0 -1
- package/dist/protocol.d.ts +0 -191
- package/dist/protocol.js +0 -272
- package/dist/protocol.js.map +0 -1
- package/dist/query/filter-translator.d.ts +0 -24
- package/dist/query/filter-translator.js +0 -38
- package/dist/query/filter-translator.js.map +0 -1
- package/dist/query/index.d.ts +0 -22
- package/dist/query/index.js +0 -39
- package/dist/query/index.js.map +0 -1
- package/dist/query/query-analyzer.d.ts +0 -186
- package/dist/query/query-analyzer.js +0 -348
- package/dist/query/query-analyzer.js.map +0 -1
- package/dist/query/query-builder.d.ts +0 -27
- package/dist/query/query-builder.js +0 -69
- package/dist/query/query-builder.js.map +0 -1
- package/dist/query/query-service.d.ts +0 -151
- package/dist/query/query-service.js +0 -272
- package/dist/query/query-service.js.map +0 -1
- package/src/ai/index.ts +0 -9
- package/src/ai/registry.ts +0 -81
- package/src/gateway.ts +0 -105
- package/src/optimizations/CompiledHookManager.ts +0 -193
- package/src/optimizations/DependencyGraph.ts +0 -255
- package/src/optimizations/GlobalConnectionPool.ts +0 -251
- package/src/optimizations/LazyMetadataLoader.ts +0 -180
- package/src/optimizations/OptimizedMetadataRegistry.ts +0 -132
- package/src/optimizations/OptimizedValidationEngine.ts +0 -172
- package/src/optimizations/QueryCompiler.ts +0 -242
- package/src/optimizations/SQLQueryOptimizer.ts +0 -329
- package/src/optimizations/index.ts +0 -34
- package/src/protocol.ts +0 -304
- package/src/query/filter-translator.ts +0 -41
- package/src/query/index.ts +0 -24
- package/src/query/query-analyzer.ts +0 -532
- package/src/query/query-builder.ts +0 -64
- package/src/query/query-service.ts +0 -397
- package/test/ai-registry.test.ts +0 -42
- package/test/app.test.ts +0 -578
- package/test/filter-syntax.test.ts +0 -233
- package/test/gateway.test.ts +0 -88
- package/test/protocol.test.ts +0 -143
- package/test/repository-validation.test.ts +0 -351
- package/test/repository.test.ts +0 -151
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* ObjectQL Query Service
|
|
4
|
-
* Copyright (c) 2026-present ObjectStack Inc.
|
|
5
|
-
*
|
|
6
|
-
* This source code is licensed under the MIT license found in the
|
|
7
|
-
* LICENSE file in the root directory of this source tree.
|
|
8
|
-
*/
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.QueryService = void 0;
|
|
11
|
-
const query_builder_1 = require("./query-builder");
|
|
12
|
-
const QueryCompiler_1 = require("../optimizations/QueryCompiler");
|
|
13
|
-
/**
|
|
14
|
-
* Query Service
|
|
15
|
-
*
|
|
16
|
-
* Handles all query execution logic, separating query concerns from
|
|
17
|
-
* the repository pattern. This service is responsible for:
|
|
18
|
-
* - Building QueryAST from UnifiedQuery
|
|
19
|
-
* - Executing queries via drivers
|
|
20
|
-
* - Optional query profiling and analysis
|
|
21
|
-
*
|
|
22
|
-
* The QueryService is registered as a service in the ObjectQLPlugin
|
|
23
|
-
* and can be used by Repository for all read operations.
|
|
24
|
-
*/
|
|
25
|
-
class QueryService {
|
|
26
|
-
constructor(datasources, metadata) {
|
|
27
|
-
this.datasources = datasources;
|
|
28
|
-
this.metadata = metadata;
|
|
29
|
-
this.queryBuilder = new query_builder_1.QueryBuilder();
|
|
30
|
-
this.queryCompiler = new QueryCompiler_1.QueryCompiler(1000);
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Get the driver for a specific object
|
|
34
|
-
* @private
|
|
35
|
-
*/
|
|
36
|
-
getDriver(objectName) {
|
|
37
|
-
const obj = this.getSchema(objectName);
|
|
38
|
-
const datasourceName = obj.datasource || 'default';
|
|
39
|
-
const driver = this.datasources[datasourceName];
|
|
40
|
-
if (!driver) {
|
|
41
|
-
throw new Error(`Datasource '${datasourceName}' not found for object '${objectName}'`);
|
|
42
|
-
}
|
|
43
|
-
return driver;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Get the schema for an object
|
|
47
|
-
* @private
|
|
48
|
-
*/
|
|
49
|
-
getSchema(objectName) {
|
|
50
|
-
const obj = this.metadata.get('object', objectName);
|
|
51
|
-
if (!obj) {
|
|
52
|
-
throw new Error(`Object '${objectName}' not found in metadata`);
|
|
53
|
-
}
|
|
54
|
-
return obj;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Build QueryAST from UnifiedQuery
|
|
58
|
-
* @private
|
|
59
|
-
*/
|
|
60
|
-
buildQueryAST(objectName, query) {
|
|
61
|
-
const ast = this.queryBuilder.build(objectName, query);
|
|
62
|
-
const compiled = this.queryCompiler.compile(objectName, ast);
|
|
63
|
-
return compiled.ast;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Execute a find query
|
|
67
|
-
*
|
|
68
|
-
* @param objectName - The object to query
|
|
69
|
-
* @param query - The unified query
|
|
70
|
-
* @param options - Query execution options
|
|
71
|
-
* @returns Array of matching records
|
|
72
|
-
*/
|
|
73
|
-
async find(objectName, query = {}, options = {}) {
|
|
74
|
-
const driver = this.getDriver(objectName);
|
|
75
|
-
const startTime = options.profile ? Date.now() : 0;
|
|
76
|
-
// Build QueryAST
|
|
77
|
-
const ast = this.buildQueryAST(objectName, query);
|
|
78
|
-
// Execute query via driver
|
|
79
|
-
const driverOptions = {
|
|
80
|
-
transaction: options.transaction,
|
|
81
|
-
...options.driverOptions
|
|
82
|
-
};
|
|
83
|
-
let results;
|
|
84
|
-
let count;
|
|
85
|
-
if (driver.find) {
|
|
86
|
-
// Legacy driver interface
|
|
87
|
-
const result = await driver.find(objectName, query, driverOptions);
|
|
88
|
-
results = Array.isArray(result) ? result : ((result === null || result === void 0 ? void 0 : result.value) || []);
|
|
89
|
-
count = (typeof result === 'object' && !Array.isArray(result) && (result === null || result === void 0 ? void 0 : result.count) !== undefined) ? result.count : undefined;
|
|
90
|
-
}
|
|
91
|
-
else if (driver.executeQuery) {
|
|
92
|
-
// New DriverInterface
|
|
93
|
-
const result = await driver.executeQuery(ast, driverOptions);
|
|
94
|
-
results = result.value || [];
|
|
95
|
-
count = result.count;
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
throw new Error(`Driver does not support query execution`);
|
|
99
|
-
}
|
|
100
|
-
const executionTime = options.profile ? Date.now() - startTime : 0;
|
|
101
|
-
return {
|
|
102
|
-
value: results,
|
|
103
|
-
count,
|
|
104
|
-
profile: options.profile ? {
|
|
105
|
-
executionTime,
|
|
106
|
-
ast,
|
|
107
|
-
rowsScanned: results.length,
|
|
108
|
-
} : undefined
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Execute a findOne query by ID
|
|
113
|
-
*
|
|
114
|
-
* @param objectName - The object to query
|
|
115
|
-
* @param id - The record ID
|
|
116
|
-
* @param options - Query execution options
|
|
117
|
-
* @returns The matching record or undefined
|
|
118
|
-
*/
|
|
119
|
-
async findOne(objectName, id, options = {}) {
|
|
120
|
-
var _a;
|
|
121
|
-
const driver = this.getDriver(objectName);
|
|
122
|
-
const startTime = options.profile ? Date.now() : 0;
|
|
123
|
-
const driverOptions = {
|
|
124
|
-
transaction: options.transaction,
|
|
125
|
-
...options.driverOptions
|
|
126
|
-
};
|
|
127
|
-
let result;
|
|
128
|
-
if (driver.findOne) {
|
|
129
|
-
// Legacy driver interface
|
|
130
|
-
result = await driver.findOne(objectName, id, driverOptions);
|
|
131
|
-
}
|
|
132
|
-
else if (driver.get) {
|
|
133
|
-
// Alternative method name
|
|
134
|
-
result = await driver.get(objectName, String(id), driverOptions);
|
|
135
|
-
}
|
|
136
|
-
else if (driver.executeQuery) {
|
|
137
|
-
// Fallback to query with ID filter
|
|
138
|
-
const query = {
|
|
139
|
-
where: { _id: id }
|
|
140
|
-
};
|
|
141
|
-
const ast = this.buildQueryAST(objectName, query);
|
|
142
|
-
const queryResult = await driver.executeQuery(ast, driverOptions);
|
|
143
|
-
result = (_a = queryResult.value) === null || _a === void 0 ? void 0 : _a[0];
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
throw new Error(`Driver does not support findOne operation`);
|
|
147
|
-
}
|
|
148
|
-
const executionTime = options.profile ? Date.now() - startTime : 0;
|
|
149
|
-
return {
|
|
150
|
-
value: result,
|
|
151
|
-
profile: options.profile ? {
|
|
152
|
-
executionTime,
|
|
153
|
-
rowsScanned: result ? 1 : 0,
|
|
154
|
-
} : undefined
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Execute a count query
|
|
159
|
-
*
|
|
160
|
-
* @param objectName - The object to query
|
|
161
|
-
* @param where - Optional filter condition
|
|
162
|
-
* @param options - Query execution options
|
|
163
|
-
* @returns Count of matching records
|
|
164
|
-
*/
|
|
165
|
-
async count(objectName, where, options = {}) {
|
|
166
|
-
var _a, _b, _c;
|
|
167
|
-
const driver = this.getDriver(objectName);
|
|
168
|
-
const startTime = options.profile ? Date.now() : 0;
|
|
169
|
-
const query = where ? { where } : {};
|
|
170
|
-
const ast = this.buildQueryAST(objectName, query);
|
|
171
|
-
const driverOptions = {
|
|
172
|
-
transaction: options.transaction,
|
|
173
|
-
...options.driverOptions
|
|
174
|
-
};
|
|
175
|
-
let count;
|
|
176
|
-
if (driver.count) {
|
|
177
|
-
// Legacy driver interface
|
|
178
|
-
count = await driver.count(objectName, where || {}, driverOptions);
|
|
179
|
-
}
|
|
180
|
-
else if (driver.executeQuery) {
|
|
181
|
-
// Use executeQuery and count results
|
|
182
|
-
// Note: This is inefficient for large datasets
|
|
183
|
-
// Ideally, driver should support count-specific optimization
|
|
184
|
-
const result = await driver.executeQuery(ast, driverOptions);
|
|
185
|
-
count = (_c = (_a = result.count) !== null && _a !== void 0 ? _a : (_b = result.value) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0;
|
|
186
|
-
}
|
|
187
|
-
else {
|
|
188
|
-
throw new Error(`Driver does not support count operation`);
|
|
189
|
-
}
|
|
190
|
-
const executionTime = options.profile ? Date.now() - startTime : 0;
|
|
191
|
-
return {
|
|
192
|
-
value: count,
|
|
193
|
-
profile: options.profile ? {
|
|
194
|
-
executionTime,
|
|
195
|
-
ast,
|
|
196
|
-
} : undefined
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* Execute an aggregate query
|
|
201
|
-
*
|
|
202
|
-
* @param objectName - The object to query
|
|
203
|
-
* @param query - The aggregation query using UnifiedQuery format
|
|
204
|
-
* @param options - Query execution options
|
|
205
|
-
* @returns Aggregation results
|
|
206
|
-
*/
|
|
207
|
-
async aggregate(objectName, query, options = {}) {
|
|
208
|
-
const driver = this.getDriver(objectName);
|
|
209
|
-
const startTime = options.profile ? Date.now() : 0;
|
|
210
|
-
const driverOptions = {
|
|
211
|
-
transaction: options.transaction,
|
|
212
|
-
...options.driverOptions
|
|
213
|
-
};
|
|
214
|
-
let results;
|
|
215
|
-
if (driver.aggregate) {
|
|
216
|
-
// Driver supports aggregation
|
|
217
|
-
results = await driver.aggregate(objectName, query, driverOptions);
|
|
218
|
-
}
|
|
219
|
-
else {
|
|
220
|
-
// Driver doesn't support aggregation
|
|
221
|
-
throw new Error(`Driver does not support aggregate operations. Consider using a driver that supports aggregation.`);
|
|
222
|
-
}
|
|
223
|
-
const executionTime = options.profile ? Date.now() - startTime : 0;
|
|
224
|
-
return {
|
|
225
|
-
value: results,
|
|
226
|
-
profile: options.profile ? {
|
|
227
|
-
executionTime,
|
|
228
|
-
rowsScanned: results.length,
|
|
229
|
-
} : undefined
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
/**
|
|
233
|
-
* Execute a direct SQL/query passthrough
|
|
234
|
-
*
|
|
235
|
-
* This bypasses ObjectQL's query builder and executes raw queries.
|
|
236
|
-
* Use with caution as it bypasses security and validation.
|
|
237
|
-
*
|
|
238
|
-
* @param objectName - The object (determines which datasource to use)
|
|
239
|
-
* @param queryString - Raw query string (SQL, MongoDB query, etc.)
|
|
240
|
-
* @param params - Query parameters (for parameterized queries)
|
|
241
|
-
* @param options - Query execution options
|
|
242
|
-
* @returns Query results
|
|
243
|
-
*/
|
|
244
|
-
async directQuery(objectName, queryString, params, options = {}) {
|
|
245
|
-
const driver = this.getDriver(objectName);
|
|
246
|
-
const startTime = options.profile ? Date.now() : 0;
|
|
247
|
-
const driverOptions = {
|
|
248
|
-
transaction: options.transaction,
|
|
249
|
-
...options.driverOptions
|
|
250
|
-
};
|
|
251
|
-
let results;
|
|
252
|
-
if (driver.directQuery) {
|
|
253
|
-
results = await driver.directQuery(queryString, params);
|
|
254
|
-
}
|
|
255
|
-
else if (driver.query) {
|
|
256
|
-
// Alternative method name
|
|
257
|
-
results = await driver.query(queryString, params);
|
|
258
|
-
}
|
|
259
|
-
else {
|
|
260
|
-
throw new Error(`Driver does not support direct query execution`);
|
|
261
|
-
}
|
|
262
|
-
const executionTime = options.profile ? Date.now() - startTime : 0;
|
|
263
|
-
return {
|
|
264
|
-
value: results,
|
|
265
|
-
profile: options.profile ? {
|
|
266
|
-
executionTime,
|
|
267
|
-
} : undefined
|
|
268
|
-
};
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
exports.QueryService = QueryService;
|
|
272
|
-
//# sourceMappingURL=query-service.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"query-service.js","sourceRoot":"","sources":["../../src/query/query-service.ts"],"names":[],"mappings":"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"}
|
package/src/ai/index.ts
DELETED
package/src/ai/registry.ts
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ObjectQL - AI Runtime Registry
|
|
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
|
-
AiRegistry,
|
|
11
|
-
AiModelDefinition,
|
|
12
|
-
ModelRegistry,
|
|
13
|
-
PromptRegistry,
|
|
14
|
-
PromptTemplate,
|
|
15
|
-
} from '@objectql/types';
|
|
16
|
-
|
|
17
|
-
const DEFAULT_PROMPT_VERSION = 'latest';
|
|
18
|
-
|
|
19
|
-
export class InMemoryModelRegistry implements ModelRegistry {
|
|
20
|
-
private readonly models = new Map<string, AiModelDefinition>();
|
|
21
|
-
|
|
22
|
-
register(model: AiModelDefinition): void {
|
|
23
|
-
this.models.set(model.id, model);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
get(id: string): AiModelDefinition | undefined {
|
|
27
|
-
return this.models.get(id);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
list(): readonly AiModelDefinition[] {
|
|
31
|
-
return Array.from(this.models.values());
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
remove(id: string): void {
|
|
35
|
-
this.models.delete(id);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export class InMemoryPromptRegistry implements PromptRegistry {
|
|
40
|
-
private readonly prompts = new Map<string, Map<string, PromptTemplate>>();
|
|
41
|
-
|
|
42
|
-
register(template: PromptTemplate): void {
|
|
43
|
-
const version = template.version ?? DEFAULT_PROMPT_VERSION;
|
|
44
|
-
const byId = this.prompts.get(template.id) ?? new Map<string, PromptTemplate>();
|
|
45
|
-
byId.set(version, { ...template, version });
|
|
46
|
-
this.prompts.set(template.id, byId);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
get(id: string, version?: string): PromptTemplate | undefined {
|
|
50
|
-
const byId = this.prompts.get(id);
|
|
51
|
-
if (!byId) return undefined;
|
|
52
|
-
if (version) return byId.get(version);
|
|
53
|
-
if (byId.has(DEFAULT_PROMPT_VERSION)) return byId.get(DEFAULT_PROMPT_VERSION);
|
|
54
|
-
return byId.values().next().value;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
list(id?: string): readonly PromptTemplate[] {
|
|
58
|
-
if (id) {
|
|
59
|
-
return Array.from(this.prompts.get(id)?.values() ?? []);
|
|
60
|
-
}
|
|
61
|
-
return Array.from(this.prompts.values()).flatMap(map => Array.from(map.values()));
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
remove(id: string, version?: string): void {
|
|
65
|
-
if (!version) {
|
|
66
|
-
this.prompts.delete(id);
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
const byId = this.prompts.get(id);
|
|
70
|
-
if (!byId) return;
|
|
71
|
-
byId.delete(version);
|
|
72
|
-
if (byId.size === 0) {
|
|
73
|
-
this.prompts.delete(id);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export const createDefaultAiRegistry = (): AiRegistry => ({
|
|
79
|
-
models: new InMemoryModelRegistry(),
|
|
80
|
-
prompts: new InMemoryPromptRegistry(),
|
|
81
|
-
});
|
package/src/gateway.ts
DELETED
|
@@ -1,105 +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 { ApiRequest, ApiResponse, GatewayProtocol, Logger, ConsoleLogger } from '@objectql/types';
|
|
10
|
-
|
|
11
|
-
export type RequestTransformer = (request: ApiRequest) => Promise<ApiRequest>;
|
|
12
|
-
export type ResponseTransformer = (response: ApiResponse) => Promise<ApiResponse>;
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Unified API Gateway
|
|
16
|
-
* Routtes generic API requests to specific protocol implementations
|
|
17
|
-
*/
|
|
18
|
-
export class ObjectGateway {
|
|
19
|
-
private protocols: GatewayProtocol[] = [];
|
|
20
|
-
private requestTransforms: RequestTransformer[] = [];
|
|
21
|
-
private responseTransforms: ResponseTransformer[] = [];
|
|
22
|
-
private logger: Logger;
|
|
23
|
-
|
|
24
|
-
constructor(protocols: GatewayProtocol[] = [], logger?: Logger) {
|
|
25
|
-
this.protocols = protocols;
|
|
26
|
-
this.logger = logger ?? new ConsoleLogger({ name: '@objectql/gateway', level: 'info' });
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Register a new protocol handler
|
|
31
|
-
*/
|
|
32
|
-
registerProtocol(protocol: GatewayProtocol) {
|
|
33
|
-
this.protocols.push(protocol);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Add a request transformer (middleware)
|
|
38
|
-
*/
|
|
39
|
-
addRequestTransform(transformer: RequestTransformer) {
|
|
40
|
-
this.requestTransforms.push(transformer);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Add a response transformer (middleware)
|
|
45
|
-
*/
|
|
46
|
-
addResponseTransform(transformer: ResponseTransformer) {
|
|
47
|
-
this.responseTransforms.push(transformer);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Handle an incoming API request
|
|
52
|
-
*/
|
|
53
|
-
async handle(request: ApiRequest): Promise<ApiResponse> {
|
|
54
|
-
let req = request;
|
|
55
|
-
|
|
56
|
-
// 1. Apply Request Transforms
|
|
57
|
-
for (const transform of this.requestTransforms) {
|
|
58
|
-
req = await transform(req);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// 2. Find matching protocol
|
|
62
|
-
const protocol = this.protocols.find(p => p.route(req));
|
|
63
|
-
|
|
64
|
-
if (!protocol) {
|
|
65
|
-
return {
|
|
66
|
-
status: 404,
|
|
67
|
-
headers: { 'Content-Type': 'application/json' },
|
|
68
|
-
body: {
|
|
69
|
-
error: {
|
|
70
|
-
code: 'PROTOCOL_NOT_FOUND',
|
|
71
|
-
message: `No protocol found to handle path: ${req.path}`
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
let response: ApiResponse;
|
|
78
|
-
|
|
79
|
-
// 3. Delegate to protocol
|
|
80
|
-
try {
|
|
81
|
-
response = await protocol.handle(req);
|
|
82
|
-
} catch (error: any) {
|
|
83
|
-
this.logger.error(`Error in ${protocol.name}`, error as Error, {
|
|
84
|
-
protocol: protocol.name,
|
|
85
|
-
});
|
|
86
|
-
response = {
|
|
87
|
-
status: 500,
|
|
88
|
-
headers: { 'Content-Type': 'application/json' },
|
|
89
|
-
body: {
|
|
90
|
-
error: {
|
|
91
|
-
code: 'INTERNAL_ERROR',
|
|
92
|
-
message: error.message || 'Internal Gateway Error'
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// 4. Apply Response Transforms
|
|
99
|
-
for (const transform of this.responseTransforms) {
|
|
100
|
-
response = await transform(response);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return response;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
@@ -1,193 +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 { Logger, ConsoleLogger } from '@objectql/types';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Hook definition
|
|
13
|
-
*/
|
|
14
|
-
export interface Hook {
|
|
15
|
-
pattern: string;
|
|
16
|
-
handler: (context: any) => Promise<void> | void;
|
|
17
|
-
packageName?: string;
|
|
18
|
-
priority?: number;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Compiled Hook Manager
|
|
23
|
-
*
|
|
24
|
-
* Improvement: Pre-compiles hook pipelines by event pattern at registration time.
|
|
25
|
-
* No runtime pattern matching required.
|
|
26
|
-
*
|
|
27
|
-
* Expected: 5x faster hook execution, parallel async support
|
|
28
|
-
*/
|
|
29
|
-
export class CompiledHookManager {
|
|
30
|
-
// Direct event -> hooks mapping (no pattern matching at runtime)
|
|
31
|
-
private pipelines = new Map<string, Hook[]>();
|
|
32
|
-
|
|
33
|
-
// Keep track of all registered hooks for management
|
|
34
|
-
private allHooks = new Map<string, Hook>();
|
|
35
|
-
|
|
36
|
-
// Structured logger
|
|
37
|
-
private logger: Logger = new ConsoleLogger({ name: '@objectql/hook-manager', level: 'warn' });
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Expand a pattern like "before*" to all matching events
|
|
41
|
-
*/
|
|
42
|
-
private expandPattern(pattern: string): string[] {
|
|
43
|
-
// Common event patterns
|
|
44
|
-
const eventTypes = [
|
|
45
|
-
'beforeCreate', 'afterCreate',
|
|
46
|
-
'beforeUpdate', 'afterUpdate',
|
|
47
|
-
'beforeDelete', 'afterDelete',
|
|
48
|
-
'beforeFind', 'afterFind',
|
|
49
|
-
'beforeCount', 'afterCount'
|
|
50
|
-
];
|
|
51
|
-
|
|
52
|
-
// Handle wildcards
|
|
53
|
-
if (pattern === '*') {
|
|
54
|
-
return eventTypes;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (pattern.includes('*')) {
|
|
58
|
-
// Use global replace to handle all occurrences of *
|
|
59
|
-
const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$');
|
|
60
|
-
return eventTypes.filter(event => regex.test(event));
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Exact match
|
|
64
|
-
return [pattern];
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Register a hook - pre-groups by event pattern
|
|
69
|
-
*/
|
|
70
|
-
registerHook(event: string, objectName: string, handler: any, packageName?: string): void {
|
|
71
|
-
const hook: Hook = {
|
|
72
|
-
pattern: `${event}:${objectName}`,
|
|
73
|
-
handler,
|
|
74
|
-
packageName,
|
|
75
|
-
priority: 0
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
// Store in all hooks registry
|
|
79
|
-
const hookId = `${event}:${objectName}:${Date.now()}`;
|
|
80
|
-
this.allHooks.set(hookId, hook);
|
|
81
|
-
|
|
82
|
-
// Expand event patterns
|
|
83
|
-
const events = this.expandPattern(event);
|
|
84
|
-
|
|
85
|
-
// Handle wildcard object names
|
|
86
|
-
if (objectName === '*') {
|
|
87
|
-
for (const concreteEvent of events) {
|
|
88
|
-
// Register for all potential object names
|
|
89
|
-
// Since we don't know all object names upfront, we keep a special '*' pipeline
|
|
90
|
-
const wildcardKey = `${concreteEvent}:*`;
|
|
91
|
-
if (!this.pipelines.has(wildcardKey)) {
|
|
92
|
-
this.pipelines.set(wildcardKey, []);
|
|
93
|
-
}
|
|
94
|
-
this.pipelines.get(wildcardKey)!.push(hook);
|
|
95
|
-
}
|
|
96
|
-
} else {
|
|
97
|
-
// Pre-group hooks by concrete event names (only for non-wildcard objects)
|
|
98
|
-
for (const concreteEvent of events) {
|
|
99
|
-
const key = `${concreteEvent}:${objectName}`;
|
|
100
|
-
if (!this.pipelines.has(key)) {
|
|
101
|
-
this.pipelines.set(key, []);
|
|
102
|
-
}
|
|
103
|
-
this.pipelines.get(key)!.push(hook);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Run hooks for an event - direct lookup, no pattern matching
|
|
110
|
-
*/
|
|
111
|
-
async runHooks(event: string, objectName: string, context: any): Promise<void> {
|
|
112
|
-
const key = `${event}:${objectName}`;
|
|
113
|
-
const wildcardKey = `${event}:*`;
|
|
114
|
-
|
|
115
|
-
// Collect all applicable hooks
|
|
116
|
-
const hooks: Hook[] = [];
|
|
117
|
-
|
|
118
|
-
// Add object-specific hooks
|
|
119
|
-
const objectHooks = this.pipelines.get(key);
|
|
120
|
-
if (objectHooks) {
|
|
121
|
-
hooks.push(...objectHooks);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Add wildcard hooks
|
|
125
|
-
const wildcardHooks = this.pipelines.get(wildcardKey);
|
|
126
|
-
if (wildcardHooks) {
|
|
127
|
-
hooks.push(...wildcardHooks);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (hooks.length === 0) {
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Sort by priority (higher priority first)
|
|
135
|
-
hooks.sort((a, b) => (b.priority || 0) - (a.priority || 0));
|
|
136
|
-
|
|
137
|
-
// Execute hooks in parallel for better performance
|
|
138
|
-
// Note: If order matters, change to sequential execution
|
|
139
|
-
await Promise.all(hooks.map(hook => {
|
|
140
|
-
try {
|
|
141
|
-
return Promise.resolve(hook.handler(context));
|
|
142
|
-
} catch (error) {
|
|
143
|
-
this.logger.error(`Hook execution failed for ${event}:${objectName}`, error as Error, {
|
|
144
|
-
event,
|
|
145
|
-
objectName,
|
|
146
|
-
});
|
|
147
|
-
return Promise.resolve();
|
|
148
|
-
}
|
|
149
|
-
}));
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Remove all hooks from a package
|
|
154
|
-
*/
|
|
155
|
-
removePackage(packageName: string): void {
|
|
156
|
-
// Remove from all hooks registry
|
|
157
|
-
const hooksToRemove: string[] = [];
|
|
158
|
-
for (const [hookId, hook] of this.allHooks.entries()) {
|
|
159
|
-
if (hook.packageName === packageName) {
|
|
160
|
-
hooksToRemove.push(hookId);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
hooksToRemove.forEach(id => this.allHooks.delete(id));
|
|
164
|
-
|
|
165
|
-
// Remove from pipelines
|
|
166
|
-
for (const [key, hooks] of this.pipelines.entries()) {
|
|
167
|
-
const filtered = hooks.filter(h => h.packageName !== packageName);
|
|
168
|
-
if (filtered.length === 0) {
|
|
169
|
-
this.pipelines.delete(key);
|
|
170
|
-
} else {
|
|
171
|
-
this.pipelines.set(key, filtered);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Clear all hooks
|
|
178
|
-
*/
|
|
179
|
-
clear(): void {
|
|
180
|
-
this.pipelines.clear();
|
|
181
|
-
this.allHooks.clear();
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Get statistics about registered hooks
|
|
186
|
-
*/
|
|
187
|
-
getStats(): { totalHooks: number; totalPipelines: number } {
|
|
188
|
-
return {
|
|
189
|
-
totalHooks: this.allHooks.size,
|
|
190
|
-
totalPipelines: this.pipelines.size
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
}
|