@objectstack/plugin-hono-server 0.6.1 → 0.7.2

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 CHANGED
@@ -1,5 +1,25 @@
1
1
  # @objectstack/plugin-hono-server
2
2
 
3
+ ## 0.7.2
4
+
5
+ ### Patch Changes
6
+
7
+ - fb41cc0: Patch release: Updated documentation and JSON schemas
8
+ - Updated dependencies [fb41cc0]
9
+ - @objectstack/spec@0.7.2
10
+ - @objectstack/core@0.7.2
11
+ - @objectstack/types@0.7.2
12
+
13
+ ## 0.7.1
14
+
15
+ ### Patch Changes
16
+
17
+ - Patch release for maintenance and stability improvements
18
+ - Updated dependencies
19
+ - @objectstack/spec@0.7.1
20
+ - @objectstack/types@0.7.1
21
+ - @objectstack/core@0.7.1
22
+
3
23
  ## 0.6.1
4
24
 
5
25
  ### Patch Changes
package/README.md ADDED
@@ -0,0 +1,324 @@
1
+ # @objectstack/plugin-hono-server
2
+
3
+ HTTP Server Adapter for ObjectStack Runtime using the [Hono](https://hono.dev/) framework. This plugin provides a production-ready REST API gateway for ObjectStack applications.
4
+
5
+ ## Plugin Capabilities
6
+
7
+ This plugin implements the ObjectStack plugin capability protocol:
8
+ - **Type**: `adapter`
9
+ - **Protocol**: `com.objectstack.protocol.http.v1` (full conformance)
10
+ - **Protocol**: `com.objectstack.protocol.api.rest.v1` (full conformance)
11
+ - **Provides**: `IHttpServer` interface for HTTP server operations
12
+ - **Requires**: `com.objectstack.engine.objectql` (optional) for protocol implementation
13
+ - **Extension Points**:
14
+ - `middleware` - Register custom HTTP middleware
15
+ - `route` - Register custom API routes
16
+
17
+ See [objectstack.config.ts](./objectstack.config.ts) for the complete capability manifest.
18
+
19
+ ## Features
20
+
21
+ - 🚀 **High Performance**: Built on Hono, one of the fastest web frameworks
22
+ - 🌐 **Universal**: Works in Node.js, Deno, Bun, and edge runtimes
23
+ - 🔒 **Type Safe**: Fully typed with TypeScript
24
+ - ðŸ“Ą **REST API**: Complete ObjectStack Runtime Protocol implementation
25
+ - ðŸŽŊ **Auto-Discovery**: Automatic endpoint registration
26
+ - 🔌 **Extensible**: Easy to add custom routes and middleware
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ pnpm add @objectstack/plugin-hono-server hono @hono/node-server
32
+ ```
33
+
34
+ ## Usage
35
+
36
+ ### Basic Setup
37
+
38
+ ```typescript
39
+ import { HonoServerPlugin } from '@objectstack/plugin-hono-server';
40
+ import { ObjectKernel } from '@objectstack/runtime';
41
+
42
+ const kernel = new ObjectKernel();
43
+
44
+ // Register the server plugin
45
+ kernel.use(new HonoServerPlugin({
46
+ port: 3000,
47
+ staticRoot: './public' // Optional: serve static files
48
+ }));
49
+
50
+ await kernel.bootstrap();
51
+
52
+ // Server starts automatically when kernel is ready
53
+ // API available at: http://localhost:3000/api/v1
54
+ ```
55
+
56
+ ### With Custom Port
57
+
58
+ ```typescript
59
+ const plugin = new HonoServerPlugin({
60
+ port: process.env.PORT || 8080
61
+ });
62
+
63
+ kernel.use(plugin);
64
+ ```
65
+
66
+ ### Configuration Options
67
+
68
+ ```typescript
69
+ interface HonoPluginOptions {
70
+ /**
71
+ * HTTP server port
72
+ * @default 3000
73
+ */
74
+ port?: number;
75
+
76
+ /**
77
+ * Path to static files directory (optional)
78
+ */
79
+ staticRoot?: string;
80
+ }
81
+ ```
82
+
83
+ ## API Endpoints
84
+
85
+ The plugin automatically exposes the following ObjectStack REST API endpoints:
86
+
87
+ ### Discovery
88
+
89
+ ```http
90
+ GET /api/v1
91
+ ```
92
+
93
+ Returns API discovery information including available endpoints and versions.
94
+
95
+ ### Metadata Protocol
96
+
97
+ ```http
98
+ GET /api/v1/meta
99
+ GET /api/v1/meta/:type
100
+ GET /api/v1/meta/:type/:name
101
+ ```
102
+
103
+ Retrieve metadata about objects, views, and other system definitions.
104
+
105
+ ### Data Protocol (CRUD Operations)
106
+
107
+ ```http
108
+ GET /api/v1/data/:object # Find records
109
+ GET /api/v1/data/:object/:id # Get record by ID
110
+ POST /api/v1/data/:object # Create record
111
+ PATCH /api/v1/data/:object/:id # Update record
112
+ DELETE /api/v1/data/:object/:id # Delete record
113
+ ```
114
+
115
+ Example requests:
116
+
117
+ ```bash
118
+ # Get all users
119
+ curl http://localhost:3000/api/v1/data/user
120
+
121
+ # Get user by ID
122
+ curl http://localhost:3000/api/v1/data/user/123
123
+
124
+ # Create a user
125
+ curl -X POST http://localhost:3000/api/v1/data/user \
126
+ -H "Content-Type: application/json" \
127
+ -d '{"name":"John Doe","email":"john@example.com"}'
128
+
129
+ # Update a user
130
+ curl -X PATCH http://localhost:3000/api/v1/data/user/123 \
131
+ -H "Content-Type: application/json" \
132
+ -d '{"name":"Jane Doe"}'
133
+
134
+ # Delete a user
135
+ curl -X DELETE http://localhost:3000/api/v1/data/user/123
136
+ ```
137
+
138
+ ### UI Protocol
139
+
140
+ ```http
141
+ GET /api/v1/ui/view/:object?type=list|form
142
+ ```
143
+
144
+ Retrieve UI view configurations for objects.
145
+
146
+ ## Advanced Usage
147
+
148
+ ### Accessing the HTTP Server Instance
149
+
150
+ The server instance is registered as a service and can be accessed by other plugins:
151
+
152
+ ```typescript
153
+ export class MyPlugin implements Plugin {
154
+ name = 'my-custom-plugin';
155
+
156
+ async start(ctx: PluginContext) {
157
+ const httpServer = ctx.getService<IHttpServer>('http-server');
158
+
159
+ // Add custom routes
160
+ httpServer.get('/api/custom', (req, res) => {
161
+ res.json({ message: 'Custom endpoint' });
162
+ });
163
+ }
164
+ }
165
+ ```
166
+
167
+ ### Extending with Middleware
168
+
169
+ The plugin provides extension points for adding custom middleware:
170
+
171
+ ```typescript
172
+ // In another plugin's manifest
173
+ capabilities: {
174
+ extensions: [
175
+ {
176
+ targetPluginId: 'com.objectstack.server.hono',
177
+ extensionPointId: 'com.objectstack.server.hono.extension.middleware',
178
+ implementation: './middleware/auth.ts',
179
+ priority: 10
180
+ }
181
+ ]
182
+ }
183
+ ```
184
+
185
+ ### Custom Route Registration
186
+
187
+ ```typescript
188
+ // In another plugin's manifest
189
+ capabilities: {
190
+ extensions: [
191
+ {
192
+ targetPluginId: 'com.objectstack.server.hono',
193
+ extensionPointId: 'com.objectstack.server.hono.extension.route',
194
+ implementation: './routes/webhooks.ts',
195
+ priority: 50
196
+ }
197
+ ]
198
+ }
199
+ ```
200
+
201
+ ## Architecture
202
+
203
+ The Hono Server Plugin follows a clean architecture:
204
+
205
+ ```
206
+ ┌─────────────────────────────────┐
207
+ │ HonoServerPlugin │
208
+ │ (Plugin Lifecycle) │
209
+ └────────────┮────────────────────┘
210
+ │
211
+ ├─ init() → Register HTTP server service
212
+ ├─ start() → Bind routes, start server
213
+ └─ destroy() → Stop server
214
+ │
215
+ ▾
216
+ ┌─────────────────────┐
217
+ │ HonoHttpServer │
218
+ │ (Adapter) │
219
+ └──────┮──────────────┘
220
+ │
221
+ ▾
222
+ ┌─────────────────────┐
223
+ │ Hono Framework │
224
+ │ (Core Library) │
225
+ └─────────────────────┘
226
+ ```
227
+
228
+ ## Plugin Lifecycle
229
+
230
+ 1. **Init Phase**:
231
+ - Creates HonoHttpServer instance
232
+ - Registers as `http-server` service
233
+
234
+ 2. **Start Phase**:
235
+ - Retrieves protocol implementation service
236
+ - Registers all ObjectStack API routes
237
+ - Sets up lifecycle hooks
238
+
239
+ 3. **Ready Hook** (`kernel:ready`):
240
+ - Starts HTTP server on configured port
241
+ - Logs server URL
242
+
243
+ 4. **Destroy Phase**:
244
+ - Gracefully closes server
245
+ - Cleans up resources
246
+
247
+ ## Error Handling
248
+
249
+ The plugin includes comprehensive error handling:
250
+
251
+ ```typescript
252
+ // 404 Not Found
253
+ GET /api/v1/data/user/999
254
+ → { "error": "Record not found" }
255
+
256
+ // 400 Bad Request
257
+ POST /api/v1/data/user (invalid data)
258
+ → { "error": "Validation failed: email is required" }
259
+ ```
260
+
261
+ ## Production Deployment
262
+
263
+ ### Environment Variables
264
+
265
+ ```bash
266
+ PORT=8080
267
+ NODE_ENV=production
268
+ ```
269
+
270
+ ### Docker Example
271
+
272
+ ```dockerfile
273
+ FROM node:20-alpine
274
+ WORKDIR /app
275
+ COPY package.json pnpm-lock.yaml ./
276
+ RUN npm install -g pnpm && pnpm install --frozen-lockfile
277
+ COPY . .
278
+ RUN pnpm build
279
+ EXPOSE 8080
280
+ CMD ["node", "dist/index.js"]
281
+ ```
282
+
283
+ ### Serverless Deployment
284
+
285
+ Hono works seamlessly with serverless platforms:
286
+
287
+ ```typescript
288
+ // Cloudflare Workers, Vercel Edge, etc.
289
+ export default {
290
+ async fetch(request: Request) {
291
+ const app = createHonoApp();
292
+ return app.fetch(request);
293
+ }
294
+ }
295
+ ```
296
+
297
+ ## Performance
298
+
299
+ Hono is designed for performance:
300
+ - ⚡ One of the fastest web frameworks for Node.js
301
+ - ðŸŠķ Minimal overhead and memory footprint
302
+ - 🚀 Optimized routing with RegExpRouter
303
+ - ðŸ“Ķ Small bundle size (~12KB)
304
+
305
+ ## Comparison with Other Adapters
306
+
307
+ | Feature | Hono | Express | Fastify |
308
+ |---------|------|---------|---------|
309
+ | Universal Runtime | ✅ | ❌ | ❌ |
310
+ | Edge Support | ✅ | ❌ | ❌ |
311
+ | TypeScript | ✅ | Partial | ✅ |
312
+ | Performance | Excellent | Good | Excellent |
313
+ | Bundle Size | 12KB | 208KB | 28KB |
314
+
315
+ ## License
316
+
317
+ Apache-2.0
318
+
319
+ ## Related Packages
320
+
321
+ - [@objectstack/runtime](../../runtime) - ObjectStack Runtime
322
+ - [@objectstack/spec](../../spec) - ObjectStack Specifications
323
+ - [hono](https://hono.dev/) - Hono Web Framework
324
+ - [@hono/node-server](https://github.com/honojs/node-server) - Node.js adapter for Hono
package/dist/adapter.js CHANGED
@@ -36,21 +36,35 @@ class HonoHttpServer {
36
36
  // internal helper to convert standard handler to Hono handler
37
37
  wrap(handler) {
38
38
  return async (c) => {
39
+ let body = {};
40
+ // Try to parse JSON body first if content-type is JSON
41
+ if (c.req.header('content-type')?.includes('application/json')) {
42
+ try {
43
+ body = await c.req.json();
44
+ }
45
+ catch (e) {
46
+ // If JSON parsing fails, try parseBody
47
+ try {
48
+ body = await c.req.parseBody();
49
+ }
50
+ catch (e2) { }
51
+ }
52
+ }
53
+ else {
54
+ // For non-JSON content types, use parseBody
55
+ try {
56
+ body = await c.req.parseBody();
57
+ }
58
+ catch (e) { }
59
+ }
39
60
  const req = {
40
61
  params: c.req.param(),
41
62
  query: c.req.query(),
42
- body: await c.req.parseBody().catch(() => { }), // fallback
63
+ body,
43
64
  headers: c.req.header(),
44
65
  method: c.req.method,
45
66
  path: c.req.path
46
67
  };
47
- // Try to parse JSON body if possible
48
- if (c.req.header('content-type')?.includes('application/json')) {
49
- try {
50
- req.body = await c.req.json();
51
- }
52
- catch (e) { }
53
- }
54
68
  let capturedResponse;
55
69
  const res = {
56
70
  json: (data) => { capturedResponse = c.json(data); },