@smicolon/ai-kit 0.3.1 → 0.4.0
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/README.md +73 -40
- package/dist/index.js +260 -126
- package/package.json +5 -5
- package/.claude-plugin/marketplace.json +0 -373
- package/packs/architect/CHANGELOG.md +0 -17
- package/packs/architect/README.md +0 -58
- package/packs/architect/agents/system-architect.md +0 -768
- package/packs/architect/commands/diagram-create.md +0 -300
- package/packs/better-auth/.mcp.json +0 -14
- package/packs/better-auth/CHANGELOG.md +0 -26
- package/packs/better-auth/README.md +0 -125
- package/packs/better-auth/agents/auth-architect.md +0 -278
- package/packs/better-auth/commands/auth-provider-add.md +0 -265
- package/packs/better-auth/commands/auth-setup.md +0 -298
- package/packs/better-auth/skills/auth-security/SKILL.md +0 -425
- package/packs/better-auth/skills/better-auth-patterns/SKILL.md +0 -455
- package/packs/dev-loop/CHANGELOG.md +0 -69
- package/packs/dev-loop/README.md +0 -155
- package/packs/dev-loop/commands/cancel-dev.md +0 -21
- package/packs/dev-loop/commands/dev-loop.md +0 -72
- package/packs/dev-loop/commands/dev-plan.md +0 -351
- package/packs/dev-loop/hooks/hooks.json +0 -15
- package/packs/dev-loop/hooks/stop-hook.sh +0 -178
- package/packs/dev-loop/scripts/setup-dev-loop.sh +0 -194
- package/packs/dev-loop/skills/tdd-planner/SKILL.md +0 -249
- package/packs/dev-loop/skills/tdd-planner/references/framework-patterns.md +0 -874
- package/packs/dev-loop/skills/tdd-planner/references/good-example.md +0 -260
- package/packs/dev-loop/skills/tdd-planner/references/plan-template.md +0 -275
- package/packs/django/CHANGELOG.md +0 -39
- package/packs/django/README.md +0 -92
- package/packs/django/agents/django-architect.md +0 -182
- package/packs/django/agents/django-builder.md +0 -250
- package/packs/django/agents/django-feature-based.md +0 -420
- package/packs/django/agents/django-reviewer.md +0 -253
- package/packs/django/agents/django-tester.md +0 -230
- package/packs/django/commands/api-endpoint.md +0 -285
- package/packs/django/commands/model-create.md +0 -178
- package/packs/django/commands/test-generate.md +0 -325
- package/packs/django/rules/migrations.md +0 -138
- package/packs/django/rules/models.md +0 -167
- package/packs/django/rules/serializers.md +0 -126
- package/packs/django/rules/services.md +0 -131
- package/packs/django/rules/tests.md +0 -140
- package/packs/django/rules/views.md +0 -102
- package/packs/django/skills/import-convention-enforcer/SKILL.md +0 -226
- package/packs/django/skills/import-convention-enforcer/patterns/django-imports.md +0 -343
- package/packs/django/skills/migration-safety-checker/SKILL.md +0 -375
- package/packs/django/skills/model-entity-validator/SKILL.md +0 -298
- package/packs/django/skills/performance-optimizer/SKILL.md +0 -447
- package/packs/django/skills/red-phase-verifier/SKILL.md +0 -180
- package/packs/django/skills/security-first-validator/SKILL.md +0 -435
- package/packs/django/skills/test-coverage-advisor/SKILL.md +0 -394
- package/packs/django/skills/test-validity-checker/SKILL.md +0 -194
- package/packs/failure-log/CHANGELOG.md +0 -20
- package/packs/failure-log/README.md +0 -168
- package/packs/failure-log/commands/failure-add.md +0 -106
- package/packs/failure-log/commands/failure-list.md +0 -89
- package/packs/failure-log/hooks/hooks.json +0 -16
- package/packs/failure-log/hooks/scripts/inject-failures.sh +0 -64
- package/packs/failure-log/skills/failure-log-manager/SKILL.md +0 -164
- package/packs/flutter/CHANGELOG.md +0 -19
- package/packs/flutter/README.md +0 -170
- package/packs/flutter/agents/flutter-architect.md +0 -166
- package/packs/flutter/agents/flutter-builder.md +0 -303
- package/packs/flutter/agents/release-manager.md +0 -355
- package/packs/flutter/commands/fastlane-setup.md +0 -188
- package/packs/flutter/commands/flutter-build.md +0 -90
- package/packs/flutter/commands/flutter-deploy.md +0 -133
- package/packs/flutter/commands/flutter-test.md +0 -117
- package/packs/flutter/commands/signing-setup.md +0 -209
- package/packs/flutter/hooks/hooks.json +0 -17
- package/packs/flutter/skills/fastlane-knowledge/SKILL.md +0 -193
- package/packs/flutter/skills/flutter-architecture/SKILL.md +0 -127
- package/packs/flutter/skills/store-publishing/SKILL.md +0 -163
- package/packs/hono/CHANGELOG.md +0 -19
- package/packs/hono/README.md +0 -143
- package/packs/hono/agents/hono-architect.md +0 -240
- package/packs/hono/agents/hono-builder.md +0 -285
- package/packs/hono/agents/hono-reviewer.md +0 -279
- package/packs/hono/agents/hono-tester.md +0 -346
- package/packs/hono/commands/middleware-create.md +0 -223
- package/packs/hono/commands/project-init.md +0 -306
- package/packs/hono/commands/route-create.md +0 -153
- package/packs/hono/commands/rpc-client.md +0 -263
- package/packs/hono/hooks/hooks.json +0 -4
- package/packs/hono/skills/cloudflare-bindings/SKILL.md +0 -408
- package/packs/hono/skills/hono-patterns/SKILL.md +0 -309
- package/packs/hono/skills/rpc-typesafe/SKILL.md +0 -388
- package/packs/hono/skills/zod-validation/SKILL.md +0 -332
- package/packs/nestjs/CHANGELOG.md +0 -29
- package/packs/nestjs/README.md +0 -75
- package/packs/nestjs/agents/nestjs-architect.md +0 -402
- package/packs/nestjs/agents/nestjs-builder.md +0 -301
- package/packs/nestjs/agents/nestjs-tester.md +0 -437
- package/packs/nestjs/commands/module-create.md +0 -369
- package/packs/nestjs/rules/controllers.md +0 -92
- package/packs/nestjs/rules/dto.md +0 -124
- package/packs/nestjs/rules/entities.md +0 -102
- package/packs/nestjs/rules/services.md +0 -106
- package/packs/nestjs/skills/barrel-export-manager/SKILL.md +0 -389
- package/packs/nestjs/skills/import-convention-enforcer/SKILL.md +0 -365
- package/packs/nextjs/CHANGELOG.md +0 -36
- package/packs/nextjs/README.md +0 -76
- package/packs/nextjs/agents/frontend-tester.md +0 -680
- package/packs/nextjs/agents/frontend-visual.md +0 -820
- package/packs/nextjs/agents/nextjs-architect.md +0 -331
- package/packs/nextjs/agents/nextjs-modular.md +0 -433
- package/packs/nextjs/commands/component-create.md +0 -398
- package/packs/nextjs/rules/api-routes.md +0 -129
- package/packs/nextjs/rules/components.md +0 -106
- package/packs/nextjs/rules/hooks.md +0 -132
- package/packs/nextjs/skills/accessibility-validator/SKILL.md +0 -445
- package/packs/nextjs/skills/import-convention-enforcer/SKILL.md +0 -399
- package/packs/nextjs/skills/react-form-validator/SKILL.md +0 -569
- package/packs/nuxtjs/CHANGELOG.md +0 -30
- package/packs/nuxtjs/README.md +0 -56
- package/packs/nuxtjs/agents/frontend-tester.md +0 -680
- package/packs/nuxtjs/agents/frontend-visual.md +0 -820
- package/packs/nuxtjs/agents/nuxtjs-architect.md +0 -537
- package/packs/nuxtjs/commands/component-create.md +0 -223
- package/packs/nuxtjs/rules/components.md +0 -101
- package/packs/nuxtjs/rules/composables.md +0 -118
- package/packs/nuxtjs/rules/server-routes.md +0 -127
- package/packs/nuxtjs/skills/accessibility-validator/SKILL.md +0 -183
- package/packs/nuxtjs/skills/import-convention-enforcer/SKILL.md +0 -196
- package/packs/nuxtjs/skills/veevalidate-form-validator/SKILL.md +0 -190
- package/packs/onboard/CHANGELOG.md +0 -22
- package/packs/onboard/README.md +0 -103
- package/packs/onboard/agents/onboard-guide.md +0 -118
- package/packs/onboard/commands/onboard.md +0 -313
- package/packs/onboard/skills/onboard-context-provider/SKILL.md +0 -98
- package/packs/tanstack-router/CHANGELOG.md +0 -30
- package/packs/tanstack-router/README.md +0 -113
- package/packs/tanstack-router/agents/tanstack-architect.md +0 -173
- package/packs/tanstack-router/agents/tanstack-builder.md +0 -360
- package/packs/tanstack-router/agents/tanstack-tester.md +0 -454
- package/packs/tanstack-router/commands/form-create.md +0 -313
- package/packs/tanstack-router/commands/query-create.md +0 -263
- package/packs/tanstack-router/commands/route-create.md +0 -190
- package/packs/tanstack-router/commands/table-create.md +0 -413
- package/packs/tanstack-router/skills/ai-patterns/SKILL.md +0 -370
- package/packs/tanstack-router/skills/db-patterns/SKILL.md +0 -346
- package/packs/tanstack-router/skills/devtools-patterns/SKILL.md +0 -415
- package/packs/tanstack-router/skills/form-patterns/SKILL.md +0 -425
- package/packs/tanstack-router/skills/pacer-patterns/SKILL.md +0 -341
- package/packs/tanstack-router/skills/query-patterns/SKILL.md +0 -359
- package/packs/tanstack-router/skills/router-patterns/SKILL.md +0 -285
- package/packs/tanstack-router/skills/store-patterns/SKILL.md +0 -351
- package/packs/tanstack-router/skills/table-patterns/SKILL.md +0 -531
- package/packs/tanstack-router/skills/tanstack-conventions/SKILL.md +0 -428
- package/packs/tanstack-router/skills/virtual-patterns/SKILL.md +0 -490
- package/packs/worktree/CHANGELOG.md +0 -45
- package/packs/worktree/README.md +0 -219
- package/packs/worktree/commands/wt.md +0 -93
- package/packs/worktree/scripts/wt.sh +0 -957
- package/packs/worktree/skills/worktree-manager/SKILL.md +0 -113
|
@@ -1,306 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: project-init
|
|
3
|
-
description: Initialize a new Hono project with Bun or Cloudflare Workers
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Initialize Hono Project
|
|
7
|
-
|
|
8
|
-
Create a new Hono project with proper structure and configuration.
|
|
9
|
-
|
|
10
|
-
## Workflow
|
|
11
|
-
|
|
12
|
-
### Step 1: Choose Template
|
|
13
|
-
|
|
14
|
-
Ask the user which template to use:
|
|
15
|
-
|
|
16
|
-
1. **Bun + Cloudflare Workers** (Recommended)
|
|
17
|
-
- Development with Bun's hot reload
|
|
18
|
-
- Deployment to Cloudflare Workers
|
|
19
|
-
- D1 database, KV, R2 support
|
|
20
|
-
|
|
21
|
-
2. **Bun Standalone**
|
|
22
|
-
- Pure Bun runtime
|
|
23
|
-
- Local development and deployment
|
|
24
|
-
- Bun SQLite for database
|
|
25
|
-
|
|
26
|
-
3. **Cloudflare Workers Only**
|
|
27
|
-
- Wrangler for dev and deploy
|
|
28
|
-
- Full CF ecosystem
|
|
29
|
-
|
|
30
|
-
### Step 2: Create Project
|
|
31
|
-
|
|
32
|
-
#### Template: Bun + Cloudflare Workers
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
# Create project directory
|
|
36
|
-
mkdir {project-name} && cd {project-name}
|
|
37
|
-
|
|
38
|
-
# Initialize with Bun
|
|
39
|
-
bun init -y
|
|
40
|
-
|
|
41
|
-
# Install dependencies
|
|
42
|
-
bun add hono @hono/zod-validator zod
|
|
43
|
-
bun add -d @cloudflare/workers-types wrangler typescript
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
**package.json:**
|
|
47
|
-
```json
|
|
48
|
-
{
|
|
49
|
-
"name": "{project-name}",
|
|
50
|
-
"scripts": {
|
|
51
|
-
"dev": "bun run --hot src/index.ts",
|
|
52
|
-
"dev:cf": "wrangler dev src/index.ts",
|
|
53
|
-
"deploy": "wrangler deploy",
|
|
54
|
-
"test": "bun test",
|
|
55
|
-
"typecheck": "tsc --noEmit"
|
|
56
|
-
},
|
|
57
|
-
"dependencies": {
|
|
58
|
-
"hono": "^4.0.0",
|
|
59
|
-
"@hono/zod-validator": "^0.4.0",
|
|
60
|
-
"zod": "^3.23.0"
|
|
61
|
-
},
|
|
62
|
-
"devDependencies": {
|
|
63
|
-
"@cloudflare/workers-types": "^4.0.0",
|
|
64
|
-
"typescript": "^5.0.0",
|
|
65
|
-
"wrangler": "^3.0.0"
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
**tsconfig.json:**
|
|
71
|
-
```json
|
|
72
|
-
{
|
|
73
|
-
"compilerOptions": {
|
|
74
|
-
"target": "ESNext",
|
|
75
|
-
"module": "ESNext",
|
|
76
|
-
"moduleResolution": "bundler",
|
|
77
|
-
"strict": true,
|
|
78
|
-
"skipLibCheck": true,
|
|
79
|
-
"lib": ["ESNext"],
|
|
80
|
-
"types": ["@cloudflare/workers-types", "bun-types"],
|
|
81
|
-
"jsx": "react-jsx",
|
|
82
|
-
"jsxImportSource": "hono/jsx",
|
|
83
|
-
"baseUrl": ".",
|
|
84
|
-
"paths": {
|
|
85
|
-
"@/*": ["src/*"]
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
|
-
"include": ["src/**/*", "tests/**/*"],
|
|
89
|
-
"exclude": ["node_modules"]
|
|
90
|
-
}
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
**wrangler.toml:**
|
|
94
|
-
```toml
|
|
95
|
-
name = "{project-name}"
|
|
96
|
-
main = "src/index.ts"
|
|
97
|
-
compatibility_date = "2024-01-01"
|
|
98
|
-
|
|
99
|
-
[vars]
|
|
100
|
-
ENVIRONMENT = "production"
|
|
101
|
-
|
|
102
|
-
# Uncomment to enable D1
|
|
103
|
-
# [[d1_databases]]
|
|
104
|
-
# binding = "DB"
|
|
105
|
-
# database_name = "{project-name}-db"
|
|
106
|
-
# database_id = "your-database-id"
|
|
107
|
-
|
|
108
|
-
# Uncomment to enable KV
|
|
109
|
-
# [[kv_namespaces]]
|
|
110
|
-
# binding = "KV"
|
|
111
|
-
# id = "your-kv-id"
|
|
112
|
-
|
|
113
|
-
# Uncomment to enable R2
|
|
114
|
-
# [[r2_buckets]]
|
|
115
|
-
# binding = "BUCKET"
|
|
116
|
-
# bucket_name = "{project-name}-bucket"
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
### Step 3: Create Directory Structure
|
|
120
|
-
|
|
121
|
-
```
|
|
122
|
-
{project-name}/
|
|
123
|
-
├── src/
|
|
124
|
-
│ ├── routes/
|
|
125
|
-
│ │ └── index.ts
|
|
126
|
-
│ ├── middleware/
|
|
127
|
-
│ │ └── index.ts
|
|
128
|
-
│ ├── validators/
|
|
129
|
-
│ │ └── index.ts
|
|
130
|
-
│ ├── types/
|
|
131
|
-
│ │ └── bindings.ts
|
|
132
|
-
│ ├── lib/
|
|
133
|
-
│ │ └── errors.ts
|
|
134
|
-
│ └── index.ts
|
|
135
|
-
├── tests/
|
|
136
|
-
│ └── index.test.ts
|
|
137
|
-
├── .dev.vars
|
|
138
|
-
├── .gitignore
|
|
139
|
-
├── package.json
|
|
140
|
-
├── tsconfig.json
|
|
141
|
-
└── wrangler.toml
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
### Step 4: Create Core Files
|
|
145
|
-
|
|
146
|
-
**src/types/bindings.ts:**
|
|
147
|
-
```typescript
|
|
148
|
-
export type Env = {
|
|
149
|
-
Bindings: {
|
|
150
|
-
// Cloudflare bindings (uncomment as needed)
|
|
151
|
-
// DB: D1Database
|
|
152
|
-
// KV: KVNamespace
|
|
153
|
-
// BUCKET: R2Bucket
|
|
154
|
-
|
|
155
|
-
// Environment variables
|
|
156
|
-
ENVIRONMENT: string
|
|
157
|
-
// JWT_SECRET: string
|
|
158
|
-
}
|
|
159
|
-
Variables: {
|
|
160
|
-
// Request-scoped variables
|
|
161
|
-
requestId: string
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
**src/index.ts:**
|
|
167
|
-
```typescript
|
|
168
|
-
import { Hono } from 'hono'
|
|
169
|
-
import { cors } from 'hono/cors'
|
|
170
|
-
import { logger } from 'hono/logger'
|
|
171
|
-
import { secureHeaders } from 'hono/secure-headers'
|
|
172
|
-
import type { Env } from './types/bindings'
|
|
173
|
-
|
|
174
|
-
const app = new Hono<Env>()
|
|
175
|
-
|
|
176
|
-
// Global middleware
|
|
177
|
-
app.use('*', logger())
|
|
178
|
-
app.use('*', secureHeaders())
|
|
179
|
-
app.use('*', cors({
|
|
180
|
-
origin: ['http://localhost:3000'],
|
|
181
|
-
allowMethods: ['GET', 'POST', 'PUT', 'DELETE'],
|
|
182
|
-
allowHeaders: ['Content-Type', 'Authorization'],
|
|
183
|
-
}))
|
|
184
|
-
|
|
185
|
-
// Request ID middleware
|
|
186
|
-
app.use('*', async (c, next) => {
|
|
187
|
-
c.set('requestId', crypto.randomUUID())
|
|
188
|
-
await next()
|
|
189
|
-
})
|
|
190
|
-
|
|
191
|
-
// Health check
|
|
192
|
-
app.get('/health', (c) => {
|
|
193
|
-
return c.json({
|
|
194
|
-
status: 'ok',
|
|
195
|
-
timestamp: new Date().toISOString(),
|
|
196
|
-
requestId: c.get('requestId')
|
|
197
|
-
})
|
|
198
|
-
})
|
|
199
|
-
|
|
200
|
-
// 404 handler
|
|
201
|
-
app.notFound((c) => {
|
|
202
|
-
return c.json({ error: 'Not found' }, 404)
|
|
203
|
-
})
|
|
204
|
-
|
|
205
|
-
// Error handler
|
|
206
|
-
app.onError((err, c) => {
|
|
207
|
-
console.error(`Error: ${err.message}`)
|
|
208
|
-
return c.json({ error: 'Internal server error' }, 500)
|
|
209
|
-
})
|
|
210
|
-
|
|
211
|
-
export default app
|
|
212
|
-
|
|
213
|
-
// Export type for RPC client
|
|
214
|
-
export type AppType = typeof app
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
**src/lib/errors.ts:**
|
|
218
|
-
```typescript
|
|
219
|
-
import { HTTPException } from 'hono/http-exception'
|
|
220
|
-
|
|
221
|
-
export class NotFoundError extends HTTPException {
|
|
222
|
-
constructor(resource: string) {
|
|
223
|
-
super(404, { message: `${resource} not found` })
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
export class UnauthorizedError extends HTTPException {
|
|
228
|
-
constructor(message = 'Unauthorized') {
|
|
229
|
-
super(401, { message })
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
export class ValidationError extends HTTPException {
|
|
234
|
-
constructor(message: string) {
|
|
235
|
-
super(400, { message })
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
**tests/index.test.ts:**
|
|
241
|
-
```typescript
|
|
242
|
-
import { describe, it, expect } from 'bun:test'
|
|
243
|
-
import app from '../src/index'
|
|
244
|
-
|
|
245
|
-
describe('Health Check', () => {
|
|
246
|
-
it('returns ok status', async () => {
|
|
247
|
-
const res = await app.request('/health')
|
|
248
|
-
|
|
249
|
-
expect(res.status).toBe(200)
|
|
250
|
-
|
|
251
|
-
const data = await res.json()
|
|
252
|
-
expect(data.status).toBe('ok')
|
|
253
|
-
expect(data.requestId).toBeDefined()
|
|
254
|
-
})
|
|
255
|
-
})
|
|
256
|
-
|
|
257
|
-
describe('404 Handler', () => {
|
|
258
|
-
it('returns 404 for unknown routes', async () => {
|
|
259
|
-
const res = await app.request('/unknown-route')
|
|
260
|
-
|
|
261
|
-
expect(res.status).toBe(404)
|
|
262
|
-
})
|
|
263
|
-
})
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
**.dev.vars:**
|
|
267
|
-
```
|
|
268
|
-
# Local development secrets (not committed)
|
|
269
|
-
# JWT_SECRET=your-secret-here
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
**.gitignore:**
|
|
273
|
-
```
|
|
274
|
-
node_modules/
|
|
275
|
-
.wrangler/
|
|
276
|
-
.dev.vars
|
|
277
|
-
*.log
|
|
278
|
-
dist/
|
|
279
|
-
.DS_Store
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
### Step 5: Verify Setup
|
|
283
|
-
|
|
284
|
-
```bash
|
|
285
|
-
# Run tests
|
|
286
|
-
bun test
|
|
287
|
-
|
|
288
|
-
# Start development server
|
|
289
|
-
bun run dev
|
|
290
|
-
|
|
291
|
-
# Test health endpoint
|
|
292
|
-
curl http://localhost:3000/health
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
## Quality Checklist
|
|
296
|
-
|
|
297
|
-
- [ ] Dependencies installed
|
|
298
|
-
- [ ] TypeScript configured with strict mode
|
|
299
|
-
- [ ] Wrangler configured for deployment
|
|
300
|
-
- [ ] Basic middleware set up
|
|
301
|
-
- [ ] Error handling configured
|
|
302
|
-
- [ ] Health endpoint working
|
|
303
|
-
- [ ] Tests passing
|
|
304
|
-
- [ ] Git initialized with .gitignore
|
|
305
|
-
|
|
306
|
-
Now ask the user what project they want to create!
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: route-create
|
|
3
|
-
description: Create a new Hono route with handlers, validators, and types
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Create Hono Route
|
|
7
|
-
|
|
8
|
-
Create a new Hono route following project conventions.
|
|
9
|
-
|
|
10
|
-
## Workflow
|
|
11
|
-
|
|
12
|
-
### Step 1: Gather Requirements
|
|
13
|
-
|
|
14
|
-
Ask the user:
|
|
15
|
-
1. **Resource name** (e.g., "users", "posts", "orders")
|
|
16
|
-
2. **Operations needed** (GET list, GET single, POST, PUT, DELETE)
|
|
17
|
-
3. **Fields/schema** for the resource
|
|
18
|
-
4. **Relationships** to other resources
|
|
19
|
-
5. **Authentication** requirements
|
|
20
|
-
|
|
21
|
-
### Step 2: Create Zod Schema
|
|
22
|
-
|
|
23
|
-
Create validator file first:
|
|
24
|
-
|
|
25
|
-
```typescript
|
|
26
|
-
// validators/{resource}.schema.ts
|
|
27
|
-
import { z } from 'zod'
|
|
28
|
-
|
|
29
|
-
export const create{Resource}Schema = z.object({
|
|
30
|
-
// Fields based on user requirements
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
export const update{Resource}Schema = create{Resource}Schema.partial()
|
|
34
|
-
|
|
35
|
-
export const {resource}ParamsSchema = z.object({
|
|
36
|
-
id: z.string().uuid(),
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
export const {resource}QuerySchema = z.object({
|
|
40
|
-
page: z.coerce.number().int().positive().default(1),
|
|
41
|
-
limit: z.coerce.number().int().min(1).max(100).default(20),
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
// Export types
|
|
45
|
-
export type Create{Resource} = z.infer<typeof create{Resource}Schema>
|
|
46
|
-
export type Update{Resource} = z.infer<typeof update{Resource}Schema>
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
### Step 3: Create Route File
|
|
50
|
-
|
|
51
|
-
```typescript
|
|
52
|
-
// routes/{resource}.ts
|
|
53
|
-
import { Hono } from 'hono'
|
|
54
|
-
import { zValidator } from '@hono/zod-validator'
|
|
55
|
-
import type { Env } from '../types/bindings'
|
|
56
|
-
import {
|
|
57
|
-
create{Resource}Schema,
|
|
58
|
-
update{Resource}Schema,
|
|
59
|
-
{resource}ParamsSchema,
|
|
60
|
-
{resource}QuerySchema
|
|
61
|
-
} from '../validators/{resource}.schema'
|
|
62
|
-
|
|
63
|
-
const {resource} = new Hono<Env>()
|
|
64
|
-
|
|
65
|
-
// GET /{resource} - List
|
|
66
|
-
{resource}.get('/',
|
|
67
|
-
zValidator('query', {resource}QuerySchema),
|
|
68
|
-
async (c) => {
|
|
69
|
-
const { page, limit } = c.req.valid('query')
|
|
70
|
-
// Implementation
|
|
71
|
-
return c.json({ data: [], meta: { page, limit } })
|
|
72
|
-
}
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
// GET /{resource}/:id - Get single
|
|
76
|
-
{resource}.get('/:id',
|
|
77
|
-
zValidator('param', {resource}ParamsSchema),
|
|
78
|
-
async (c) => {
|
|
79
|
-
const { id } = c.req.valid('param')
|
|
80
|
-
// Implementation
|
|
81
|
-
return c.json({ id })
|
|
82
|
-
}
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
// POST /{resource} - Create
|
|
86
|
-
{resource}.post('/',
|
|
87
|
-
zValidator('json', create{Resource}Schema),
|
|
88
|
-
async (c) => {
|
|
89
|
-
const data = c.req.valid('json')
|
|
90
|
-
// Implementation
|
|
91
|
-
return c.json({ id: crypto.randomUUID(), ...data }, 201)
|
|
92
|
-
}
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
// PUT /{resource}/:id - Update
|
|
96
|
-
{resource}.put('/:id',
|
|
97
|
-
zValidator('param', {resource}ParamsSchema),
|
|
98
|
-
zValidator('json', update{Resource}Schema),
|
|
99
|
-
async (c) => {
|
|
100
|
-
const { id } = c.req.valid('param')
|
|
101
|
-
const data = c.req.valid('json')
|
|
102
|
-
// Implementation
|
|
103
|
-
return c.json({ id, ...data })
|
|
104
|
-
}
|
|
105
|
-
)
|
|
106
|
-
|
|
107
|
-
// DELETE /{resource}/:id - Delete
|
|
108
|
-
{resource}.delete('/:id',
|
|
109
|
-
zValidator('param', {resource}ParamsSchema),
|
|
110
|
-
async (c) => {
|
|
111
|
-
const { id } = c.req.valid('param')
|
|
112
|
-
// Implementation
|
|
113
|
-
return c.body(null, 204)
|
|
114
|
-
}
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
export { {resource} }
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
### Step 4: Mount Route
|
|
121
|
-
|
|
122
|
-
Update `src/index.ts`:
|
|
123
|
-
|
|
124
|
-
```typescript
|
|
125
|
-
import { {resource} } from './routes/{resource}'
|
|
126
|
-
|
|
127
|
-
// Mount route
|
|
128
|
-
app.route('/api/{resource}', {resource})
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
### Step 5: Update Types (if using RPC)
|
|
132
|
-
|
|
133
|
-
```typescript
|
|
134
|
-
// Ensure AppType is exported for RPC client
|
|
135
|
-
export type AppType = typeof app
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
## Generated Files
|
|
139
|
-
|
|
140
|
-
1. `validators/{resource}.schema.ts` - Zod schemas
|
|
141
|
-
2. `routes/{resource}.ts` - Route handlers
|
|
142
|
-
3. Updated `src/index.ts` - Route mounting
|
|
143
|
-
|
|
144
|
-
## Quality Checklist
|
|
145
|
-
|
|
146
|
-
- [ ] All handlers have Zod validation
|
|
147
|
-
- [ ] Proper HTTP status codes (200, 201, 204, 400, 404)
|
|
148
|
-
- [ ] Types exported for RPC
|
|
149
|
-
- [ ] Consistent response format
|
|
150
|
-
- [ ] Error handling included
|
|
151
|
-
- [ ] Route mounted in main app
|
|
152
|
-
|
|
153
|
-
Now ask the user what route they want to create!
|
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: rpc-client
|
|
3
|
-
description: Generate type-safe RPC client from Hono server routes
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Generate Hono RPC Client
|
|
7
|
-
|
|
8
|
-
Create a type-safe client for your Hono API using the `hc` client.
|
|
9
|
-
|
|
10
|
-
## Workflow
|
|
11
|
-
|
|
12
|
-
### Step 1: Verify Server Setup
|
|
13
|
-
|
|
14
|
-
Check that the server exports the app type:
|
|
15
|
-
|
|
16
|
-
```typescript
|
|
17
|
-
// src/index.ts
|
|
18
|
-
import { Hono } from 'hono'
|
|
19
|
-
|
|
20
|
-
const app = new Hono()
|
|
21
|
-
|
|
22
|
-
// ... routes ...
|
|
23
|
-
|
|
24
|
-
export default app
|
|
25
|
-
|
|
26
|
-
// REQUIRED: Export type for RPC client
|
|
27
|
-
export type AppType = typeof app
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
### Step 2: Create Client Package
|
|
31
|
-
|
|
32
|
-
For monorepo or separate client package:
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
# If using monorepo with workspaces
|
|
36
|
-
mkdir -p packages/api-client
|
|
37
|
-
cd packages/api-client
|
|
38
|
-
bun init -y
|
|
39
|
-
bun add hono
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
**packages/api-client/package.json:**
|
|
43
|
-
```json
|
|
44
|
-
{
|
|
45
|
-
"name": "@{project}/api-client",
|
|
46
|
-
"version": "1.0.0",
|
|
47
|
-
"main": "src/index.ts",
|
|
48
|
-
"types": "src/index.ts",
|
|
49
|
-
"exports": {
|
|
50
|
-
".": "./src/index.ts"
|
|
51
|
-
},
|
|
52
|
-
"dependencies": {
|
|
53
|
-
"hono": "^4.0.0"
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### Step 3: Create Client
|
|
59
|
-
|
|
60
|
-
**packages/api-client/src/index.ts:**
|
|
61
|
-
```typescript
|
|
62
|
-
import { hc } from 'hono/client'
|
|
63
|
-
import type { AppType } from '@{project}/api/src/index'
|
|
64
|
-
|
|
65
|
-
// Create typed client
|
|
66
|
-
export const createApiClient = (baseUrl: string) => {
|
|
67
|
-
return hc<AppType>(baseUrl)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Default client for common use
|
|
71
|
-
export const api = createApiClient(
|
|
72
|
-
process.env.API_URL || 'http://localhost:8787'
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
// Re-export types for consumers
|
|
76
|
-
export type { AppType }
|
|
77
|
-
|
|
78
|
-
// Export inferred types for convenience
|
|
79
|
-
export type ApiClient = ReturnType<typeof createApiClient>
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### Step 4: Usage Examples
|
|
83
|
-
|
|
84
|
-
**Basic Usage:**
|
|
85
|
-
```typescript
|
|
86
|
-
import { api } from '@{project}/api-client'
|
|
87
|
-
|
|
88
|
-
// GET request
|
|
89
|
-
const users = await api.api.users.$get()
|
|
90
|
-
const data = await users.json()
|
|
91
|
-
|
|
92
|
-
// POST request with body
|
|
93
|
-
const newUser = await api.api.users.$post({
|
|
94
|
-
json: {
|
|
95
|
-
email: 'user@example.com',
|
|
96
|
-
name: 'New User'
|
|
97
|
-
}
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
// GET with query params
|
|
101
|
-
const searchResults = await api.api.users.$get({
|
|
102
|
-
query: {
|
|
103
|
-
page: 1,
|
|
104
|
-
limit: 10,
|
|
105
|
-
search: 'john'
|
|
106
|
-
}
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
// GET with path params
|
|
110
|
-
const user = await api.api.users[':id'].$get({
|
|
111
|
-
param: { id: 'user-uuid' }
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
// PUT with params and body
|
|
115
|
-
const updated = await api.api.users[':id'].$put({
|
|
116
|
-
param: { id: 'user-uuid' },
|
|
117
|
-
json: { name: 'Updated Name' }
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
// DELETE
|
|
121
|
-
await api.api.users[':id'].$delete({
|
|
122
|
-
param: { id: 'user-uuid' }
|
|
123
|
-
})
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
**With Error Handling:**
|
|
127
|
-
```typescript
|
|
128
|
-
import { api } from '@{project}/api-client'
|
|
129
|
-
|
|
130
|
-
async function getUser(id: string) {
|
|
131
|
-
const res = await api.api.users[':id'].$get({
|
|
132
|
-
param: { id }
|
|
133
|
-
})
|
|
134
|
-
|
|
135
|
-
if (!res.ok) {
|
|
136
|
-
if (res.status === 404) {
|
|
137
|
-
throw new Error('User not found')
|
|
138
|
-
}
|
|
139
|
-
throw new Error(`API error: ${res.status}`)
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
return res.json()
|
|
143
|
-
}
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
**With Headers:**
|
|
147
|
-
```typescript
|
|
148
|
-
import { hc } from 'hono/client'
|
|
149
|
-
import type { AppType } from '@{project}/api/src/index'
|
|
150
|
-
|
|
151
|
-
const api = hc<AppType>('http://localhost:8787', {
|
|
152
|
-
headers: {
|
|
153
|
-
Authorization: `Bearer ${token}`
|
|
154
|
-
}
|
|
155
|
-
})
|
|
156
|
-
|
|
157
|
-
// Or per-request headers
|
|
158
|
-
const res = await api.api.users.$get({
|
|
159
|
-
headers: {
|
|
160
|
-
'X-Custom-Header': 'value'
|
|
161
|
-
}
|
|
162
|
-
})
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
**React Query Integration:**
|
|
166
|
-
```typescript
|
|
167
|
-
import { useQuery, useMutation } from '@tanstack/react-query'
|
|
168
|
-
import { api } from '@{project}/api-client'
|
|
169
|
-
|
|
170
|
-
// Query hook
|
|
171
|
-
export function useUsers(page = 1) {
|
|
172
|
-
return useQuery({
|
|
173
|
-
queryKey: ['users', page],
|
|
174
|
-
queryFn: async () => {
|
|
175
|
-
const res = await api.api.users.$get({
|
|
176
|
-
query: { page, limit: 20 }
|
|
177
|
-
})
|
|
178
|
-
if (!res.ok) throw new Error('Failed to fetch users')
|
|
179
|
-
return res.json()
|
|
180
|
-
}
|
|
181
|
-
})
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Mutation hook
|
|
185
|
-
export function useCreateUser() {
|
|
186
|
-
return useMutation({
|
|
187
|
-
mutationFn: async (data: { email: string; name: string }) => {
|
|
188
|
-
const res = await api.api.users.$post({ json: data })
|
|
189
|
-
if (!res.ok) throw new Error('Failed to create user')
|
|
190
|
-
return res.json()
|
|
191
|
-
}
|
|
192
|
-
})
|
|
193
|
-
}
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
### Step 5: TypeScript Configuration
|
|
197
|
-
|
|
198
|
-
Ensure both server and client have matching TypeScript settings:
|
|
199
|
-
|
|
200
|
-
**tsconfig.json (both projects):**
|
|
201
|
-
```json
|
|
202
|
-
{
|
|
203
|
-
"compilerOptions": {
|
|
204
|
-
"strict": true,
|
|
205
|
-
"moduleResolution": "bundler"
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
## Type Inference
|
|
211
|
-
|
|
212
|
-
The client automatically infers:
|
|
213
|
-
- Request body types from Zod validators
|
|
214
|
-
- Response types from handler return values
|
|
215
|
-
- Query parameter types
|
|
216
|
-
- Path parameter types
|
|
217
|
-
|
|
218
|
-
```typescript
|
|
219
|
-
// Server: defines the contract
|
|
220
|
-
app.post('/users',
|
|
221
|
-
zValidator('json', z.object({
|
|
222
|
-
email: z.string().email(),
|
|
223
|
-
name: z.string()
|
|
224
|
-
})),
|
|
225
|
-
async (c) => {
|
|
226
|
-
const data = c.req.valid('json')
|
|
227
|
-
return c.json({ id: '123', ...data }, 201)
|
|
228
|
-
}
|
|
229
|
-
)
|
|
230
|
-
|
|
231
|
-
// Client: types are inferred!
|
|
232
|
-
const res = await api.api.users.$post({
|
|
233
|
-
json: {
|
|
234
|
-
email: 'user@example.com', // typed as string
|
|
235
|
-
name: 'User' // typed as string
|
|
236
|
-
}
|
|
237
|
-
})
|
|
238
|
-
const user = await res.json()
|
|
239
|
-
// user is typed as { id: string; email: string; name: string }
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
## URL Generation
|
|
243
|
-
|
|
244
|
-
```typescript
|
|
245
|
-
import { api } from '@{project}/api-client'
|
|
246
|
-
|
|
247
|
-
// Generate URL without making request
|
|
248
|
-
const url = api.api.users[':id'].$url({
|
|
249
|
-
param: { id: 'user-123' }
|
|
250
|
-
})
|
|
251
|
-
// url = 'http://localhost:8787/api/users/user-123'
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
## Quality Checklist
|
|
255
|
-
|
|
256
|
-
- [ ] Server exports `AppType`
|
|
257
|
-
- [ ] `strict: true` in both tsconfigs
|
|
258
|
-
- [ ] Client properly typed
|
|
259
|
-
- [ ] Error handling implemented
|
|
260
|
-
- [ ] Headers configured (auth, etc.)
|
|
261
|
-
- [ ] Works with React Query (if using)
|
|
262
|
-
|
|
263
|
-
Now set up the RPC client for your project!
|