@objectstack/runtime 0.1.0 → 0.1.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/CHANGELOG.md +11 -0
- package/dist/index.d.ts +3 -4
- package/dist/index.js +21 -7
- package/dist/{data-engine.d.ts → kernel.d.ts} +5 -7
- package/dist/{data-engine.js → kernel.js} +36 -24
- package/dist/protocol.d.ts +2 -2
- package/dist/protocol.js +5 -5
- package/dist/types.d.ts +9 -0
- package/dist/types.js +2 -0
- package/package.json +4 -2
- package/src/index.ts +3 -6
- package/src/{data-engine.ts → kernel.ts} +29 -16
- package/src/protocol.ts +4 -4
- package/src/types.ts +11 -0
- package/dist/engine.d.ts +0 -40
- package/dist/engine.js +0 -157
- package/dist/registry.d.ts +0 -55
- package/dist/registry.js +0 -93
- package/src/engine.ts +0 -189
- package/src/registry.ts +0 -107
package/CHANGELOG.md
ADDED
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
export { ObjectQL } from '
|
|
2
|
-
export {
|
|
3
|
-
export { DataEngine } from './data-engine';
|
|
1
|
+
export { ObjectQL, SchemaRegistry } from '@objectstack/objectql';
|
|
2
|
+
export { ObjectStackKernel } from './kernel';
|
|
4
3
|
export { ObjectStackRuntimeProtocol } from './protocol';
|
|
5
|
-
export
|
|
4
|
+
export * from './types';
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
2
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ObjectStackRuntimeProtocol = exports.
|
|
17
|
+
exports.ObjectStackRuntimeProtocol = exports.ObjectStackKernel = exports.SchemaRegistry = exports.ObjectQL = void 0;
|
|
4
18
|
// Export core engine
|
|
5
|
-
var
|
|
6
|
-
Object.defineProperty(exports, "ObjectQL", { enumerable: true, get: function () { return
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
Object.defineProperty(exports, "DataEngine", { enumerable: true, get: function () { return data_engine_1.DataEngine; } });
|
|
19
|
+
var objectql_1 = require("@objectstack/objectql");
|
|
20
|
+
Object.defineProperty(exports, "ObjectQL", { enumerable: true, get: function () { return objectql_1.ObjectQL; } });
|
|
21
|
+
Object.defineProperty(exports, "SchemaRegistry", { enumerable: true, get: function () { return objectql_1.SchemaRegistry; } });
|
|
22
|
+
var kernel_1 = require("./kernel");
|
|
23
|
+
Object.defineProperty(exports, "ObjectStackKernel", { enumerable: true, get: function () { return kernel_1.ObjectStackKernel; } });
|
|
11
24
|
var protocol_1 = require("./protocol");
|
|
12
25
|
Object.defineProperty(exports, "ObjectStackRuntimeProtocol", { enumerable: true, get: function () { return protocol_1.ObjectStackRuntimeProtocol; } });
|
|
26
|
+
__exportStar(require("./types"), exports);
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import { ObjectQL } from '
|
|
1
|
+
import { ObjectQL } from '@objectstack/objectql';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* ObjectStack Kernel (Microkernel)
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* The core logic has been moved to @objectstack/objectql.
|
|
5
|
+
* The central container orchestrating the application lifecycle,
|
|
6
|
+
* plugins, and the core ObjectQL engine.
|
|
9
7
|
*/
|
|
10
|
-
export declare class
|
|
8
|
+
export declare class ObjectStackKernel {
|
|
11
9
|
ql: ObjectQL;
|
|
12
10
|
private plugins;
|
|
13
11
|
constructor(plugins?: any[]);
|
|
@@ -33,39 +33,44 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.
|
|
37
|
-
const
|
|
38
|
-
const engine_1 = require("./engine");
|
|
36
|
+
exports.ObjectStackKernel = void 0;
|
|
37
|
+
const objectql_1 = require("@objectstack/objectql");
|
|
39
38
|
/**
|
|
40
|
-
*
|
|
39
|
+
* ObjectStack Kernel (Microkernel)
|
|
41
40
|
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* The core logic has been moved to @objectstack/objectql.
|
|
41
|
+
* The central container orchestrating the application lifecycle,
|
|
42
|
+
* plugins, and the core ObjectQL engine.
|
|
46
43
|
*/
|
|
47
|
-
class
|
|
44
|
+
class ObjectStackKernel {
|
|
48
45
|
constructor(plugins = []) {
|
|
49
46
|
// 1. Initialize Engine with Host Context (Simulated OS services)
|
|
50
|
-
this.ql = new
|
|
47
|
+
this.ql = new objectql_1.ObjectQL({
|
|
51
48
|
env: process.env.NODE_ENV || 'development'
|
|
52
49
|
});
|
|
53
50
|
this.plugins = plugins;
|
|
54
51
|
}
|
|
55
52
|
async start() {
|
|
56
|
-
console.log('[
|
|
53
|
+
console.log('[Kernel] Starting...');
|
|
57
54
|
// 0. Register Provided Plugins
|
|
58
|
-
this.plugins
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
for (const p of this.plugins) {
|
|
56
|
+
// Check if it is a Runtime Plugin (System Capability)
|
|
57
|
+
if ('onStart' in p || 'install' in p) {
|
|
58
|
+
console.log(`[Kernel] Loading Runtime Plugin: ${p.name}`);
|
|
59
|
+
if (p.install)
|
|
60
|
+
await p.install({ engine: this });
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
// Otherwise treat as App Manifest
|
|
64
|
+
console.log(`[Kernel] Loading App Manifest: ${p.id || p.name}`);
|
|
65
|
+
objectql_1.SchemaRegistry.registerPlugin(p);
|
|
61
66
|
// Register Objects from App/Plugin
|
|
62
67
|
if (p.objects) {
|
|
63
68
|
for (const obj of p.objects) {
|
|
64
|
-
|
|
65
|
-
console.log(`[
|
|
69
|
+
objectql_1.SchemaRegistry.registerObject(obj);
|
|
70
|
+
console.log(`[Kernel] Registered Object: ${obj.name}`);
|
|
66
71
|
}
|
|
67
72
|
}
|
|
68
|
-
}
|
|
73
|
+
}
|
|
69
74
|
// 1. Load Drivers (Default to Memory if none provided in plugins)
|
|
70
75
|
// TODO: Detect driver from plugins. For now, we still hard load memory driver if needed?
|
|
71
76
|
// In strict mode, user should pass driver in plugins array (DriverManifest).
|
|
@@ -84,6 +89,13 @@ class DataEngine {
|
|
|
84
89
|
await this.ql.init();
|
|
85
90
|
// 3. Seed Data
|
|
86
91
|
await this.seed();
|
|
92
|
+
// 4. Start Runtime Plugins
|
|
93
|
+
for (const p of this.plugins) {
|
|
94
|
+
if (('onStart' in p) && typeof p.onStart === 'function') {
|
|
95
|
+
console.log(`[Kernel] Starting Plugin: ${p.name}`);
|
|
96
|
+
await p.onStart({ engine: this });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
87
99
|
}
|
|
88
100
|
async seed() {
|
|
89
101
|
// If no driver registered yet, this might fail or wait.
|
|
@@ -96,28 +108,28 @@ class DataEngine {
|
|
|
96
108
|
}
|
|
97
109
|
catch { }
|
|
98
110
|
// Iterate over all registered plugins/apps and check for 'data' property in manifest
|
|
99
|
-
const plugins =
|
|
111
|
+
const plugins = objectql_1.SchemaRegistry.getRegisteredTypes(); // This returns types like 'plugin', 'app'
|
|
100
112
|
// This is a bit hacky because we don't have a direct "getAllManifests" API exposed easily
|
|
101
113
|
// We will iterate known apps for now, or improve Registry API later.
|
|
102
114
|
// Actually, SchemaRegistry.listItems('app') returns the manifests!
|
|
103
|
-
const apps = [...
|
|
115
|
+
const apps = [...objectql_1.SchemaRegistry.listItems('app'), ...objectql_1.SchemaRegistry.listItems('plugin')];
|
|
104
116
|
for (const appItem of apps) {
|
|
105
117
|
const app = appItem; // Cast to access data prop safely
|
|
106
118
|
if (app.data && Array.isArray(app.data)) {
|
|
107
|
-
console.log(`[
|
|
119
|
+
console.log(`[Kernel] Seeding data for ${app.name || app.id}...`);
|
|
108
120
|
for (const seed of app.data) {
|
|
109
121
|
try {
|
|
110
122
|
// Check if data exists
|
|
111
123
|
const existing = await this.ql.find(seed.object, { top: 1 });
|
|
112
124
|
if (existing.length === 0) {
|
|
113
|
-
console.log(`[
|
|
125
|
+
console.log(`[Kernel] Inserting ${seed.records.length} records into ${seed.object}`);
|
|
114
126
|
for (const record of seed.records) {
|
|
115
127
|
await this.ql.insert(seed.object, record);
|
|
116
128
|
}
|
|
117
129
|
}
|
|
118
130
|
}
|
|
119
131
|
catch (e) {
|
|
120
|
-
console.warn(`[
|
|
132
|
+
console.warn(`[Kernel] Failed to seed ${seed.object}`, e);
|
|
121
133
|
}
|
|
122
134
|
}
|
|
123
135
|
}
|
|
@@ -173,10 +185,10 @@ class DataEngine {
|
|
|
173
185
|
return null;
|
|
174
186
|
}
|
|
175
187
|
ensureSchema(name) {
|
|
176
|
-
const schema =
|
|
188
|
+
const schema = objectql_1.SchemaRegistry.getObject(name);
|
|
177
189
|
if (!schema)
|
|
178
190
|
throw new Error(`Unknown object: ${name}`);
|
|
179
191
|
return schema;
|
|
180
192
|
}
|
|
181
193
|
}
|
|
182
|
-
exports.
|
|
194
|
+
exports.ObjectStackKernel = ObjectStackKernel;
|
package/dist/protocol.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ObjectStackKernel } from './kernel';
|
|
2
2
|
export interface ApiRequest {
|
|
3
3
|
params: Record<string, string>;
|
|
4
4
|
query: Record<string, string | string[]>;
|
|
@@ -6,7 +6,7 @@ export interface ApiRequest {
|
|
|
6
6
|
}
|
|
7
7
|
export declare class ObjectStackRuntimeProtocol {
|
|
8
8
|
private engine;
|
|
9
|
-
constructor(engine:
|
|
9
|
+
constructor(engine: ObjectStackKernel);
|
|
10
10
|
getDiscovery(): {
|
|
11
11
|
name: string;
|
|
12
12
|
version: string;
|
package/dist/protocol.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ObjectStackRuntimeProtocol = void 0;
|
|
4
|
-
const
|
|
4
|
+
const objectql_1 = require("@objectstack/objectql");
|
|
5
5
|
class ObjectStackRuntimeProtocol {
|
|
6
6
|
constructor(engine) {
|
|
7
7
|
this.engine = engine;
|
|
@@ -27,12 +27,12 @@ class ObjectStackRuntimeProtocol {
|
|
|
27
27
|
}
|
|
28
28
|
// 2. Metadata: List Types
|
|
29
29
|
getMetaTypes() {
|
|
30
|
-
const types =
|
|
30
|
+
const types = objectql_1.SchemaRegistry.getRegisteredTypes();
|
|
31
31
|
return {
|
|
32
32
|
data: types.map(type => ({
|
|
33
33
|
type,
|
|
34
34
|
href: `/api/v1/meta/${type}s`,
|
|
35
|
-
count:
|
|
35
|
+
count: objectql_1.SchemaRegistry.listItems(type).length
|
|
36
36
|
}))
|
|
37
37
|
};
|
|
38
38
|
}
|
|
@@ -48,7 +48,7 @@ class ObjectStackRuntimeProtocol {
|
|
|
48
48
|
'kinds': 'kind'
|
|
49
49
|
};
|
|
50
50
|
const type = typeMap[typePlural] || typePlural;
|
|
51
|
-
const items =
|
|
51
|
+
const items = objectql_1.SchemaRegistry.listItems(type);
|
|
52
52
|
const summaries = items.map((item) => ({
|
|
53
53
|
id: item.id,
|
|
54
54
|
name: item.name,
|
|
@@ -72,7 +72,7 @@ class ObjectStackRuntimeProtocol {
|
|
|
72
72
|
'kinds': 'kind'
|
|
73
73
|
};
|
|
74
74
|
const type = typeMap[typePlural] || typePlural;
|
|
75
|
-
const item =
|
|
75
|
+
const item = objectql_1.SchemaRegistry.getItem(type, name);
|
|
76
76
|
if (!item)
|
|
77
77
|
throw new Error(`Metadata not found: ${type}/${name}`);
|
|
78
78
|
return item;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ObjectStackKernel } from './kernel';
|
|
2
|
+
export interface RuntimeContext {
|
|
3
|
+
engine: ObjectStackKernel;
|
|
4
|
+
}
|
|
5
|
+
export interface RuntimePlugin {
|
|
6
|
+
name: string;
|
|
7
|
+
install?: (ctx: RuntimeContext) => void | Promise<void>;
|
|
8
|
+
onStart?: (ctx: RuntimeContext) => void | Promise<void>;
|
|
9
|
+
}
|
package/dist/types.js
ADDED
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@objectstack/runtime",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "ObjectStack Core Runtime & Query Engine",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@objectstack/
|
|
8
|
+
"@objectstack/objectql": "0.1.1",
|
|
9
|
+
"@objectstack/types": "0.1.1",
|
|
10
|
+
"@objectstack/spec": "0.1.2"
|
|
9
11
|
},
|
|
10
12
|
"devDependencies": {
|
|
11
13
|
"typescript": "^5.0.0"
|
package/src/index.ts
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
// Export core engine
|
|
2
|
-
export { ObjectQL } from '
|
|
3
|
-
export {
|
|
4
|
-
export { DataEngine } from './data-engine';
|
|
2
|
+
export { ObjectQL, SchemaRegistry } from '@objectstack/objectql';
|
|
3
|
+
export { ObjectStackKernel } from './kernel';
|
|
5
4
|
export { ObjectStackRuntimeProtocol } from './protocol';
|
|
6
5
|
|
|
6
|
+
export * from './types';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
// Re-export common types from spec for convenience
|
|
10
|
-
export type { DriverInterface, DriverOptions, QueryAST } from '@objectstack/spec';
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
import { ServiceObject } from '@objectstack/spec';
|
|
2
|
-
import { SchemaRegistry } from '
|
|
3
|
-
import { ObjectQL } from './engine';
|
|
2
|
+
import { SchemaRegistry, ObjectQL } from '@objectstack/objectql';
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
|
-
*
|
|
5
|
+
* ObjectStack Kernel (Microkernel)
|
|
7
6
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* The core logic has been moved to @objectstack/objectql.
|
|
7
|
+
* The central container orchestrating the application lifecycle,
|
|
8
|
+
* plugins, and the core ObjectQL engine.
|
|
12
9
|
*/
|
|
13
|
-
export class
|
|
10
|
+
export class ObjectStackKernel {
|
|
14
11
|
public ql: ObjectQL;
|
|
15
12
|
private plugins: any[];
|
|
16
13
|
|
|
@@ -23,21 +20,29 @@ export class DataEngine {
|
|
|
23
20
|
}
|
|
24
21
|
|
|
25
22
|
async start() {
|
|
26
|
-
console.log('[
|
|
23
|
+
console.log('[Kernel] Starting...');
|
|
27
24
|
|
|
28
25
|
// 0. Register Provided Plugins
|
|
29
|
-
this.plugins
|
|
30
|
-
|
|
26
|
+
for (const p of this.plugins) {
|
|
27
|
+
// Check if it is a Runtime Plugin (System Capability)
|
|
28
|
+
if ('onStart' in p || 'install' in p) {
|
|
29
|
+
console.log(`[Kernel] Loading Runtime Plugin: ${p.name}`);
|
|
30
|
+
if (p.install) await p.install({ engine: this });
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Otherwise treat as App Manifest
|
|
35
|
+
console.log(`[Kernel] Loading App Manifest: ${p.id || p.name}`);
|
|
31
36
|
SchemaRegistry.registerPlugin(p);
|
|
32
37
|
|
|
33
38
|
// Register Objects from App/Plugin
|
|
34
39
|
if (p.objects) {
|
|
35
40
|
for (const obj of p.objects) {
|
|
36
41
|
SchemaRegistry.registerObject(obj);
|
|
37
|
-
console.log(`[
|
|
42
|
+
console.log(`[Kernel] Registered Object: ${obj.name}`);
|
|
38
43
|
}
|
|
39
44
|
}
|
|
40
|
-
}
|
|
45
|
+
}
|
|
41
46
|
|
|
42
47
|
// 1. Load Drivers (Default to Memory if none provided in plugins)
|
|
43
48
|
// TODO: Detect driver from plugins. For now, we still hard load memory driver if needed?
|
|
@@ -60,6 +65,14 @@ export class DataEngine {
|
|
|
60
65
|
|
|
61
66
|
// 3. Seed Data
|
|
62
67
|
await this.seed();
|
|
68
|
+
|
|
69
|
+
// 4. Start Runtime Plugins
|
|
70
|
+
for (const p of this.plugins) {
|
|
71
|
+
if (('onStart' in p) && typeof p.onStart === 'function') {
|
|
72
|
+
console.log(`[Kernel] Starting Plugin: ${p.name}`);
|
|
73
|
+
await p.onStart({ engine: this });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
63
76
|
}
|
|
64
77
|
|
|
65
78
|
async seed() {
|
|
@@ -85,19 +98,19 @@ export class DataEngine {
|
|
|
85
98
|
for (const appItem of apps) {
|
|
86
99
|
const app = appItem as any; // Cast to access data prop safely
|
|
87
100
|
if (app.data && Array.isArray(app.data)) {
|
|
88
|
-
console.log(`[
|
|
101
|
+
console.log(`[Kernel] Seeding data for ${app.name || app.id}...`);
|
|
89
102
|
for (const seed of app.data) {
|
|
90
103
|
try {
|
|
91
104
|
// Check if data exists
|
|
92
105
|
const existing = await this.ql.find(seed.object, { top: 1 });
|
|
93
106
|
if (existing.length === 0) {
|
|
94
|
-
console.log(`[
|
|
107
|
+
console.log(`[Kernel] Inserting ${seed.records.length} records into ${seed.object}`);
|
|
95
108
|
for (const record of seed.records) {
|
|
96
109
|
await this.ql.insert(seed.object, record);
|
|
97
110
|
}
|
|
98
111
|
}
|
|
99
112
|
} catch (e) {
|
|
100
|
-
console.warn(`[
|
|
113
|
+
console.warn(`[Kernel] Failed to seed ${seed.object}`, e);
|
|
101
114
|
}
|
|
102
115
|
}
|
|
103
116
|
}
|
package/src/protocol.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { SchemaRegistry } from '
|
|
2
|
-
import {
|
|
1
|
+
import { SchemaRegistry } from '@objectstack/objectql';
|
|
2
|
+
import { ObjectStackKernel } from './kernel';
|
|
3
3
|
|
|
4
4
|
export interface ApiRequest {
|
|
5
5
|
params: Record<string, string>;
|
|
@@ -8,9 +8,9 @@ export interface ApiRequest {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export class ObjectStackRuntimeProtocol {
|
|
11
|
-
private engine:
|
|
11
|
+
private engine: ObjectStackKernel;
|
|
12
12
|
|
|
13
|
-
constructor(engine:
|
|
13
|
+
constructor(engine: ObjectStackKernel) {
|
|
14
14
|
this.engine = engine;
|
|
15
15
|
}
|
|
16
16
|
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ObjectStackKernel } from './kernel';
|
|
2
|
+
|
|
3
|
+
export interface RuntimeContext {
|
|
4
|
+
engine: ObjectStackKernel;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface RuntimePlugin {
|
|
8
|
+
name: string;
|
|
9
|
+
install?: (ctx: RuntimeContext) => void | Promise<void>;
|
|
10
|
+
onStart?: (ctx: RuntimeContext) => void | Promise<void>;
|
|
11
|
+
}
|
package/dist/engine.d.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { DriverInterface, DriverOptions } from '@objectstack/spec';
|
|
2
|
-
/**
|
|
3
|
-
* Host Context provided to plugins
|
|
4
|
-
*/
|
|
5
|
-
export interface PluginContext {
|
|
6
|
-
ql: ObjectQL;
|
|
7
|
-
logger: Console;
|
|
8
|
-
[key: string]: any;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* ObjectQL Engine
|
|
12
|
-
*/
|
|
13
|
-
export declare class ObjectQL {
|
|
14
|
-
private drivers;
|
|
15
|
-
private defaultDriver;
|
|
16
|
-
private plugins;
|
|
17
|
-
private hostContext;
|
|
18
|
-
constructor(hostContext?: Record<string, any>);
|
|
19
|
-
/**
|
|
20
|
-
* Load and Register a Plugin
|
|
21
|
-
*/
|
|
22
|
-
use(manifestPart: any, runtimePart?: any): Promise<void>;
|
|
23
|
-
/**
|
|
24
|
-
* Register a new storage driver
|
|
25
|
-
*/
|
|
26
|
-
registerDriver(driver: DriverInterface, isDefault?: boolean): void;
|
|
27
|
-
/**
|
|
28
|
-
* Helper to get the target driver
|
|
29
|
-
*/
|
|
30
|
-
private getDriver;
|
|
31
|
-
/**
|
|
32
|
-
* Initialize the engine and all registered drivers
|
|
33
|
-
*/
|
|
34
|
-
init(): Promise<void>;
|
|
35
|
-
destroy(): Promise<void>;
|
|
36
|
-
find(object: string, filters?: any, options?: DriverOptions): Promise<Record<string, any>[]>;
|
|
37
|
-
insert(object: string, data: Record<string, any>, options?: DriverOptions): Promise<Record<string, any>>;
|
|
38
|
-
update(object: string, id: string, data: Record<string, any>, options?: DriverOptions): Promise<Record<string, any>>;
|
|
39
|
-
delete(object: string, id: string, options?: DriverOptions): Promise<boolean>;
|
|
40
|
-
}
|
package/dist/engine.js
DELETED
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ObjectQL = void 0;
|
|
4
|
-
const registry_1 = require("./registry");
|
|
5
|
-
/**
|
|
6
|
-
* ObjectQL Engine
|
|
7
|
-
*/
|
|
8
|
-
class ObjectQL {
|
|
9
|
-
constructor(hostContext = {}) {
|
|
10
|
-
this.drivers = new Map();
|
|
11
|
-
this.defaultDriver = null;
|
|
12
|
-
this.plugins = new Map();
|
|
13
|
-
// Host provided context additions (e.g. Server router)
|
|
14
|
-
this.hostContext = {};
|
|
15
|
-
this.hostContext = hostContext;
|
|
16
|
-
console.log(`[ObjectQL] Engine Instance Created`);
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Load and Register a Plugin
|
|
20
|
-
*/
|
|
21
|
-
async use(manifestPart, runtimePart) {
|
|
22
|
-
// 1. Validate / Register Manifest
|
|
23
|
-
if (manifestPart) {
|
|
24
|
-
// 1. Handle Module Imports (commonjs/esm interop)
|
|
25
|
-
// If the passed object is a module namespace with a default export, use that.
|
|
26
|
-
const manifest = manifestPart.default || manifestPart;
|
|
27
|
-
// In a real scenario, we might strictly parse this using Zod
|
|
28
|
-
// For now, simple ID check
|
|
29
|
-
const id = manifest.id || manifest.name;
|
|
30
|
-
if (!id) {
|
|
31
|
-
console.warn(`[ObjectQL] Plugin manifest missing ID (keys: ${Object.keys(manifest)})`, manifest);
|
|
32
|
-
// Don't return, try to proceed if it looks like an App (Apps might use 'name' instead of 'id')
|
|
33
|
-
// return;
|
|
34
|
-
}
|
|
35
|
-
console.log(`[ObjectQL] Loading Plugin: ${id}`);
|
|
36
|
-
registry_1.SchemaRegistry.registerPlugin(manifest);
|
|
37
|
-
// Register Objects from App/Plugin
|
|
38
|
-
if (manifest.objects) {
|
|
39
|
-
for (const obj of manifest.objects) {
|
|
40
|
-
// Ensure object name is registered globally
|
|
41
|
-
registry_1.SchemaRegistry.registerObject(obj);
|
|
42
|
-
console.log(`[ObjectQL] Registered Object: ${obj.name}`);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
// Register contributions
|
|
46
|
-
if (manifest.contributes?.kinds) {
|
|
47
|
-
for (const kind of manifest.contributes.kinds) {
|
|
48
|
-
registry_1.SchemaRegistry.registerKind(kind);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
// Register Data Seeding (Lazy execution or immediate?)
|
|
52
|
-
// We store it in a temporary registry or execute immediately if engine is ready.
|
|
53
|
-
// Since `use` is init time, we might need to store it and run later in `seed()`.
|
|
54
|
-
// For this MVP, let's attach it to the manifest object in registry so DataEngine can find it.
|
|
55
|
-
}
|
|
56
|
-
// 2. Execute Runtime
|
|
57
|
-
if (runtimePart) {
|
|
58
|
-
const pluginDef = runtimePart.default || runtimePart;
|
|
59
|
-
if (pluginDef.onEnable) {
|
|
60
|
-
const context = {
|
|
61
|
-
ql: this,
|
|
62
|
-
logger: console,
|
|
63
|
-
// Expose the driver registry helper explicitly if needed
|
|
64
|
-
drivers: {
|
|
65
|
-
register: (driver) => this.registerDriver(driver)
|
|
66
|
-
},
|
|
67
|
-
...this.hostContext
|
|
68
|
-
};
|
|
69
|
-
await pluginDef.onEnable(context);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Register a new storage driver
|
|
75
|
-
*/
|
|
76
|
-
registerDriver(driver, isDefault = false) {
|
|
77
|
-
if (this.drivers.has(driver.name)) {
|
|
78
|
-
console.warn(`[ObjectQL] Driver ${driver.name} is already registered. Skipping.`);
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
this.drivers.set(driver.name, driver);
|
|
82
|
-
console.log(`[ObjectQL] Registered driver: ${driver.name} v${driver.version}`);
|
|
83
|
-
if (isDefault || this.drivers.size === 1) {
|
|
84
|
-
this.defaultDriver = driver.name;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Helper to get the target driver
|
|
89
|
-
*/
|
|
90
|
-
getDriver(object) {
|
|
91
|
-
// TODO: Look up Object definition to see if it specifies a specific datasource/driver
|
|
92
|
-
// For now, always return default
|
|
93
|
-
if (!this.defaultDriver) {
|
|
94
|
-
throw new Error('[ObjectQL] No drivers registered!');
|
|
95
|
-
}
|
|
96
|
-
return this.drivers.get(this.defaultDriver);
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Initialize the engine and all registered drivers
|
|
100
|
-
*/
|
|
101
|
-
async init() {
|
|
102
|
-
console.log('[ObjectQL] Initializing drivers...');
|
|
103
|
-
for (const [name, driver] of this.drivers) {
|
|
104
|
-
try {
|
|
105
|
-
await driver.connect();
|
|
106
|
-
}
|
|
107
|
-
catch (e) {
|
|
108
|
-
console.error(`[ObjectQL] Failed to connect driver ${name}`, e);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
// In a real app, we would sync schemas here
|
|
112
|
-
}
|
|
113
|
-
async destroy() {
|
|
114
|
-
for (const driver of this.drivers.values()) {
|
|
115
|
-
await driver.disconnect();
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
// ============================================
|
|
119
|
-
// Data Access Methods
|
|
120
|
-
// ============================================
|
|
121
|
-
async find(object, filters = {}, options) {
|
|
122
|
-
const driver = this.getDriver(object);
|
|
123
|
-
console.log(`[ObjectQL] Finding ${object} on ${driver.name}...`);
|
|
124
|
-
// Transform simplified filters to QueryAST
|
|
125
|
-
// This is a simplified "Mock" transform.
|
|
126
|
-
// Real implementation would parse complex JSON or FilterBuilders.
|
|
127
|
-
const ast = {
|
|
128
|
-
object, // Add missing required field
|
|
129
|
-
// Pass through if it looks like AST, otherwise empty
|
|
130
|
-
// In this demo, we assume the caller passes a simplified object or raw AST
|
|
131
|
-
filters: filters.filters || undefined,
|
|
132
|
-
top: filters.top || 100,
|
|
133
|
-
sort: filters.sort || []
|
|
134
|
-
};
|
|
135
|
-
return driver.find(object, ast, options);
|
|
136
|
-
}
|
|
137
|
-
async insert(object, data, options) {
|
|
138
|
-
const driver = this.getDriver(object);
|
|
139
|
-
console.log(`[ObjectQL] Creating ${object} on ${driver.name}...`);
|
|
140
|
-
// 1. Validate Schema
|
|
141
|
-
// 2. Run "Before Insert" Triggers
|
|
142
|
-
const result = await driver.create(object, data, options);
|
|
143
|
-
// 3. Run "After Insert" Triggers
|
|
144
|
-
return result;
|
|
145
|
-
}
|
|
146
|
-
async update(object, id, data, options) {
|
|
147
|
-
const driver = this.getDriver(object);
|
|
148
|
-
console.log(`[ObjectQL] Updating ${object} ${id}...`);
|
|
149
|
-
return driver.update(object, id, data, options);
|
|
150
|
-
}
|
|
151
|
-
async delete(object, id, options) {
|
|
152
|
-
const driver = this.getDriver(object);
|
|
153
|
-
console.log(`[ObjectQL] Deleting ${object} ${id}...`);
|
|
154
|
-
return driver.delete(object, id, options);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
exports.ObjectQL = ObjectQL;
|
package/dist/registry.d.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { ServiceObject, App, ObjectStackManifest } from '@objectstack/spec';
|
|
2
|
-
/**
|
|
3
|
-
* Global Schema Registry
|
|
4
|
-
* Unified storage for all metadata types (Objects, Apps, Flows, Layouts, etc.)
|
|
5
|
-
*/
|
|
6
|
-
export declare class SchemaRegistry {
|
|
7
|
-
private static metadata;
|
|
8
|
-
/**
|
|
9
|
-
* Universal Register Method
|
|
10
|
-
* @param type The category of metadata (e.g., 'object', 'app', 'plugin')
|
|
11
|
-
* @param item The metadata item itself
|
|
12
|
-
* @param keyField The property to use as the unique key (default: 'name')
|
|
13
|
-
*/
|
|
14
|
-
static registerItem<T>(type: string, item: T, keyField?: keyof T): void;
|
|
15
|
-
/**
|
|
16
|
-
* Universal Get Method
|
|
17
|
-
*/
|
|
18
|
-
static getItem<T>(type: string, name: string): T | undefined;
|
|
19
|
-
/**
|
|
20
|
-
* Universal List Method
|
|
21
|
-
*/
|
|
22
|
-
static listItems<T>(type: string): T[];
|
|
23
|
-
/**
|
|
24
|
-
* Get all registered metadata types (Kinds)
|
|
25
|
-
*/
|
|
26
|
-
static getRegisteredTypes(): string[];
|
|
27
|
-
/**
|
|
28
|
-
* Object Helpers
|
|
29
|
-
*/
|
|
30
|
-
static registerObject(schema: ServiceObject): void;
|
|
31
|
-
static getObject(name: string): ServiceObject | undefined;
|
|
32
|
-
static getAllObjects(): ServiceObject[];
|
|
33
|
-
/**
|
|
34
|
-
* App Helpers
|
|
35
|
-
*/
|
|
36
|
-
static registerApp(app: App): void;
|
|
37
|
-
static getApp(name: string): App | undefined;
|
|
38
|
-
static getAllApps(): App[];
|
|
39
|
-
/**
|
|
40
|
-
* Plugin Helpers
|
|
41
|
-
*/
|
|
42
|
-
static registerPlugin(manifest: ObjectStackManifest): void;
|
|
43
|
-
static getAllPlugins(): ObjectStackManifest[];
|
|
44
|
-
/**
|
|
45
|
-
* Kind (Metadata Type) Helpers
|
|
46
|
-
*/
|
|
47
|
-
static registerKind(kind: {
|
|
48
|
-
id: string;
|
|
49
|
-
globs: string[];
|
|
50
|
-
}): void;
|
|
51
|
-
static getAllKinds(): {
|
|
52
|
-
id: string;
|
|
53
|
-
globs: string[];
|
|
54
|
-
}[];
|
|
55
|
-
}
|
package/dist/registry.js
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SchemaRegistry = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Global Schema Registry
|
|
6
|
-
* Unified storage for all metadata types (Objects, Apps, Flows, Layouts, etc.)
|
|
7
|
-
*/
|
|
8
|
-
class SchemaRegistry {
|
|
9
|
-
/**
|
|
10
|
-
* Universal Register Method
|
|
11
|
-
* @param type The category of metadata (e.g., 'object', 'app', 'plugin')
|
|
12
|
-
* @param item The metadata item itself
|
|
13
|
-
* @param keyField The property to use as the unique key (default: 'name')
|
|
14
|
-
*/
|
|
15
|
-
static registerItem(type, item, keyField = 'name') {
|
|
16
|
-
if (!this.metadata.has(type)) {
|
|
17
|
-
this.metadata.set(type, new Map());
|
|
18
|
-
}
|
|
19
|
-
const collection = this.metadata.get(type);
|
|
20
|
-
const key = String(item[keyField]);
|
|
21
|
-
if (collection.has(key)) {
|
|
22
|
-
console.warn(`[Registry] Overwriting ${type}: ${key}`);
|
|
23
|
-
}
|
|
24
|
-
collection.set(key, item);
|
|
25
|
-
console.log(`[Registry] Registered ${type}: ${key}`);
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Universal Get Method
|
|
29
|
-
*/
|
|
30
|
-
static getItem(type, name) {
|
|
31
|
-
return this.metadata.get(type)?.get(name);
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Universal List Method
|
|
35
|
-
*/
|
|
36
|
-
static listItems(type) {
|
|
37
|
-
return Array.from(this.metadata.get(type)?.values() || []);
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Get all registered metadata types (Kinds)
|
|
41
|
-
*/
|
|
42
|
-
static getRegisteredTypes() {
|
|
43
|
-
return Array.from(this.metadata.keys());
|
|
44
|
-
}
|
|
45
|
-
// ==========================================
|
|
46
|
-
// Typed Helper Methods (Shortcuts)
|
|
47
|
-
// ==========================================
|
|
48
|
-
/**
|
|
49
|
-
* Object Helpers
|
|
50
|
-
*/
|
|
51
|
-
static registerObject(schema) {
|
|
52
|
-
this.registerItem('object', schema, 'name');
|
|
53
|
-
}
|
|
54
|
-
static getObject(name) {
|
|
55
|
-
return this.getItem('object', name);
|
|
56
|
-
}
|
|
57
|
-
static getAllObjects() {
|
|
58
|
-
return this.listItems('object');
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* App Helpers
|
|
62
|
-
*/
|
|
63
|
-
static registerApp(app) {
|
|
64
|
-
this.registerItem('app', app, 'name');
|
|
65
|
-
}
|
|
66
|
-
static getApp(name) {
|
|
67
|
-
return this.getItem('app', name);
|
|
68
|
-
}
|
|
69
|
-
static getAllApps() {
|
|
70
|
-
return this.listItems('app');
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Plugin Helpers
|
|
74
|
-
*/
|
|
75
|
-
static registerPlugin(manifest) {
|
|
76
|
-
this.registerItem('plugin', manifest, 'id');
|
|
77
|
-
}
|
|
78
|
-
static getAllPlugins() {
|
|
79
|
-
return this.listItems('plugin');
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Kind (Metadata Type) Helpers
|
|
83
|
-
*/
|
|
84
|
-
static registerKind(kind) {
|
|
85
|
-
this.registerItem('kind', kind, 'id');
|
|
86
|
-
}
|
|
87
|
-
static getAllKinds() {
|
|
88
|
-
return this.listItems('kind');
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
exports.SchemaRegistry = SchemaRegistry;
|
|
92
|
-
// Nested Map: Type -> Name/ID -> MetadataItem
|
|
93
|
-
SchemaRegistry.metadata = new Map();
|
package/src/engine.ts
DELETED
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
import { DriverInterface, DriverOptions, QueryAST, ObjectStackManifest, ManifestSchema } from '@objectstack/spec';
|
|
2
|
-
import { SchemaRegistry } from './registry';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Host Context provided to plugins
|
|
6
|
-
*/
|
|
7
|
-
export interface PluginContext {
|
|
8
|
-
ql: ObjectQL;
|
|
9
|
-
logger: Console;
|
|
10
|
-
// Extensible map for host-specific globals (like HTTP Router, etc.)
|
|
11
|
-
[key: string]: any;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* ObjectQL Engine
|
|
16
|
-
*/
|
|
17
|
-
export class ObjectQL {
|
|
18
|
-
private drivers = new Map<string, DriverInterface>();
|
|
19
|
-
private defaultDriver: string | null = null;
|
|
20
|
-
private plugins = new Map<string, any>();
|
|
21
|
-
|
|
22
|
-
// Host provided context additions (e.g. Server router)
|
|
23
|
-
private hostContext: Record<string, any> = {};
|
|
24
|
-
|
|
25
|
-
constructor(hostContext: Record<string, any> = {}) {
|
|
26
|
-
this.hostContext = hostContext;
|
|
27
|
-
console.log(`[ObjectQL] Engine Instance Created`);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Load and Register a Plugin
|
|
32
|
-
*/
|
|
33
|
-
async use(manifestPart: any, runtimePart?: any) {
|
|
34
|
-
// 1. Validate / Register Manifest
|
|
35
|
-
if (manifestPart) {
|
|
36
|
-
// 1. Handle Module Imports (commonjs/esm interop)
|
|
37
|
-
// If the passed object is a module namespace with a default export, use that.
|
|
38
|
-
const manifest = manifestPart.default || manifestPart;
|
|
39
|
-
|
|
40
|
-
// In a real scenario, we might strictly parse this using Zod
|
|
41
|
-
// For now, simple ID check
|
|
42
|
-
const id = manifest.id || manifest.name;
|
|
43
|
-
if (!id) {
|
|
44
|
-
console.warn(`[ObjectQL] Plugin manifest missing ID (keys: ${Object.keys(manifest)})`, manifest);
|
|
45
|
-
// Don't return, try to proceed if it looks like an App (Apps might use 'name' instead of 'id')
|
|
46
|
-
// return;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
console.log(`[ObjectQL] Loading Plugin: ${id}`);
|
|
50
|
-
SchemaRegistry.registerPlugin(manifest as ObjectStackManifest);
|
|
51
|
-
|
|
52
|
-
// Register Objects from App/Plugin
|
|
53
|
-
if (manifest.objects) {
|
|
54
|
-
for (const obj of manifest.objects) {
|
|
55
|
-
// Ensure object name is registered globally
|
|
56
|
-
SchemaRegistry.registerObject(obj);
|
|
57
|
-
console.log(`[ObjectQL] Registered Object: ${obj.name}`);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Register contributions
|
|
62
|
-
if (manifest.contributes?.kinds) {
|
|
63
|
-
for (const kind of manifest.contributes.kinds) {
|
|
64
|
-
SchemaRegistry.registerKind(kind);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Register Data Seeding (Lazy execution or immediate?)
|
|
69
|
-
// We store it in a temporary registry or execute immediately if engine is ready.
|
|
70
|
-
// Since `use` is init time, we might need to store it and run later in `seed()`.
|
|
71
|
-
// For this MVP, let's attach it to the manifest object in registry so DataEngine can find it.
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// 2. Execute Runtime
|
|
75
|
-
if (runtimePart) {
|
|
76
|
-
const pluginDef = (runtimePart as any).default || runtimePart;
|
|
77
|
-
if (pluginDef.onEnable) {
|
|
78
|
-
const context: PluginContext = {
|
|
79
|
-
ql: this,
|
|
80
|
-
logger: console,
|
|
81
|
-
// Expose the driver registry helper explicitly if needed
|
|
82
|
-
drivers: {
|
|
83
|
-
register: (driver: DriverInterface) => this.registerDriver(driver)
|
|
84
|
-
},
|
|
85
|
-
...this.hostContext
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
await pluginDef.onEnable(context);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Register a new storage driver
|
|
95
|
-
*/
|
|
96
|
-
registerDriver(driver: DriverInterface, isDefault: boolean = false) {
|
|
97
|
-
if (this.drivers.has(driver.name)) {
|
|
98
|
-
console.warn(`[ObjectQL] Driver ${driver.name} is already registered. Skipping.`);
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
this.drivers.set(driver.name, driver);
|
|
103
|
-
console.log(`[ObjectQL] Registered driver: ${driver.name} v${driver.version}`);
|
|
104
|
-
|
|
105
|
-
if (isDefault || this.drivers.size === 1) {
|
|
106
|
-
this.defaultDriver = driver.name;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Helper to get the target driver
|
|
112
|
-
*/
|
|
113
|
-
private getDriver(object: string): DriverInterface {
|
|
114
|
-
// TODO: Look up Object definition to see if it specifies a specific datasource/driver
|
|
115
|
-
// For now, always return default
|
|
116
|
-
if (!this.defaultDriver) {
|
|
117
|
-
throw new Error('[ObjectQL] No drivers registered!');
|
|
118
|
-
}
|
|
119
|
-
return this.drivers.get(this.defaultDriver)!;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Initialize the engine and all registered drivers
|
|
124
|
-
*/
|
|
125
|
-
async init() {
|
|
126
|
-
console.log('[ObjectQL] Initializing drivers...');
|
|
127
|
-
for (const [name, driver] of this.drivers) {
|
|
128
|
-
try {
|
|
129
|
-
await driver.connect();
|
|
130
|
-
} catch (e) {
|
|
131
|
-
console.error(`[ObjectQL] Failed to connect driver ${name}`, e);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
// In a real app, we would sync schemas here
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
async destroy() {
|
|
138
|
-
for (const driver of this.drivers.values()) {
|
|
139
|
-
await driver.disconnect();
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// ============================================
|
|
144
|
-
// Data Access Methods
|
|
145
|
-
// ============================================
|
|
146
|
-
|
|
147
|
-
async find(object: string, filters: any = {}, options?: DriverOptions) {
|
|
148
|
-
const driver = this.getDriver(object);
|
|
149
|
-
console.log(`[ObjectQL] Finding ${object} on ${driver.name}...`);
|
|
150
|
-
|
|
151
|
-
// Transform simplified filters to QueryAST
|
|
152
|
-
// This is a simplified "Mock" transform.
|
|
153
|
-
// Real implementation would parse complex JSON or FilterBuilders.
|
|
154
|
-
const ast: QueryAST = {
|
|
155
|
-
object, // Add missing required field
|
|
156
|
-
// Pass through if it looks like AST, otherwise empty
|
|
157
|
-
// In this demo, we assume the caller passes a simplified object or raw AST
|
|
158
|
-
filters: filters.filters || undefined,
|
|
159
|
-
top: filters.top || 100,
|
|
160
|
-
sort: filters.sort || []
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
return driver.find(object, ast, options);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
async insert(object: string, data: Record<string, any>, options?: DriverOptions) {
|
|
167
|
-
const driver = this.getDriver(object);
|
|
168
|
-
console.log(`[ObjectQL] Creating ${object} on ${driver.name}...`);
|
|
169
|
-
// 1. Validate Schema
|
|
170
|
-
// 2. Run "Before Insert" Triggers
|
|
171
|
-
|
|
172
|
-
const result = await driver.create(object, data, options);
|
|
173
|
-
|
|
174
|
-
// 3. Run "After Insert" Triggers
|
|
175
|
-
return result;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
async update(object: string, id: string, data: Record<string, any>, options?: DriverOptions) {
|
|
179
|
-
const driver = this.getDriver(object);
|
|
180
|
-
console.log(`[ObjectQL] Updating ${object} ${id}...`);
|
|
181
|
-
return driver.update(object, id, data, options);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
async delete(object: string, id: string, options?: DriverOptions) {
|
|
185
|
-
const driver = this.getDriver(object);
|
|
186
|
-
console.log(`[ObjectQL] Deleting ${object} ${id}...`);
|
|
187
|
-
return driver.delete(object, id, options);
|
|
188
|
-
}
|
|
189
|
-
}
|
package/src/registry.ts
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import { ServiceObject, App, ObjectStackManifest } from '@objectstack/spec';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Global Schema Registry
|
|
5
|
-
* Unified storage for all metadata types (Objects, Apps, Flows, Layouts, etc.)
|
|
6
|
-
*/
|
|
7
|
-
export class SchemaRegistry {
|
|
8
|
-
// Nested Map: Type -> Name/ID -> MetadataItem
|
|
9
|
-
private static metadata = new Map<string, Map<string, any>>();
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Universal Register Method
|
|
13
|
-
* @param type The category of metadata (e.g., 'object', 'app', 'plugin')
|
|
14
|
-
* @param item The metadata item itself
|
|
15
|
-
* @param keyField The property to use as the unique key (default: 'name')
|
|
16
|
-
*/
|
|
17
|
-
static registerItem<T>(type: string, item: T, keyField: keyof T = 'name' as keyof T) {
|
|
18
|
-
if (!this.metadata.has(type)) {
|
|
19
|
-
this.metadata.set(type, new Map());
|
|
20
|
-
}
|
|
21
|
-
const collection = this.metadata.get(type)!;
|
|
22
|
-
const key = String(item[keyField]);
|
|
23
|
-
|
|
24
|
-
if (collection.has(key)) {
|
|
25
|
-
console.warn(`[Registry] Overwriting ${type}: ${key}`);
|
|
26
|
-
}
|
|
27
|
-
collection.set(key, item);
|
|
28
|
-
console.log(`[Registry] Registered ${type}: ${key}`);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Universal Get Method
|
|
33
|
-
*/
|
|
34
|
-
static getItem<T>(type: string, name: string): T | undefined {
|
|
35
|
-
return this.metadata.get(type)?.get(name) as T;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Universal List Method
|
|
40
|
-
*/
|
|
41
|
-
static listItems<T>(type: string): T[] {
|
|
42
|
-
return Array.from(this.metadata.get(type)?.values() || []) as T[];
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Get all registered metadata types (Kinds)
|
|
47
|
-
*/
|
|
48
|
-
static getRegisteredTypes(): string[] {
|
|
49
|
-
return Array.from(this.metadata.keys());
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// ==========================================
|
|
53
|
-
// Typed Helper Methods (Shortcuts)
|
|
54
|
-
// ==========================================
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Object Helpers
|
|
58
|
-
*/
|
|
59
|
-
static registerObject(schema: ServiceObject) {
|
|
60
|
-
this.registerItem('object', schema, 'name');
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
static getObject(name: string): ServiceObject | undefined {
|
|
64
|
-
return this.getItem<ServiceObject>('object', name);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
static getAllObjects(): ServiceObject[] {
|
|
68
|
-
return this.listItems<ServiceObject>('object');
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* App Helpers
|
|
73
|
-
*/
|
|
74
|
-
static registerApp(app: App) {
|
|
75
|
-
this.registerItem('app', app, 'name');
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
static getApp(name: string): App | undefined {
|
|
79
|
-
return this.getItem<App>('app', name);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
static getAllApps(): App[] {
|
|
83
|
-
return this.listItems<App>('app');
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Plugin Helpers
|
|
88
|
-
*/
|
|
89
|
-
static registerPlugin(manifest: ObjectStackManifest) {
|
|
90
|
-
this.registerItem('plugin', manifest, 'id');
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
static getAllPlugins(): ObjectStackManifest[] {
|
|
94
|
-
return this.listItems<ObjectStackManifest>('plugin');
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Kind (Metadata Type) Helpers
|
|
99
|
-
*/
|
|
100
|
-
static registerKind(kind: { id: string, globs: string[] }) {
|
|
101
|
-
this.registerItem('kind', kind, 'id');
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
static getAllKinds(): { id: string, globs: string[] }[] {
|
|
105
|
-
return this.listItems('kind');
|
|
106
|
-
}
|
|
107
|
-
}
|