Skip to content

Commit 2000351

Browse files
Copilothotlong
andcommitted
feat: create @objectql/plugin-query package with query modules from core
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 3a53c24 commit 2000351

9 files changed

Lines changed: 1204 additions & 0 deletions

File tree

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "@objectql/plugin-query",
3+
"version": "4.2.0",
4+
"description": "Query execution and analysis plugin for ObjectQL - query service, builder, and analyzer",
5+
"main": "dist/index.js",
6+
"types": "dist/index.d.ts",
7+
"sideEffects": false,
8+
"exports": {
9+
".": {
10+
"types": "./dist/index.d.ts",
11+
"default": "./dist/index.js"
12+
}
13+
},
14+
"files": ["dist"],
15+
"scripts": {
16+
"build": "tsc",
17+
"test": "vitest run"
18+
},
19+
"dependencies": {
20+
"@objectql/types": "workspace:*",
21+
"@objectql/plugin-optimizations": "workspace:*",
22+
"@objectstack/core": "^2.0.6",
23+
"@objectstack/spec": "^2.0.6"
24+
},
25+
"devDependencies": {
26+
"typescript": "^5.3.0"
27+
}
28+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* ObjectQL
3+
* Copyright (c) 2026-present ObjectStack Inc.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
import type { Filter } from '@objectql/types';
10+
11+
/**
12+
* Filter Translator
13+
*
14+
* Translates ObjectQL Filter to ObjectStack FilterCondition format.
15+
* Since both now use the same format, this is mostly a pass-through.
16+
*
17+
* @example
18+
* Input: { age: { $gte: 18 }, $or: [{ status: "active" }, { role: "admin" }] }
19+
* Output: { age: { $gte: 18 }, $or: [{ status: "active" }, { role: "admin" }] }
20+
*/
21+
export class FilterTranslator {
22+
/**
23+
* Translate filters from ObjectQL format to ObjectStack FilterCondition format
24+
*/
25+
translate(filters?: Filter): Filter | undefined {
26+
if (!filters) {
27+
return undefined;
28+
}
29+
30+
// If it's an empty object, return undefined
31+
if (typeof filters === 'object' && Object.keys(filters).length === 0) {
32+
return undefined;
33+
}
34+
35+
// Both ObjectQL Filter and ObjectStack FilterCondition use the same format now
36+
return filters;
37+
}
38+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* @objectql/plugin-query
3+
* Copyright (c) 2026-present ObjectStack Inc.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
/**
10+
* Query Plugin
11+
*
12+
* Provides query execution and analysis capabilities:
13+
* - QueryService — query execution with profiling support
14+
* - QueryBuilder — builds ObjectStack QueryAST from ObjectQL UnifiedQuery
15+
* - QueryAnalyzer — query performance analysis and optimization suggestions
16+
*/
17+
18+
export { QueryPlugin } from './plugin';
19+
export { QueryService, type QueryOptions, type QueryResult, type QueryProfile } from './query-service';
20+
export { QueryBuilder } from './query-builder';
21+
export { QueryAnalyzer, type QueryPlan, type ProfileResult, type QueryStats } from './query-analyzer';
22+
export { FilterTranslator } from './filter-translator';
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/**
2+
* @objectql/plugin-query
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 { RuntimePlugin, RuntimeContext } from '@objectql/types';
10+
import { ConsoleLogger } from '@objectql/types';
11+
import type { Logger, Driver } from '@objectql/types';
12+
import { QueryService } from './query-service';
13+
import { QueryAnalyzer } from './query-analyzer';
14+
15+
/**
16+
* Configuration for the Query Plugin
17+
*/
18+
export interface QueryPluginConfig {
19+
/**
20+
* Datasources for query service
21+
*/
22+
datasources?: Record<string, Driver>;
23+
24+
/**
25+
* Enable query analyzer
26+
* @default true
27+
*/
28+
enableAnalyzer?: boolean;
29+
}
30+
31+
/**
32+
* Query Plugin
33+
*
34+
* Provides query execution and analysis capabilities for the ObjectQL kernel.
35+
* Registers QueryService and QueryAnalyzer on the kernel for consumer access.
36+
*/
37+
export class QueryPlugin implements RuntimePlugin {
38+
name = '@objectql/plugin-query';
39+
version = '4.2.0';
40+
private logger: Logger;
41+
42+
constructor(private config: QueryPluginConfig = {}) {
43+
this.config = {
44+
enableAnalyzer: true,
45+
...config,
46+
};
47+
this.logger = new ConsoleLogger({ name: this.name, level: 'info' });
48+
}
49+
50+
async install(ctx: RuntimeContext): Promise<void> {
51+
this.logger.info('Installing query plugin...');
52+
53+
const kernel = ctx.engine as any;
54+
55+
// Get datasources - either from config or from kernel drivers
56+
let datasources = this.config.datasources;
57+
if (!datasources) {
58+
const drivers = kernel.getAllDrivers?.();
59+
if (drivers && drivers.length > 0) {
60+
datasources = {};
61+
drivers.forEach((driver: any, index: number) => {
62+
const driverName = driver.name || (index === 0 ? 'default' : `driver_${index + 1}`);
63+
datasources![driverName] = driver;
64+
});
65+
}
66+
}
67+
68+
if (!datasources) {
69+
this.logger.warn('No datasources available. QueryService will not be registered.');
70+
return;
71+
}
72+
73+
// Create QueryService
74+
const queryService = new QueryService(datasources, kernel.metadata);
75+
kernel.queryService = queryService;
76+
this.logger.debug('QueryService registered');
77+
78+
// Create QueryAnalyzer if enabled
79+
if (this.config.enableAnalyzer !== false) {
80+
const queryAnalyzer = new QueryAnalyzer(queryService, kernel.metadata);
81+
kernel.queryAnalyzer = queryAnalyzer;
82+
this.logger.debug('QueryAnalyzer registered');
83+
}
84+
85+
this.logger.info('Query plugin installed successfully');
86+
}
87+
88+
async onStart(_ctx: RuntimeContext): Promise<void> {
89+
this.logger.debug('Query plugin started');
90+
}
91+
}

0 commit comments

Comments
 (0)