Skip to content

Commit 96dec98

Browse files
committed
Refactor ObjectQL and Hono server integration; add protocol implementation and update dependencies
1 parent 16d2521 commit 96dec98

File tree

10 files changed

+211
-204
lines changed

10 files changed

+211
-204
lines changed

packages/core/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,8 @@
1010
},
1111
"devDependencies": {
1212
"typescript": "^5.0.0"
13+
},
14+
"dependencies": {
15+
"@objectstack/spec": "workspace:*"
1316
}
1417
}

packages/objectql/src/plugin.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
import { ObjectQL } from './index';
2+
import { ObjectStackProtocolImplementation } from './protocol';
3+
// IObjectStackProtocol is used for type checking implicitly via ObjectStackProtocolImplementation contract
24

35
// Minimal Context interface to avoid circular dependency on @objectstack/runtime
46
export interface PluginContext {
57
registerService(name: string, service: any): void;
68
logger: Console;
9+
// We need access to the kernel-like object to pass to protocol,
10+
// or at least expose getService on context if it's there
11+
getService?: <T>(name: string) => T;
712
[key: string]: any;
813
}
914

@@ -31,6 +36,15 @@ export class ObjectQLPlugin {
3136

3237
ctx.registerService('objectql', this.ql);
3338
if(ctx.logger) ctx.logger.log(`[ObjectQLPlugin] ObjectQL engine registered as service`);
39+
40+
// Register Protocol Implementation
41+
if (!this.ql) {
42+
throw new Error('ObjectQL engine not initialized');
43+
}
44+
const protocolShim = new ObjectStackProtocolImplementation(this.ql);
45+
46+
ctx.registerService('protocol', protocolShim);
47+
if(ctx.logger) ctx.logger.log(`[ObjectQLPlugin] Protocol service registered`);
3448
}
3549

3650
async start(ctx: PluginContext) {

packages/objectql/src/protocol.ts

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { IObjectStackProtocol } from '@objectstack/spec/api';
2+
import { IDataEngine } from '@objectstack/spec/system';
3+
4+
// We import SchemaRegistry directly since this class lives in the same package
5+
import { SchemaRegistry } from './registry';
6+
7+
export class ObjectStackProtocolImplementation implements IObjectStackProtocol {
8+
private engine: IDataEngine;
9+
10+
constructor(engine: IDataEngine) {
11+
this.engine = engine;
12+
}
13+
14+
getDiscovery() {
15+
return {
16+
name: 'ObjectStack API',
17+
version: '1.0',
18+
capabilities: {
19+
metadata: true,
20+
data: true,
21+
ui: true
22+
}
23+
};
24+
}
25+
26+
getMetaTypes() {
27+
return SchemaRegistry.getRegisteredTypes();
28+
}
29+
30+
getMetaItems(type: string) {
31+
return SchemaRegistry.listItems(type);
32+
}
33+
34+
getMetaItem(type: string, name: string) {
35+
return SchemaRegistry.getItem(type, name);
36+
}
37+
38+
getUiView(object: string, type: 'list' | 'form') {
39+
const schema = SchemaRegistry.getObject(object);
40+
if (!schema) throw new Error(`Object ${object} not found`);
41+
42+
if (type === 'list') {
43+
return {
44+
type: 'list',
45+
object: object,
46+
columns: Object.keys(schema.fields || {}).slice(0, 5).map(f => ({
47+
field: f,
48+
label: schema.fields[f].label || f
49+
}))
50+
};
51+
} else {
52+
return {
53+
type: 'form',
54+
object: object,
55+
sections: [
56+
{
57+
label: 'General',
58+
fields: Object.keys(schema.fields || {}).map(f => ({
59+
field: f
60+
}))
61+
}
62+
]
63+
};
64+
}
65+
}
66+
67+
findData(object: string, query: any) {
68+
return this.engine.find(object, query);
69+
}
70+
71+
async getData(object: string, id: string) {
72+
// IDataEngine doesn't have findOne, so we simulate it with find and limit 1
73+
// Assuming the ID field is named '_id' or 'id'.
74+
// For broad compatibility, we might need to know the ID field name.
75+
// But traditionally it is _id in ObjectStack/mongo or id in others.
76+
// Let's rely on finding by ID if the engine supports it via find?
77+
// Actually, ObjectQL (the implementation) DOES have findOne.
78+
// But we are programming against IDataEngine interface here.
79+
80+
// If the engine IS ObjectQL (which it practically is), we could cast it.
81+
// But let's try to stick to interface.
82+
83+
const results = await this.engine.find(object, {
84+
filter: { _id: id }, // Default Assumption: _id
85+
limit: 1
86+
});
87+
if (results && results.length > 0) {
88+
return results[0];
89+
}
90+
throw new Error(`Record ${id} not found in ${object}`);
91+
}
92+
93+
createData(object: string, data: any) {
94+
return this.engine.insert(object, data);
95+
}
96+
97+
updateData(object: string, id: string, data: any) {
98+
return this.engine.update(object, id, data);
99+
}
100+
101+
deleteData(object: string, id: string) {
102+
return this.engine.delete(object, id);
103+
}
104+
}

packages/plugin-hono-server/package.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,13 @@
99
},
1010
"dependencies": {
1111
"@hono/node-server": "^1.2.0",
12+
"@objectstack/core": "workspace:*",
1213
"@objectstack/spec": "workspace:*",
1314
"@objectstack/types": "workspace:*",
14-
"@objectstack/runtime": "workspace:*",
1515
"hono": "^4.0.0"
1616
},
1717
"devDependencies": {
1818
"@types/node": "^20.0.0",
1919
"typescript": "^5.0.0"
20-
},
21-
"peerDependencies": {
22-
"@objectstack/runtime": "^0.4.2"
2320
}
2421
}

packages/plugin-hono-server/src/hono-plugin.ts

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
1-
import {
2-
Plugin,
3-
PluginContext,
4-
ObjectStackRuntimeProtocol
5-
} from '@objectstack/runtime';
6-
// Use the new IHttpServer interface
7-
import { IHttpServer } from '@objectstack/spec/api';
1+
import { Plugin, PluginContext } from '@objectstack/core';
2+
import { IHttpServer, IObjectStackProtocol } from '@objectstack/spec/api';
83
import { HonoHttpServer } from './adapter';
94

105
export interface HonoPluginOptions {
@@ -46,24 +41,13 @@ export class HonoServerPlugin implements Plugin {
4641
* Start phase - Bind routes and start listening
4742
*/
4843
async start(ctx: PluginContext) {
49-
// Get ObjectQL directly from services
50-
let protocol: ObjectStackRuntimeProtocol | null = null;
44+
// Get protocol implementation instance
45+
let protocol: IObjectStackProtocol | null = null;
5146

5247
try {
53-
const objectql = ctx.getService<any>('objectql');
54-
55-
// Create Protocol Instance with faked Kernel
56-
// This is necessary because Protocol expects full Kernel but we only have Context
57-
protocol = new ObjectStackRuntimeProtocol({
58-
getService: (name: string) => {
59-
if (name === 'objectql') return objectql;
60-
throw new Error(`[HonoPlugin] Service ${name} not found`);
61-
},
62-
getAllPlugins: () => [] // Mock
63-
} as any);
64-
48+
protocol = ctx.getService<IObjectStackProtocol>('protocol');
6549
} catch (e) {
66-
ctx.logger.log('[HonoServerPlugin] ObjectQL service not found, skipping protocol routes');
50+
ctx.logger.log('[HonoServerPlugin] Protocol service not found, skipping protocol routes');
6751
}
6852

6953
// Register protocol routes if available

packages/runtime/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export { DriverPlugin } from './driver-plugin.js';
1010
export { AppManifestPlugin } from './app-manifest-plugin.js';
1111

1212
// Export Protocol
13-
export { ObjectStackRuntimeProtocol } from './protocol.js';
13+
// export { ObjectStackRuntimeProtocol } from './protocol.js';
1414

1515
// Export Types
1616
export * from '@objectstack/core';

packages/runtime/src/protocol.ts

Lines changed: 0 additions & 175 deletions
This file was deleted.

packages/spec/src/api/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,5 @@ export * from './router.zod';
1515
export * from './odata.zod';
1616

1717
export * from './http-server';
18+
export * from './protocol';
19+

0 commit comments

Comments
 (0)