Skip to content

Commit eb2758f

Browse files
Copilothotlong
andcommitted
Add Hono server example demonstrating plugin usage
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent a3cbe94 commit eb2758f

7 files changed

Lines changed: 420 additions & 11 deletions

File tree

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# ObjectQL Hono Server Example
2+
3+
This example demonstrates how to integrate ObjectQL with the [Hono](https://hono.dev/) web framework.
4+
5+
## Features
6+
7+
- ⚡ Fast and lightweight Hono framework
8+
- 🔌 ObjectQL plugin-based architecture
9+
- 📡 JSON-RPC, REST, and Metadata APIs
10+
- 🌐 CORS support
11+
- 💾 SQLite in-memory database
12+
13+
## Quick Start
14+
15+
```bash
16+
# Install dependencies
17+
pnpm install
18+
19+
# Start the server
20+
pnpm dev
21+
```
22+
23+
The server will start on http://localhost:3005
24+
25+
## API Endpoints
26+
27+
### JSON-RPC
28+
```bash
29+
curl -X POST http://localhost:3005/api/objectql \
30+
-H "Content-Type: application/json" \
31+
-d '{"op": "find", "object": "User", "args": {}}'
32+
```
33+
34+
### REST API
35+
```bash
36+
# List all users
37+
curl http://localhost:3005/api/data/User
38+
39+
# Get a specific user
40+
curl http://localhost:3005/api/data/User/1
41+
42+
# Create a user
43+
curl -X POST http://localhost:3005/api/data/User \
44+
-H "Content-Type: application/json" \
45+
-d '{"name": "John", "email": "john@example.com", "age": 30, "status": "active"}'
46+
```
47+
48+
### Metadata API
49+
```bash
50+
# List all objects
51+
curl http://localhost:3005/api/metadata/object
52+
53+
# Get User object schema
54+
curl http://localhost:3005/api/metadata/object/User
55+
```
56+
57+
## Why Hono?
58+
59+
Hono is a modern, ultra-lightweight web framework that works on any JavaScript runtime (Node.js, Cloudflare Workers, Deno, Bun). It's perfect for:
60+
61+
- Edge computing deployments
62+
- Serverless functions
63+
- High-performance APIs
64+
- TypeScript-first development
65+
66+
## Architecture
67+
68+
This example uses the `@objectql/plugin-server` package which provides a clean adapter for Hono:
69+
70+
```typescript
71+
import { createHonoAdapter } from '@objectql/plugin-server';
72+
73+
const server = new Hono();
74+
const objectqlHandler = createHonoAdapter(app);
75+
server.all('/api/*', objectqlHandler);
76+
```
77+
78+
## Learn More
79+
80+
- [Hono Documentation](https://hono.dev/)
81+
- [ObjectQL Documentation](https://objectql.org)
82+
- [@objectql/plugin-server](../../packages/plugins/server)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"name": "@objectql/example-hono-server",
3+
"version": "3.0.1",
4+
"description": "Hono Server Integration Example for ObjectQL",
5+
"private": true,
6+
"keywords": [
7+
"objectql",
8+
"module",
9+
"hono",
10+
"api",
11+
"rest",
12+
"server",
13+
"interface"
14+
],
15+
"license": "MIT",
16+
"author": "ObjectQL Contributors",
17+
"repository": {
18+
"type": "git",
19+
"url": "https://github.com/objectql/objectql.git",
20+
"directory": "examples/integrations/hono-server"
21+
},
22+
"scripts": {
23+
"build": "tsc && cp src/*.yml dist/ || true",
24+
"start": "node dist/index.js",
25+
"dev": "tsx src/index.ts"
26+
},
27+
"dependencies": {
28+
"@objectql/core": "workspace:*",
29+
"@objectql/plugin-server": "workspace:*",
30+
"@objectql/types": "workspace:*",
31+
"@objectql/driver-sql": "workspace:*",
32+
"@objectql/platform-node": "workspace:*",
33+
"hono": "^4.11.0",
34+
"@hono/node-server": "^1.19.0",
35+
"sqlite3": "^5.1.7"
36+
},
37+
"devDependencies": {
38+
"@types/node": "^20.10.0",
39+
"typescript": "^5.0.0",
40+
"tsx": "^4.7.0"
41+
}
42+
}
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
/**
2+
* ObjectQL
3+
* Copyright (c) 2026-present ObjectStack Inc.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
import { Hono } from 'hono';
10+
import { serve } from '@hono/node-server';
11+
import { ObjectQL } from '@objectql/core';
12+
import { SqlDriver } from '@objectql/driver-sql';
13+
import { ObjectLoader } from '@objectql/platform-node';
14+
import { createHonoAdapter } from '@objectql/plugin-server';
15+
import * as path from 'path';
16+
17+
async function main() {
18+
// 1. Init ObjectQL
19+
const app = new ObjectQL({
20+
datasources: {
21+
default: new SqlDriver({
22+
client: 'sqlite3',
23+
connection: {
24+
filename: ':memory:'
25+
},
26+
useNullAsDefault: true
27+
})
28+
}
29+
});
30+
31+
// 2. Load Schema
32+
const rootDir = path.resolve(__dirname, '..');
33+
const loader = new ObjectLoader(app.metadata);
34+
loader.load(rootDir);
35+
36+
// 3. Init
37+
await app.init();
38+
39+
// 4. Create Hono server with ObjectQL adapter
40+
const server = new Hono();
41+
const port = 3005;
42+
43+
// Add CORS middleware
44+
server.use('*', async (c, next) => {
45+
c.header('Access-Control-Allow-Origin', '*');
46+
c.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
47+
c.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
48+
49+
if (c.req.method === 'OPTIONS') {
50+
return c.text('', 200);
51+
}
52+
53+
await next();
54+
});
55+
56+
// Mount ObjectQL handler
57+
const objectqlHandler = createHonoAdapter(app);
58+
server.all('/api/*', objectqlHandler);
59+
60+
// Welcome page
61+
server.get('/', (c) => {
62+
return c.html(`
63+
<!DOCTYPE html>
64+
<html>
65+
<head>
66+
<title>ObjectQL Hono Server</title>
67+
<style>
68+
body {
69+
font-family: system-ui, -apple-system, sans-serif;
70+
max-width: 800px;
71+
margin: 50px auto;
72+
padding: 20px;
73+
line-height: 1.6;
74+
}
75+
h1 { color: #333; }
76+
.endpoint {
77+
background: #f5f5f5;
78+
padding: 10px;
79+
margin: 10px 0;
80+
border-left: 3px solid #007acc;
81+
}
82+
code {
83+
background: #e8e8e8;
84+
padding: 2px 6px;
85+
border-radius: 3px;
86+
}
87+
</style>
88+
</head>
89+
<body>
90+
<h1>🚀 ObjectQL Hono Server</h1>
91+
<p>Welcome to the ObjectQL Hono integration example!</p>
92+
93+
<h2>Available APIs</h2>
94+
<div class="endpoint">
95+
<strong>JSON-RPC:</strong> <code>POST /api/objectql</code><br>
96+
Example: <code>{"op": "find", "object": "User", "args": {}}</code>
97+
</div>
98+
<div class="endpoint">
99+
<strong>REST:</strong> <code>GET /api/data/:object</code><br>
100+
Example: <code>GET /api/data/User</code>
101+
</div>
102+
<div class="endpoint">
103+
<strong>Metadata:</strong> <code>GET /api/metadata/object</code><br>
104+
Get schema information
105+
</div>
106+
107+
<h2>Test Commands</h2>
108+
<pre><code>curl -X POST http://localhost:${port}/api/objectql \\
109+
-H "Content-Type: application/json" \\
110+
-d '{"op": "find", "object": "User", "args": {}}'
111+
112+
curl http://localhost:${port}/api/data/User
113+
114+
curl http://localhost:${port}/api/metadata/object</code></pre>
115+
</body>
116+
</html>
117+
`);
118+
});
119+
120+
// Create some sample data
121+
const ctx = app.createContext({ isSystem: true });
122+
await ctx.object('User').create({
123+
name: 'Alice',
124+
email: 'alice@example.com',
125+
age: 28,
126+
status: 'active'
127+
});
128+
await ctx.object('User').create({
129+
name: 'Bob',
130+
email: 'bob@example.com',
131+
age: 35,
132+
status: 'active'
133+
});
134+
await ctx.object('User').create({
135+
name: 'Charlie',
136+
email: 'charlie@example.com',
137+
age: 42,
138+
status: 'inactive'
139+
});
140+
141+
await ctx.object('Task').create({
142+
title: 'Complete project',
143+
description: 'Finish the ObjectQL console',
144+
status: 'in-progress',
145+
priority: 'high'
146+
});
147+
await ctx.object('Task').create({
148+
title: 'Write documentation',
149+
description: 'Document the new console feature',
150+
status: 'pending',
151+
priority: 'medium'
152+
});
153+
await ctx.object('Task').create({
154+
title: 'Code review',
155+
description: 'Review pull requests',
156+
status: 'pending',
157+
priority: 'low'
158+
});
159+
160+
// Start Hono server
161+
console.log(`\n🚀 ObjectQL Hono Server running on http://localhost:${port}`);
162+
console.log(`\n🔌 APIs:`);
163+
console.log(` - JSON-RPC: http://localhost:${port}/api/objectql`);
164+
console.log(` - REST: http://localhost:${port}/api/data`);
165+
console.log(` - Metadata: http://localhost:${port}/api/metadata`);
166+
console.log(` - Web UI: http://localhost:${port}/`);
167+
168+
serve({
169+
fetch: server.fetch,
170+
port
171+
});
172+
}
173+
174+
main().catch(console.error);
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
label: Tasks
2+
fields:
3+
title:
4+
type: string
5+
label: Title
6+
required: true
7+
description:
8+
type: text
9+
label: Description
10+
status:
11+
type: string
12+
label: Status
13+
defaultValue: pending
14+
priority:
15+
type: string
16+
label: Priority
17+
defaultValue: medium
18+
due_date:
19+
type: date
20+
label: Due Date
21+
completed:
22+
type: boolean
23+
label: Completed
24+
defaultValue: false
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
label: Users
2+
fields:
3+
name:
4+
type: string
5+
label: Full Name
6+
required: true
7+
email:
8+
type: string
9+
label: Email Address
10+
required: true
11+
status:
12+
type: string
13+
label: Status
14+
defaultValue: active
15+
age:
16+
type: number
17+
label: Age
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"extends": "../../../tsconfig.base.json",
3+
"compilerOptions": {
4+
"outDir": "./dist",
5+
"rootDir": "./src"
6+
},
7+
"include": ["src/**/*"],
8+
"exclude": ["node_modules", "dist"]
9+
}

0 commit comments

Comments
 (0)