Skip to content

Commit 0621e14

Browse files
committed
Enhance HonoServerPlugin to implement ObjectStackRuntimeProtocol and add API routes for metadata and data operations
1 parent ce72c60 commit 0621e14

File tree

2 files changed

+56
-11
lines changed

2 files changed

+56
-11
lines changed

packages/plugin-hono-server/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111
"@hono/node-server": "^1.2.0",
1212
"@objectstack/spec": "workspace:*",
1313
"@objectstack/types": "workspace:*",
14+
"@objectstack/runtime": "workspace:*",
1415
"hono": "^4.0.0"
1516
},
1617
"devDependencies": {
17-
"@objectstack/runtime": "workspace:*",
1818
"@types/node": "^20.0.0",
1919
"typescript": "^5.0.0"
2020
},

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

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,22 +66,67 @@ export class HonoServerPlugin implements Plugin {
6666

6767
try {
6868
const objectql = ctx.getService<any>('objectql');
69-
// For now, we create a minimal protocol wrapper
70-
// In future, we'd refactor protocol to work with services directly
71-
protocol = {
72-
getDiscovery: () => ({
73-
name: 'ObjectOS Server',
74-
version: '1.0.0',
75-
environment: process.env.NODE_ENV || 'development',
76-
}),
77-
} as any;
69+
70+
// Create Protocol Instance with faked Kernel
71+
// This is necessary because Protocol expects full Kernel but we only have Context
72+
protocol = new ObjectStackRuntimeProtocol({
73+
getService: (name: string) => {
74+
if (name === 'objectql') return objectql;
75+
throw new Error(`[HonoPlugin] Service ${name} not found`);
76+
}
77+
} as any);
78+
7879
} catch (e) {
7980
ctx.logger.log('[HonoServerPlugin] ObjectQL service not found, skipping protocol routes');
8081
}
8182

8283
// Register protocol routes if available
8384
if (protocol) {
84-
this.app.get('/api/v1', (c) => c.json(protocol!.getDiscovery()));
85+
const p = protocol!;
86+
this.app.get('/api/v1', (c) => c.json(p.getDiscovery()));
87+
88+
// Meta Protocol
89+
this.app.get('/api/v1/meta', (c) => c.json(p.getMetaTypes()));
90+
this.app.get('/api/v1/meta/:type', (c) => c.json(p.getMetaItems(c.req.param('type'))));
91+
this.app.get('/api/v1/meta/:type/:name', (c) => {
92+
try {
93+
return c.json(p.getMetaItem(c.req.param('type'), c.req.param('name')));
94+
} catch(e:any) {
95+
return c.json({error: e.message}, 404);
96+
}
97+
});
98+
99+
// Data Protocol
100+
this.app.get('/api/v1/data/:object', async (c) => {
101+
try { return c.json(await p.findData(c.req.param('object'), c.req.query())); }
102+
catch(e:any) { return c.json({error:e.message}, 400); }
103+
});
104+
this.app.get('/api/v1/data/:object/:id', async (c) => {
105+
try { return c.json(await p.getData(c.req.param('object'), c.req.param('id'))); }
106+
catch(e:any) { return c.json({error:e.message}, 404); }
107+
});
108+
this.app.post('/api/v1/data/:object', async (c) => {
109+
try { return c.json(await p.createData(c.req.param('object'), await c.req.json()), 201); }
110+
catch(e:any) { return c.json({error:e.message}, 400); }
111+
});
112+
this.app.patch('/api/v1/data/:object/:id', async (c) => {
113+
try { return c.json(await p.updateData(c.req.param('object'), c.req.param('id'), await c.req.json())); }
114+
catch(e:any) { return c.json({error:e.message}, 400); }
115+
});
116+
this.app.delete('/api/v1/data/:object/:id', async (c) => {
117+
try { return c.json(await p.deleteData(c.req.param('object'), c.req.param('id'))); }
118+
catch(e:any) { return c.json({error:e.message}, 400); }
119+
});
120+
121+
// UI Protocol
122+
// @ts-ignore
123+
this.app.get('/api/v1/ui/view/:object', (c) => {
124+
try {
125+
const viewType = (c.req.query('type') as 'list' | 'form') || 'list';
126+
return c.json(p.getUiView(c.req.param('object'), viewType));
127+
}
128+
catch(e:any) { return c.json({error:e.message}, 404); }
129+
});
85130
}
86131

87132
// Static files

0 commit comments

Comments
 (0)