@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.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +42 -0
- package/dist/app.d.ts +61 -51
- package/dist/app.js +101 -431
- package/dist/app.js.map +1 -1
- package/dist/index.d.ts +4 -11
- package/dist/index.js +13 -9
- 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 +10 -16
- package/dist/plugin.js +104 -58
- package/dist/plugin.js.map +1 -1
- package/dist/repository.d.ts +4 -31
- package/dist/repository.js +7 -275
- package/dist/repository.js.map +1 -1
- package/dist/util.js +4 -2
- package/dist/util.js.map +1 -1
- package/package.json +19 -11
- package/src/app.ts +157 -531
- package/src/index.ts +8 -23
- package/src/kernel-factory.ts +47 -0
- package/src/plugin.ts +116 -94
- package/src/repository.ts +4 -313
- package/src/util.ts +5 -3
- package/test/__mocks__/@objectstack/core.ts +250 -1
- package/test/__mocks__/@objectstack/objectql.ts +127 -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 +4 -5
- package/test/utils.ts +6 -6
- package/tsconfig.json +3 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/gateway.d.ts +0 -36
- package/dist/gateway.js +0 -89
- package/dist/gateway.js.map +0 -1
- package/dist/optimizations/CompiledHookManager.d.ts +0 -55
- package/dist/optimizations/CompiledHookManager.js +0 -164
- 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 -180
- package/dist/protocol.js +0 -260
- package/dist/protocol.js.map +0 -1
- package/dist/query/filter-translator.d.ts +0 -27
- 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 -188
- 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 -35
- package/dist/query/query-builder.js +0 -61
- package/dist/query/query-builder.js.map +0 -1
- package/dist/query/query-service.d.ts +0 -153
- package/dist/query/query-service.js +0 -272
- package/dist/query/query-service.js.map +0 -1
- package/jest.config.js +0 -29
- package/src/gateway.ts +0 -101
- package/src/optimizations/CompiledHookManager.ts +0 -185
- 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 -291
- package/src/query/filter-translator.ts +0 -41
- package/src/query/index.ts +0 -24
- package/src/query/query-analyzer.ts +0 -533
- package/src/query/query-builder.ts +0 -64
- package/src/query/query-service.ts +0 -398
- 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
|
@@ -11,9 +11,103 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
export class ObjectQL {
|
|
14
|
+
private drivers = new Map<string, any>();
|
|
15
|
+
private defaultDriver: any = null;
|
|
16
|
+
private hooks = new Map<string, any[]>();
|
|
17
|
+
|
|
14
18
|
constructor(public config: any) {}
|
|
19
|
+
|
|
15
20
|
async connect() {}
|
|
16
21
|
async disconnect() {}
|
|
22
|
+
async init() {}
|
|
23
|
+
|
|
24
|
+
registerDriver(driver: any, isDefault: boolean = false) {
|
|
25
|
+
if (!driver.name) {
|
|
26
|
+
throw new Error('Driver must have a name');
|
|
27
|
+
}
|
|
28
|
+
this.drivers.set(driver.name, driver);
|
|
29
|
+
if (isDefault) {
|
|
30
|
+
this.defaultDriver = driver.name;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
registerObject(schema: any, packageId: string = '__runtime__', namespace?: string): string {
|
|
35
|
+
// Auto-assign field names from keys
|
|
36
|
+
if (schema.fields) {
|
|
37
|
+
for (const [key, field] of Object.entries(schema.fields)) {
|
|
38
|
+
if (field && typeof field === 'object' && !('name' in field)) {
|
|
39
|
+
(field as any).name = key;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return SchemaRegistry.registerObject(schema, packageId, namespace);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
getObject(name: string) {
|
|
47
|
+
return SchemaRegistry.getObject(name);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
getConfigs(): Record<string, any> {
|
|
51
|
+
return SchemaRegistry.getAllObjects().reduce((acc: any, obj: any) => {
|
|
52
|
+
if (obj.name) {
|
|
53
|
+
acc[obj.name] = obj;
|
|
54
|
+
}
|
|
55
|
+
return acc;
|
|
56
|
+
}, {});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
removePackage(packageId: string) {
|
|
60
|
+
SchemaRegistry.unregisterObjectsByPackage(packageId);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
registerHook(event: string, handler: any, options?: any) {
|
|
64
|
+
if (!this.hooks.has(event)) {
|
|
65
|
+
this.hooks.set(event, []);
|
|
66
|
+
}
|
|
67
|
+
this.hooks.get(event)!.push({ handler, options });
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
createContext(options: any = {}) {
|
|
71
|
+
return {
|
|
72
|
+
isSystem: options.isSystem || false,
|
|
73
|
+
object: (name: string) => ({
|
|
74
|
+
find: async (filter: any) => {
|
|
75
|
+
const driver = this.drivers.get(this.defaultDriver || this.drivers.keys().next().value);
|
|
76
|
+
if (driver && driver.find) {
|
|
77
|
+
return driver.find(name, filter);
|
|
78
|
+
}
|
|
79
|
+
return [];
|
|
80
|
+
},
|
|
81
|
+
findOne: async (filter: any) => {
|
|
82
|
+
const driver = this.drivers.get(this.defaultDriver || this.drivers.keys().next().value);
|
|
83
|
+
if (driver && driver.findOne) {
|
|
84
|
+
return driver.findOne(name, filter);
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
},
|
|
88
|
+
insert: async (data: any) => {
|
|
89
|
+
const driver = this.drivers.get(this.defaultDriver || this.drivers.keys().next().value);
|
|
90
|
+
if (driver && driver.insert) {
|
|
91
|
+
return driver.insert(name, data);
|
|
92
|
+
}
|
|
93
|
+
return data;
|
|
94
|
+
},
|
|
95
|
+
update: async (id: string, data: any) => {
|
|
96
|
+
const driver = this.drivers.get(this.defaultDriver || this.drivers.keys().next().value);
|
|
97
|
+
if (driver && driver.update) {
|
|
98
|
+
return driver.update(name, id, data);
|
|
99
|
+
}
|
|
100
|
+
return data;
|
|
101
|
+
},
|
|
102
|
+
delete: async (id: string) => {
|
|
103
|
+
const driver = this.drivers.get(this.defaultDriver || this.drivers.keys().next().value);
|
|
104
|
+
if (driver && driver.delete) {
|
|
105
|
+
return driver.delete(name, id);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
};
|
|
110
|
+
}
|
|
17
111
|
}
|
|
18
112
|
|
|
19
113
|
const mockStore = new Map<string, Map<string, any>>();
|
|
@@ -42,4 +136,37 @@ export const SchemaRegistry = {
|
|
|
42
136
|
return items ? Array.from(items.values()) : [];
|
|
43
137
|
}),
|
|
44
138
|
metadata: mockStore,
|
|
139
|
+
|
|
140
|
+
// Additional methods needed for ObjectQL compatibility
|
|
141
|
+
registerObject: jest.fn((schema: any, packageId?: string, namespace?: string) => {
|
|
142
|
+
if (!mockStore.has('object')) {
|
|
143
|
+
mockStore.set('object', new Map());
|
|
144
|
+
}
|
|
145
|
+
const name = schema.name || 'unnamed';
|
|
146
|
+
mockStore.get('object')!.set(name, schema);
|
|
147
|
+
return namespace ? `${namespace}.${name}` : name;
|
|
148
|
+
}),
|
|
149
|
+
|
|
150
|
+
getObject: jest.fn((name: string) => {
|
|
151
|
+
return mockStore.get('object')?.get(name);
|
|
152
|
+
}),
|
|
153
|
+
|
|
154
|
+
getAllObjects: jest.fn(() => {
|
|
155
|
+
const objects = mockStore.get('object');
|
|
156
|
+
return objects ? Array.from(objects.values()) : [];
|
|
157
|
+
}),
|
|
158
|
+
|
|
159
|
+
unregisterObjectsByPackage: jest.fn((packageId: string) => {
|
|
160
|
+
// In mock, just clear the objects store
|
|
161
|
+
const objects = mockStore.get('object');
|
|
162
|
+
if (objects) {
|
|
163
|
+
const toDelete: string[] = [];
|
|
164
|
+
objects.forEach((obj, key) => {
|
|
165
|
+
if ((obj as any).__packageId === packageId) {
|
|
166
|
+
toDelete.push(key);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
toDelete.forEach(key => objects.delete(key));
|
|
170
|
+
}
|
|
171
|
+
}),
|
|
45
172
|
};
|
|
@@ -11,12 +11,21 @@
|
|
|
11
11
|
class MockMetadataRegistry {
|
|
12
12
|
private store = new Map<string, Map<string, any>>();
|
|
13
13
|
|
|
14
|
-
register(type: string,
|
|
14
|
+
register(type: string, nameOrConfig: string | any, config?: any): void {
|
|
15
15
|
if (!this.store.has(type)) {
|
|
16
16
|
this.store.set(type, new Map());
|
|
17
17
|
}
|
|
18
18
|
const typeMap = this.store.get(type)!;
|
|
19
|
-
|
|
19
|
+
let name: string;
|
|
20
|
+
let item: any;
|
|
21
|
+
if (config) {
|
|
22
|
+
name = nameOrConfig as string;
|
|
23
|
+
item = config;
|
|
24
|
+
} else {
|
|
25
|
+
item = nameOrConfig;
|
|
26
|
+
name = item.id || item.name;
|
|
27
|
+
}
|
|
28
|
+
typeMap.set(name, item);
|
|
20
29
|
}
|
|
21
30
|
|
|
22
31
|
get<T = any>(type: string, id: string): T | undefined {
|
|
@@ -43,7 +52,7 @@ class MockMetadataRegistry {
|
|
|
43
52
|
|
|
44
53
|
unregisterPackage(packageName: string): void {
|
|
45
54
|
// Simple implementation - in real runtime this would filter by package
|
|
46
|
-
for (const [
|
|
55
|
+
for (const [_type, typeMap] of this.store.entries()) {
|
|
47
56
|
const toDelete: string[] = [];
|
|
48
57
|
for (const [id, item] of typeMap.entries()) {
|
|
49
58
|
if (item.packageName === packageName || item.package === packageName) {
|
|
@@ -233,11 +242,11 @@ export class ObjectKernel {
|
|
|
233
242
|
return true;
|
|
234
243
|
}
|
|
235
244
|
|
|
236
|
-
getMetadata(
|
|
245
|
+
getMetadata(_objectName: string): any {
|
|
237
246
|
return {};
|
|
238
247
|
}
|
|
239
248
|
|
|
240
|
-
getView(
|
|
249
|
+
getView(_objectName: string, _viewType?: 'list' | 'form'): any {
|
|
241
250
|
return null;
|
|
242
251
|
}
|
|
243
252
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { convertIntrospectedSchemaToObjects } from '../src/util';
|
|
10
|
-
import { IntrospectedSchema
|
|
10
|
+
import { IntrospectedSchema } from '@objectql/types';
|
|
11
11
|
|
|
12
12
|
describe('convertIntrospectedSchemaToObjects', () => {
|
|
13
13
|
it('should convert simple table to object config', () => {
|
package/test/mock-driver.ts
CHANGED
|
@@ -25,7 +25,7 @@ export class MockDriver implements Driver {
|
|
|
25
25
|
return this.data[objectName];
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
async find(objectName: string, query: any,
|
|
28
|
+
async find(objectName: string, query: any, _options?: any): Promise<any[]> {
|
|
29
29
|
const items = this.getData(objectName);
|
|
30
30
|
// Very basic filter implementation for testing
|
|
31
31
|
if (query.filters) {
|
|
@@ -42,12 +42,12 @@ export class MockDriver implements Driver {
|
|
|
42
42
|
return items;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
async findOne(objectName: string, id: string | number,
|
|
45
|
+
async findOne(objectName: string, id: string | number, _query?: any, _options?: any): Promise<any> {
|
|
46
46
|
const items = this.getData(objectName);
|
|
47
47
|
return items.find((item: any) => item._id === id);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
async create(objectName: string, data: any,
|
|
50
|
+
async create(objectName: string, data: any, _options?: any): Promise<any> {
|
|
51
51
|
const items = this.getData(objectName);
|
|
52
52
|
const newItem = {
|
|
53
53
|
...data,
|
|
@@ -57,7 +57,7 @@ export class MockDriver implements Driver {
|
|
|
57
57
|
return newItem;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
async update(objectName: string, id: string | number, data: any,
|
|
60
|
+
async update(objectName: string, id: string | number, data: any, _options?: any): Promise<any> {
|
|
61
61
|
const items = this.getData(objectName);
|
|
62
62
|
const index = items.findIndex((item: any) => item._id === id);
|
|
63
63
|
if (index > -1) {
|
|
@@ -67,7 +67,7 @@ export class MockDriver implements Driver {
|
|
|
67
67
|
throw new Error('Not found');
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
async delete(objectName: string, id: string | number,
|
|
70
|
+
async delete(objectName: string, id: string | number, _options?: any): Promise<any> {
|
|
71
71
|
const items = this.getData(objectName);
|
|
72
72
|
const index = items.findIndex((item: any) => item._id === id);
|
|
73
73
|
if (index > -1) {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
// Import from the plugin package where the optimization modules now live
|
|
10
10
|
import {
|
|
11
11
|
OptimizedMetadataRegistry,
|
|
12
12
|
QueryCompiler,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
LazyMetadataLoader,
|
|
17
17
|
DependencyGraph,
|
|
18
18
|
SQLQueryOptimizer
|
|
19
|
-
} from '
|
|
19
|
+
} from '@objectql/plugin-optimizations';
|
|
20
20
|
|
|
21
21
|
describe('Kernel Optimizations', () => {
|
|
22
22
|
describe('OptimizedMetadataRegistry', () => {
|
|
@@ -9,10 +9,11 @@
|
|
|
9
9
|
import { ObjectQLPlugin } from '../src/plugin';
|
|
10
10
|
import { ValidatorPlugin } from '@objectql/plugin-validator';
|
|
11
11
|
import { FormulaPlugin } from '@objectql/plugin-formula';
|
|
12
|
+
import { vi } from 'vitest';
|
|
12
13
|
|
|
13
14
|
// Mock the sub-plugins
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
vi.mock('@objectql/plugin-validator');
|
|
16
|
+
vi.mock('@objectql/plugin-formula');
|
|
16
17
|
|
|
17
18
|
describe('ObjectQLPlugin Integration', () => {
|
|
18
19
|
let plugin: ObjectQLPlugin;
|
|
@@ -45,7 +46,7 @@ describe('ObjectQLPlugin Integration', () => {
|
|
|
45
46
|
it('should have correct name and version', () => {
|
|
46
47
|
plugin = new ObjectQLPlugin();
|
|
47
48
|
expect(plugin.name).toBe('@objectql/core');
|
|
48
|
-
expect(plugin.version).toBe('4.0
|
|
49
|
+
expect(plugin.version).toBe('4.2.0');
|
|
49
50
|
});
|
|
50
51
|
});
|
|
51
52
|
|
|
@@ -60,7 +61,6 @@ describe('ObjectQLPlugin Integration', () => {
|
|
|
60
61
|
enableRepository: false,
|
|
61
62
|
enableValidator: false,
|
|
62
63
|
enableFormulas: true,
|
|
63
|
-
enableAI: false,
|
|
64
64
|
});
|
|
65
65
|
expect(plugin).toBeDefined();
|
|
66
66
|
});
|
|
@@ -175,7 +175,6 @@ describe('ObjectQLPlugin Integration', () => {
|
|
|
175
175
|
enableRepository: false,
|
|
176
176
|
enableValidator: false,
|
|
177
177
|
enableFormulas: false,
|
|
178
|
-
enableAI: false,
|
|
179
178
|
});
|
|
180
179
|
|
|
181
180
|
const runtimeContext = { engine: mockContext.app };
|
package/test/utils.ts
CHANGED
|
@@ -20,22 +20,22 @@ export class MockDriver implements Driver {
|
|
|
20
20
|
return this.data[objectName];
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
async find(objectName: string,
|
|
23
|
+
async find(objectName: string, _query: any, _options?: any): Promise<any[]> {
|
|
24
24
|
return this.getData(objectName);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
async findOne(objectName: string, id: string | number,
|
|
27
|
+
async findOne(objectName: string, id: string | number, _query?: any, _options?: any): Promise<any> {
|
|
28
28
|
return this.getData(objectName).find(item => item.id == id);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
async create(objectName: string, data: any,
|
|
31
|
+
async create(objectName: string, data: any, _options?: any): Promise<any> {
|
|
32
32
|
const list = this.getData(objectName);
|
|
33
33
|
if (!data.id) data.id = list.length + 1;
|
|
34
34
|
list.push(data);
|
|
35
35
|
return data;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
async update(objectName: string, id: string | number, data: any,
|
|
38
|
+
async update(objectName: string, id: string | number, data: any, _options?: any): Promise<any> {
|
|
39
39
|
const list = this.getData(objectName);
|
|
40
40
|
const idx = list.findIndex(item => item.id == id);
|
|
41
41
|
if (idx >= 0) {
|
|
@@ -45,7 +45,7 @@ export class MockDriver implements Driver {
|
|
|
45
45
|
return null;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
async delete(objectName: string, id: string | number,
|
|
48
|
+
async delete(objectName: string, id: string | number, _options?: any): Promise<any> {
|
|
49
49
|
const list = this.getData(objectName);
|
|
50
50
|
const idx = list.findIndex(item => item.id == id);
|
|
51
51
|
if (idx >= 0) {
|
|
@@ -56,7 +56,7 @@ export class MockDriver implements Driver {
|
|
|
56
56
|
return null;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
async count(objectName: string,
|
|
59
|
+
async count(objectName: string, _filters: any, _options?: any): Promise<number> {
|
|
60
60
|
return this.getData(objectName).length;
|
|
61
61
|
}
|
|
62
62
|
}
|
package/tsconfig.json
CHANGED