@objectql/core 3.0.1 → 4.0.0
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/IMPLEMENTATION_STATUS.md +364 -0
- package/README.md +31 -9
- package/RUNTIME_INTEGRATION.md +391 -0
- package/dist/ai-agent.d.ts +4 -3
- package/dist/ai-agent.js +10 -3
- package/dist/ai-agent.js.map +1 -1
- package/dist/app.d.ts +29 -6
- package/dist/app.js +117 -58
- package/dist/app.js.map +1 -1
- package/dist/formula-engine.d.ts +7 -0
- package/dist/formula-engine.js +9 -2
- package/dist/formula-engine.js.map +1 -1
- package/dist/formula-plugin.d.ts +52 -0
- package/dist/formula-plugin.js +107 -0
- package/dist/formula-plugin.js.map +1 -0
- package/dist/index.d.ts +13 -3
- package/dist/index.js +14 -3
- package/dist/index.js.map +1 -1
- package/dist/plugin.d.ts +89 -0
- package/dist/plugin.js +99 -0
- package/dist/plugin.js.map +1 -0
- package/dist/query/filter-translator.d.ts +37 -0
- package/dist/query/filter-translator.js +135 -0
- package/dist/query/filter-translator.js.map +1 -0
- package/dist/query/index.d.ts +22 -0
- package/dist/query/index.js +39 -0
- package/dist/query/index.js.map +1 -0
- package/dist/query/query-analyzer.d.ts +186 -0
- package/dist/query/query-analyzer.js +349 -0
- package/dist/query/query-analyzer.js.map +1 -0
- package/dist/query/query-builder.d.ts +27 -0
- package/dist/query/query-builder.js +71 -0
- package/dist/query/query-builder.js.map +1 -0
- package/dist/query/query-service.d.ts +150 -0
- package/dist/query/query-service.js +268 -0
- package/dist/query/query-service.js.map +1 -0
- package/dist/repository.d.ts +23 -2
- package/dist/repository.js +62 -13
- package/dist/repository.js.map +1 -1
- package/dist/util.d.ts +7 -0
- package/dist/util.js +18 -3
- package/dist/util.js.map +1 -1
- package/dist/validator-plugin.d.ts +56 -0
- package/dist/validator-plugin.js +106 -0
- package/dist/validator-plugin.js.map +1 -0
- package/dist/validator.d.ts +7 -0
- package/dist/validator.js +10 -8
- package/dist/validator.js.map +1 -1
- package/jest.config.js +16 -0
- package/package.json +8 -5
- package/src/ai-agent.ts +8 -0
- package/src/app.ts +136 -72
- package/src/formula-engine.ts +8 -0
- package/src/formula-plugin.ts +141 -0
- package/src/index.ts +25 -3
- package/src/plugin.ts +179 -0
- package/src/query/filter-translator.ts +147 -0
- package/src/query/index.ts +24 -0
- package/src/query/query-analyzer.ts +535 -0
- package/src/query/query-builder.ts +80 -0
- package/src/query/query-service.ts +392 -0
- package/src/repository.ts +81 -17
- package/src/util.ts +19 -3
- package/src/validator-plugin.ts +140 -0
- package/src/validator.ts +12 -5
- package/test/__mocks__/@objectstack/runtime.ts +255 -0
- package/test/app.test.ts +23 -35
- package/test/filter-syntax.test.ts +233 -0
- package/test/formula-engine.test.ts +8 -0
- package/test/formula-integration.test.ts +8 -0
- package/test/formula-plugin.test.ts +197 -0
- package/test/introspection.test.ts +8 -0
- package/test/mock-driver.ts +8 -0
- package/test/plugin-integration.test.ts +213 -0
- package/test/repository-validation.test.ts +8 -0
- package/test/repository.test.ts +8 -0
- package/test/util.test.ts +9 -1
- package/test/utils.ts +8 -0
- package/test/validator-plugin.test.ts +126 -0
- package/test/validator.test.ts +8 -0
- package/tsconfig.json +9 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/action.d.ts +0 -7
- package/dist/action.js +0 -23
- package/dist/action.js.map +0 -1
- package/dist/hook.d.ts +0 -8
- package/dist/hook.js +0 -25
- package/dist/hook.js.map +0 -1
- package/dist/object.d.ts +0 -3
- package/dist/object.js +0 -28
- package/dist/object.js.map +0 -1
- package/src/action.ts +0 -40
- package/src/hook.ts +0 -42
- package/src/object.ts +0 -26
- package/test/action.test.ts +0 -276
- package/test/hook.test.ts +0 -343
- package/test/object.test.ts +0 -183
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectQL Plugin
|
|
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
|
+
import type { RuntimePlugin, RuntimeContext } from '@objectstack/runtime';
|
|
9
|
+
import { ValidatorPluginConfig } from './validator-plugin';
|
|
10
|
+
import { FormulaPluginConfig } from './formula-plugin';
|
|
11
|
+
import type { Driver } from '@objectql/types';
|
|
12
|
+
/**
|
|
13
|
+
* Configuration for the ObjectQL Plugin
|
|
14
|
+
*/
|
|
15
|
+
export interface ObjectQLPluginConfig {
|
|
16
|
+
/**
|
|
17
|
+
* Enable repository pattern for data access
|
|
18
|
+
* @default true
|
|
19
|
+
*/
|
|
20
|
+
enableRepository?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Enable validation engine
|
|
23
|
+
* @default true
|
|
24
|
+
*/
|
|
25
|
+
enableValidator?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Validator plugin configuration
|
|
28
|
+
* Only used if enableValidator is not false
|
|
29
|
+
*/
|
|
30
|
+
validatorConfig?: ValidatorPluginConfig;
|
|
31
|
+
/**
|
|
32
|
+
* Enable formula engine
|
|
33
|
+
* @default true
|
|
34
|
+
*/
|
|
35
|
+
enableFormulas?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Formula plugin configuration
|
|
38
|
+
* Only used if enableFormulas is not false
|
|
39
|
+
*/
|
|
40
|
+
formulaConfig?: FormulaPluginConfig;
|
|
41
|
+
/**
|
|
42
|
+
* Enable AI integration
|
|
43
|
+
* @default true
|
|
44
|
+
*/
|
|
45
|
+
enableAI?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Enable query service and analyzer
|
|
48
|
+
* @default true
|
|
49
|
+
*/
|
|
50
|
+
enableQueryService?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Datasources for query service
|
|
53
|
+
* Required if enableQueryService is true
|
|
54
|
+
*/
|
|
55
|
+
datasources?: Record<string, Driver>;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* ObjectQL Plugin
|
|
59
|
+
*
|
|
60
|
+
* Implements the RuntimePlugin interface from @objectstack/runtime
|
|
61
|
+
* to provide ObjectQL's enhanced features (Repository, Validator, Formula, AI)
|
|
62
|
+
* on top of the ObjectStack kernel.
|
|
63
|
+
*/
|
|
64
|
+
export declare class ObjectQLPlugin implements RuntimePlugin {
|
|
65
|
+
private config;
|
|
66
|
+
name: string;
|
|
67
|
+
version: string;
|
|
68
|
+
constructor(config?: ObjectQLPluginConfig);
|
|
69
|
+
/**
|
|
70
|
+
* Install the plugin into the kernel
|
|
71
|
+
* This is called during kernel initialization
|
|
72
|
+
*/
|
|
73
|
+
install(ctx: RuntimeContext): Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Called when the kernel starts
|
|
76
|
+
* This is the initialization phase
|
|
77
|
+
*/
|
|
78
|
+
onStart(ctx: RuntimeContext): Promise<void>;
|
|
79
|
+
/**
|
|
80
|
+
* Register the Repository pattern
|
|
81
|
+
* @private
|
|
82
|
+
*/
|
|
83
|
+
private registerRepository;
|
|
84
|
+
/**
|
|
85
|
+
* Register AI integration
|
|
86
|
+
* @private
|
|
87
|
+
*/
|
|
88
|
+
private registerAI;
|
|
89
|
+
}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ObjectQL Plugin
|
|
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.ObjectQLPlugin = void 0;
|
|
11
|
+
const validator_plugin_1 = require("./validator-plugin");
|
|
12
|
+
const formula_plugin_1 = require("./formula-plugin");
|
|
13
|
+
const query_service_1 = require("./query/query-service");
|
|
14
|
+
const query_analyzer_1 = require("./query/query-analyzer");
|
|
15
|
+
/**
|
|
16
|
+
* ObjectQL Plugin
|
|
17
|
+
*
|
|
18
|
+
* Implements the RuntimePlugin interface from @objectstack/runtime
|
|
19
|
+
* to provide ObjectQL's enhanced features (Repository, Validator, Formula, AI)
|
|
20
|
+
* on top of the ObjectStack kernel.
|
|
21
|
+
*/
|
|
22
|
+
class ObjectQLPlugin {
|
|
23
|
+
constructor(config = {}) {
|
|
24
|
+
this.config = config;
|
|
25
|
+
this.name = '@objectql/core';
|
|
26
|
+
this.version = '4.0.0';
|
|
27
|
+
// Set defaults
|
|
28
|
+
this.config = {
|
|
29
|
+
enableRepository: true,
|
|
30
|
+
enableValidator: true,
|
|
31
|
+
enableFormulas: true,
|
|
32
|
+
enableAI: true,
|
|
33
|
+
enableQueryService: true,
|
|
34
|
+
...config
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Install the plugin into the kernel
|
|
39
|
+
* This is called during kernel initialization
|
|
40
|
+
*/
|
|
41
|
+
async install(ctx) {
|
|
42
|
+
console.log(`[${this.name}] Installing plugin...`);
|
|
43
|
+
const kernel = ctx.engine;
|
|
44
|
+
// Register QueryService and QueryAnalyzer if enabled
|
|
45
|
+
if (this.config.enableQueryService !== false && this.config.datasources) {
|
|
46
|
+
const queryService = new query_service_1.QueryService(this.config.datasources, kernel.metadata);
|
|
47
|
+
kernel.queryService = queryService;
|
|
48
|
+
const queryAnalyzer = new query_analyzer_1.QueryAnalyzer(queryService, kernel.metadata);
|
|
49
|
+
kernel.queryAnalyzer = queryAnalyzer;
|
|
50
|
+
console.log(`[${this.name}] QueryService and QueryAnalyzer registered`);
|
|
51
|
+
}
|
|
52
|
+
// Register components based on configuration
|
|
53
|
+
if (this.config.enableRepository !== false) {
|
|
54
|
+
await this.registerRepository(ctx.engine);
|
|
55
|
+
}
|
|
56
|
+
// Install validator plugin if enabled
|
|
57
|
+
if (this.config.enableValidator !== false) {
|
|
58
|
+
const validatorPlugin = new validator_plugin_1.ValidatorPlugin(this.config.validatorConfig || {});
|
|
59
|
+
await validatorPlugin.install(ctx);
|
|
60
|
+
}
|
|
61
|
+
// Install formula plugin if enabled
|
|
62
|
+
if (this.config.enableFormulas !== false) {
|
|
63
|
+
const formulaPlugin = new formula_plugin_1.FormulaPlugin(this.config.formulaConfig || {});
|
|
64
|
+
await formulaPlugin.install(ctx);
|
|
65
|
+
}
|
|
66
|
+
if (this.config.enableAI !== false) {
|
|
67
|
+
await this.registerAI(ctx.engine);
|
|
68
|
+
}
|
|
69
|
+
console.log(`[${this.name}] Plugin installed successfully`);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Called when the kernel starts
|
|
73
|
+
* This is the initialization phase
|
|
74
|
+
*/
|
|
75
|
+
async onStart(ctx) {
|
|
76
|
+
console.log(`[${this.name}] Starting plugin...`);
|
|
77
|
+
// Additional startup logic can be added here
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Register the Repository pattern
|
|
81
|
+
* @private
|
|
82
|
+
*/
|
|
83
|
+
async registerRepository(kernel) {
|
|
84
|
+
// TODO: Implement repository registration
|
|
85
|
+
// For now, this is a placeholder to establish the structure
|
|
86
|
+
console.log(`[${this.name}] Repository pattern registered`);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Register AI integration
|
|
90
|
+
* @private
|
|
91
|
+
*/
|
|
92
|
+
async registerAI(kernel) {
|
|
93
|
+
// TODO: Implement AI registration
|
|
94
|
+
// For now, this is a placeholder to establish the structure
|
|
95
|
+
console.log(`[${this.name}] AI integration registered`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
exports.ObjectQLPlugin = ObjectQLPlugin;
|
|
99
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
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
|
+
import type { Filter } from '@objectql/types';
|
|
9
|
+
import type { FilterNode } from '@objectstack/spec';
|
|
10
|
+
/**
|
|
11
|
+
* Filter Translator
|
|
12
|
+
*
|
|
13
|
+
* Translates ObjectQL Filter (FilterCondition) to ObjectStack FilterNode format.
|
|
14
|
+
* Converts modern object-based syntax to legacy array-based syntax for backward compatibility.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* Input: { age: { $gte: 18 }, $or: [{ status: "active" }, { role: "admin" }] }
|
|
18
|
+
* Output: [["age", ">=", 18], "or", [["status", "=", "active"], "or", ["role", "=", "admin"]]]
|
|
19
|
+
*/
|
|
20
|
+
export declare class FilterTranslator {
|
|
21
|
+
/**
|
|
22
|
+
* Translate filters from ObjectQL format to ObjectStack FilterNode format
|
|
23
|
+
*/
|
|
24
|
+
translate(filters?: Filter): FilterNode | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Recursively converts FilterCondition to FilterNode array format
|
|
27
|
+
*/
|
|
28
|
+
private convertToNode;
|
|
29
|
+
/**
|
|
30
|
+
* Interleaves filter nodes with a logical operator
|
|
31
|
+
*/
|
|
32
|
+
private interleaveWithOperator;
|
|
33
|
+
/**
|
|
34
|
+
* Maps modern $-prefixed operators to legacy format
|
|
35
|
+
*/
|
|
36
|
+
private mapOperatorToLegacy;
|
|
37
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ObjectQL
|
|
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.FilterTranslator = void 0;
|
|
11
|
+
const types_1 = require("@objectql/types");
|
|
12
|
+
/**
|
|
13
|
+
* Filter Translator
|
|
14
|
+
*
|
|
15
|
+
* Translates ObjectQL Filter (FilterCondition) to ObjectStack FilterNode format.
|
|
16
|
+
* Converts modern object-based syntax to legacy array-based syntax for backward compatibility.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* Input: { age: { $gte: 18 }, $or: [{ status: "active" }, { role: "admin" }] }
|
|
20
|
+
* Output: [["age", ">=", 18], "or", [["status", "=", "active"], "or", ["role", "=", "admin"]]]
|
|
21
|
+
*/
|
|
22
|
+
class FilterTranslator {
|
|
23
|
+
/**
|
|
24
|
+
* Translate filters from ObjectQL format to ObjectStack FilterNode format
|
|
25
|
+
*/
|
|
26
|
+
translate(filters) {
|
|
27
|
+
if (!filters) {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
// Backward compatibility: if it's already an array (old format), pass through
|
|
31
|
+
if (Array.isArray(filters)) {
|
|
32
|
+
return filters;
|
|
33
|
+
}
|
|
34
|
+
// If it's an empty object, return undefined
|
|
35
|
+
if (typeof filters === 'object' && Object.keys(filters).length === 0) {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
return this.convertToNode(filters);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Recursively converts FilterCondition to FilterNode array format
|
|
42
|
+
*/
|
|
43
|
+
convertToNode(filter) {
|
|
44
|
+
const nodes = [];
|
|
45
|
+
// Process logical operators first
|
|
46
|
+
if (filter.$and) {
|
|
47
|
+
const andNodes = filter.$and.map((f) => this.convertToNode(f));
|
|
48
|
+
nodes.push(...this.interleaveWithOperator(andNodes, 'and'));
|
|
49
|
+
}
|
|
50
|
+
if (filter.$or) {
|
|
51
|
+
const orNodes = filter.$or.map((f) => this.convertToNode(f));
|
|
52
|
+
if (nodes.length > 0) {
|
|
53
|
+
nodes.push('and');
|
|
54
|
+
}
|
|
55
|
+
nodes.push(...this.interleaveWithOperator(orNodes, 'or'));
|
|
56
|
+
}
|
|
57
|
+
// Note: $not operator is not currently supported in the legacy FilterNode format
|
|
58
|
+
if (filter.$not) {
|
|
59
|
+
throw new types_1.ObjectQLError({
|
|
60
|
+
code: 'UNSUPPORTED_OPERATOR',
|
|
61
|
+
message: '$not operator is not supported. Use $ne for field negation instead.'
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
// Process field conditions
|
|
65
|
+
for (const [field, value] of Object.entries(filter)) {
|
|
66
|
+
if (field.startsWith('$')) {
|
|
67
|
+
continue; // Skip logical operators (already processed)
|
|
68
|
+
}
|
|
69
|
+
if (nodes.length > 0) {
|
|
70
|
+
nodes.push('and');
|
|
71
|
+
}
|
|
72
|
+
// Handle field value
|
|
73
|
+
if (value === null || value === undefined) {
|
|
74
|
+
nodes.push([field, '=', value]);
|
|
75
|
+
}
|
|
76
|
+
else if (typeof value === 'object' && !Array.isArray(value) && !(value instanceof Date)) {
|
|
77
|
+
// Explicit operators - multiple operators on same field are AND-ed together
|
|
78
|
+
const entries = Object.entries(value);
|
|
79
|
+
for (let i = 0; i < entries.length; i++) {
|
|
80
|
+
const [op, opValue] = entries[i];
|
|
81
|
+
// Add 'and' before each operator (except the very first node)
|
|
82
|
+
if (nodes.length > 0 || i > 0) {
|
|
83
|
+
nodes.push('and');
|
|
84
|
+
}
|
|
85
|
+
const legacyOp = this.mapOperatorToLegacy(op);
|
|
86
|
+
nodes.push([field, legacyOp, opValue]);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
// Implicit equality
|
|
91
|
+
nodes.push([field, '=', value]);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Return as FilterNode (type assertion for backward compatibility)
|
|
95
|
+
return (nodes.length === 1 ? nodes[0] : nodes);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Interleaves filter nodes with a logical operator
|
|
99
|
+
*/
|
|
100
|
+
interleaveWithOperator(nodes, operator) {
|
|
101
|
+
if (nodes.length === 0)
|
|
102
|
+
return [];
|
|
103
|
+
if (nodes.length === 1)
|
|
104
|
+
return [nodes[0]];
|
|
105
|
+
const result = [nodes[0]];
|
|
106
|
+
for (let i = 1; i < nodes.length; i++) {
|
|
107
|
+
result.push(operator, nodes[i]);
|
|
108
|
+
}
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Maps modern $-prefixed operators to legacy format
|
|
113
|
+
*/
|
|
114
|
+
mapOperatorToLegacy(operator) {
|
|
115
|
+
const mapping = {
|
|
116
|
+
'$eq': '=',
|
|
117
|
+
'$ne': '!=',
|
|
118
|
+
'$gt': '>',
|
|
119
|
+
'$gte': '>=',
|
|
120
|
+
'$lt': '<',
|
|
121
|
+
'$lte': '<=',
|
|
122
|
+
'$in': 'in',
|
|
123
|
+
'$nin': 'nin',
|
|
124
|
+
'$contains': 'contains',
|
|
125
|
+
'$startsWith': 'startswith',
|
|
126
|
+
'$endsWith': 'endswith',
|
|
127
|
+
'$null': 'is_null',
|
|
128
|
+
'$exist': 'is_not_null',
|
|
129
|
+
'$between': 'between',
|
|
130
|
+
};
|
|
131
|
+
return mapping[operator] || operator.replace('$', '');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
exports.FilterTranslator = FilterTranslator;
|
|
135
|
+
//# sourceMappingURL=filter-translator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter-translator.js","sourceRoot":"","sources":["../../src/query/filter-translator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
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
|
+
* Query Module
|
|
10
|
+
*
|
|
11
|
+
* This module contains ObjectQL's query-specific functionality:
|
|
12
|
+
* - FilterTranslator: Converts ObjectQL filters to ObjectStack FilterNode
|
|
13
|
+
* - QueryBuilder: Builds ObjectStack QueryAST from ObjectQL UnifiedQuery
|
|
14
|
+
* - QueryService: Executes queries via drivers with profiling support
|
|
15
|
+
* - QueryAnalyzer: Provides query performance analysis and optimization suggestions
|
|
16
|
+
*
|
|
17
|
+
* These are the core components that differentiate ObjectQL from generic runtime systems.
|
|
18
|
+
*/
|
|
19
|
+
export * from './filter-translator';
|
|
20
|
+
export * from './query-builder';
|
|
21
|
+
export * from './query-service';
|
|
22
|
+
export * from './query-analyzer';
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ObjectQL
|
|
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
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(o, k2, desc);
|
|
16
|
+
}) : (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
o[k2] = m[k];
|
|
19
|
+
}));
|
|
20
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
21
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
22
|
+
};
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
/**
|
|
25
|
+
* Query Module
|
|
26
|
+
*
|
|
27
|
+
* This module contains ObjectQL's query-specific functionality:
|
|
28
|
+
* - FilterTranslator: Converts ObjectQL filters to ObjectStack FilterNode
|
|
29
|
+
* - QueryBuilder: Builds ObjectStack QueryAST from ObjectQL UnifiedQuery
|
|
30
|
+
* - QueryService: Executes queries via drivers with profiling support
|
|
31
|
+
* - QueryAnalyzer: Provides query performance analysis and optimization suggestions
|
|
32
|
+
*
|
|
33
|
+
* These are the core components that differentiate ObjectQL from generic runtime systems.
|
|
34
|
+
*/
|
|
35
|
+
__exportStar(require("./filter-translator"), exports);
|
|
36
|
+
__exportStar(require("./query-builder"), exports);
|
|
37
|
+
__exportStar(require("./query-service"), exports);
|
|
38
|
+
__exportStar(require("./query-analyzer"), exports);
|
|
39
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/query/index.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;;;;;;;;;;;;;;AAEH;;;;;;;;;;GAUG;AAEH,sDAAoC;AACpC,kDAAgC;AAChC,kDAAgC;AAChC,mDAAiC"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectQL Query Analyzer
|
|
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
|
+
import type { UnifiedQuery, MetadataRegistry } from '@objectql/types';
|
|
9
|
+
import type { QueryAST } from '@objectstack/spec';
|
|
10
|
+
import { QueryService, QueryOptions } from './query-service';
|
|
11
|
+
/**
|
|
12
|
+
* Query execution plan
|
|
13
|
+
*/
|
|
14
|
+
export interface QueryPlan {
|
|
15
|
+
/**
|
|
16
|
+
* The compiled QueryAST
|
|
17
|
+
*/
|
|
18
|
+
ast: QueryAST;
|
|
19
|
+
/**
|
|
20
|
+
* Estimated number of rows to be scanned
|
|
21
|
+
*/
|
|
22
|
+
estimatedRows?: number;
|
|
23
|
+
/**
|
|
24
|
+
* Indexes that could be used for this query
|
|
25
|
+
*/
|
|
26
|
+
indexes: string[];
|
|
27
|
+
/**
|
|
28
|
+
* Warnings about potential performance issues
|
|
29
|
+
*/
|
|
30
|
+
warnings: string[];
|
|
31
|
+
/**
|
|
32
|
+
* Suggestions for optimization
|
|
33
|
+
*/
|
|
34
|
+
suggestions: string[];
|
|
35
|
+
/**
|
|
36
|
+
* Complexity score (0-100, higher is more complex)
|
|
37
|
+
*/
|
|
38
|
+
complexity: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Query profile result with execution statistics
|
|
42
|
+
*/
|
|
43
|
+
export interface ProfileResult {
|
|
44
|
+
/**
|
|
45
|
+
* Execution time in milliseconds
|
|
46
|
+
*/
|
|
47
|
+
executionTime: number;
|
|
48
|
+
/**
|
|
49
|
+
* Number of rows scanned by the database
|
|
50
|
+
*/
|
|
51
|
+
rowsScanned: number;
|
|
52
|
+
/**
|
|
53
|
+
* Number of rows returned
|
|
54
|
+
*/
|
|
55
|
+
rowsReturned: number;
|
|
56
|
+
/**
|
|
57
|
+
* Whether an index was used
|
|
58
|
+
*/
|
|
59
|
+
indexUsed: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* The query plan
|
|
62
|
+
*/
|
|
63
|
+
plan: QueryPlan;
|
|
64
|
+
/**
|
|
65
|
+
* Efficiency ratio (rowsReturned / rowsScanned)
|
|
66
|
+
* Higher is better (1.0 is perfect, 0.0 is worst)
|
|
67
|
+
*/
|
|
68
|
+
efficiency: number;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Aggregated query statistics
|
|
72
|
+
*/
|
|
73
|
+
export interface QueryStats {
|
|
74
|
+
/**
|
|
75
|
+
* Total number of queries executed
|
|
76
|
+
*/
|
|
77
|
+
totalQueries: number;
|
|
78
|
+
/**
|
|
79
|
+
* Average execution time in milliseconds
|
|
80
|
+
*/
|
|
81
|
+
avgExecutionTime: number;
|
|
82
|
+
/**
|
|
83
|
+
* Slowest query execution time
|
|
84
|
+
*/
|
|
85
|
+
slowestQuery: number;
|
|
86
|
+
/**
|
|
87
|
+
* Fastest query execution time
|
|
88
|
+
*/
|
|
89
|
+
fastestQuery: number;
|
|
90
|
+
/**
|
|
91
|
+
* Queries by object
|
|
92
|
+
*/
|
|
93
|
+
byObject: Record<string, {
|
|
94
|
+
count: number;
|
|
95
|
+
avgTime: number;
|
|
96
|
+
}>;
|
|
97
|
+
/**
|
|
98
|
+
* Top slow queries
|
|
99
|
+
*/
|
|
100
|
+
slowQueries: Array<{
|
|
101
|
+
objectName: string;
|
|
102
|
+
executionTime: number;
|
|
103
|
+
query: UnifiedQuery;
|
|
104
|
+
timestamp: Date;
|
|
105
|
+
}>;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Query Analyzer
|
|
109
|
+
*
|
|
110
|
+
* Provides query performance analysis and profiling capabilities.
|
|
111
|
+
* This class helps developers optimize queries by:
|
|
112
|
+
* - Analyzing query plans
|
|
113
|
+
* - Profiling execution performance
|
|
114
|
+
* - Tracking statistics
|
|
115
|
+
* - Providing optimization suggestions
|
|
116
|
+
*/
|
|
117
|
+
export declare class QueryAnalyzer {
|
|
118
|
+
private queryService;
|
|
119
|
+
private metadata;
|
|
120
|
+
private stats;
|
|
121
|
+
private executionTimes;
|
|
122
|
+
private readonly MAX_SLOW_QUERIES;
|
|
123
|
+
constructor(queryService: QueryService, metadata: MetadataRegistry);
|
|
124
|
+
/**
|
|
125
|
+
* Analyze a query and generate an execution plan
|
|
126
|
+
*
|
|
127
|
+
* @param objectName - The object to query
|
|
128
|
+
* @param query - The unified query
|
|
129
|
+
* @returns Query plan with optimization suggestions
|
|
130
|
+
*/
|
|
131
|
+
explain(objectName: string, query: UnifiedQuery): Promise<QueryPlan>;
|
|
132
|
+
/**
|
|
133
|
+
* Profile a query execution
|
|
134
|
+
*
|
|
135
|
+
* @param objectName - The object to query
|
|
136
|
+
* @param query - The unified query
|
|
137
|
+
* @param options - Query execution options
|
|
138
|
+
* @returns Profile result with execution statistics
|
|
139
|
+
*/
|
|
140
|
+
profile(objectName: string, query: UnifiedQuery, options?: QueryOptions): Promise<ProfileResult>;
|
|
141
|
+
/**
|
|
142
|
+
* Get aggregated query statistics
|
|
143
|
+
*
|
|
144
|
+
* @returns Current query statistics
|
|
145
|
+
*/
|
|
146
|
+
getStatistics(): QueryStats;
|
|
147
|
+
/**
|
|
148
|
+
* Reset statistics
|
|
149
|
+
*/
|
|
150
|
+
resetStatistics(): void;
|
|
151
|
+
/**
|
|
152
|
+
* Get schema for an object
|
|
153
|
+
* @private
|
|
154
|
+
*/
|
|
155
|
+
private getSchema;
|
|
156
|
+
/**
|
|
157
|
+
* Find indexes that could be used for the query
|
|
158
|
+
* @private
|
|
159
|
+
*/
|
|
160
|
+
private findApplicableIndexes;
|
|
161
|
+
/**
|
|
162
|
+
* Analyze query for potential issues
|
|
163
|
+
* @private
|
|
164
|
+
*/
|
|
165
|
+
private analyzeWarnings;
|
|
166
|
+
/**
|
|
167
|
+
* Generate optimization suggestions
|
|
168
|
+
* @private
|
|
169
|
+
*/
|
|
170
|
+
private generateSuggestions;
|
|
171
|
+
/**
|
|
172
|
+
* Calculate query complexity score (0-100)
|
|
173
|
+
* @private
|
|
174
|
+
*/
|
|
175
|
+
private calculateComplexity;
|
|
176
|
+
/**
|
|
177
|
+
* Estimate number of rows (very rough heuristic)
|
|
178
|
+
* @private
|
|
179
|
+
*/
|
|
180
|
+
private estimateRows;
|
|
181
|
+
/**
|
|
182
|
+
* Record a query execution for statistics
|
|
183
|
+
* @private
|
|
184
|
+
*/
|
|
185
|
+
private recordExecution;
|
|
186
|
+
}
|