@smicolon/ai-kit 0.1.0 → 0.1.1

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.
Files changed (162) hide show
  1. package/.claude-plugin/CLAUDE.md +7 -0
  2. package/.claude-plugin/marketplace.json +373 -0
  3. package/package.json +4 -3
  4. package/packs/architect/CHANGELOG.md +17 -0
  5. package/packs/architect/README.md +58 -0
  6. package/packs/architect/agents/system-architect.md +768 -0
  7. package/packs/architect/commands/diagram-create.md +300 -0
  8. package/packs/better-auth/.claude-plugin/plugin.json +14 -0
  9. package/packs/better-auth/.mcp.json +14 -0
  10. package/packs/better-auth/CHANGELOG.md +26 -0
  11. package/packs/better-auth/README.md +125 -0
  12. package/packs/better-auth/agents/auth-architect.md +278 -0
  13. package/packs/better-auth/commands/auth-provider-add.md +265 -0
  14. package/packs/better-auth/commands/auth-setup.md +298 -0
  15. package/packs/better-auth/skills/auth-security/SKILL.md +425 -0
  16. package/packs/better-auth/skills/better-auth-patterns/SKILL.md +455 -0
  17. package/packs/dev-loop/.claude-plugin/plugin.json +10 -0
  18. package/packs/dev-loop/CHANGELOG.md +69 -0
  19. package/packs/dev-loop/README.md +155 -0
  20. package/packs/dev-loop/commands/cancel-dev.md +21 -0
  21. package/packs/dev-loop/commands/dev-loop.md +72 -0
  22. package/packs/dev-loop/commands/dev-plan.md +351 -0
  23. package/packs/dev-loop/hooks/hooks.json +15 -0
  24. package/packs/dev-loop/hooks/stop-hook.sh +178 -0
  25. package/packs/dev-loop/scripts/setup-dev-loop.sh +194 -0
  26. package/packs/dev-loop/skills/tdd-planner/SKILL.md +249 -0
  27. package/packs/dev-loop/skills/tdd-planner/references/framework-patterns.md +874 -0
  28. package/packs/dev-loop/skills/tdd-planner/references/good-example.md +260 -0
  29. package/packs/dev-loop/skills/tdd-planner/references/plan-template.md +275 -0
  30. package/packs/django/CHANGELOG.md +39 -0
  31. package/packs/django/README.md +92 -0
  32. package/packs/django/agents/django-architect.md +182 -0
  33. package/packs/django/agents/django-builder.md +250 -0
  34. package/packs/django/agents/django-feature-based.md +420 -0
  35. package/packs/django/agents/django-reviewer.md +253 -0
  36. package/packs/django/agents/django-tester.md +230 -0
  37. package/packs/django/commands/api-endpoint.md +285 -0
  38. package/packs/django/commands/model-create.md +178 -0
  39. package/packs/django/commands/test-generate.md +325 -0
  40. package/packs/django/rules/migrations.md +138 -0
  41. package/packs/django/rules/models.md +167 -0
  42. package/packs/django/rules/serializers.md +126 -0
  43. package/packs/django/rules/services.md +131 -0
  44. package/packs/django/rules/tests.md +140 -0
  45. package/packs/django/rules/views.md +102 -0
  46. package/packs/django/skills/import-convention-enforcer/SKILL.md +226 -0
  47. package/packs/django/skills/import-convention-enforcer/patterns/django-imports.md +343 -0
  48. package/packs/django/skills/migration-safety-checker/SKILL.md +375 -0
  49. package/packs/django/skills/model-entity-validator/SKILL.md +298 -0
  50. package/packs/django/skills/performance-optimizer/SKILL.md +447 -0
  51. package/packs/django/skills/red-phase-verifier/SKILL.md +180 -0
  52. package/packs/django/skills/security-first-validator/SKILL.md +435 -0
  53. package/packs/django/skills/test-coverage-advisor/SKILL.md +394 -0
  54. package/packs/django/skills/test-validity-checker/SKILL.md +194 -0
  55. package/packs/failure-log/.claude-plugin/plugin.json +14 -0
  56. package/packs/failure-log/CHANGELOG.md +20 -0
  57. package/packs/failure-log/README.md +168 -0
  58. package/packs/failure-log/commands/failure-add.md +106 -0
  59. package/packs/failure-log/commands/failure-list.md +89 -0
  60. package/packs/failure-log/hooks/hooks.json +16 -0
  61. package/packs/failure-log/hooks/scripts/inject-failures.sh +64 -0
  62. package/packs/failure-log/skills/failure-log-manager/SKILL.md +164 -0
  63. package/packs/flutter/.claude-plugin/plugin.json +10 -0
  64. package/packs/flutter/CHANGELOG.md +19 -0
  65. package/packs/flutter/README.md +170 -0
  66. package/packs/flutter/agents/flutter-architect.md +166 -0
  67. package/packs/flutter/agents/flutter-builder.md +303 -0
  68. package/packs/flutter/agents/release-manager.md +355 -0
  69. package/packs/flutter/commands/fastlane-setup.md +188 -0
  70. package/packs/flutter/commands/flutter-build.md +90 -0
  71. package/packs/flutter/commands/flutter-deploy.md +133 -0
  72. package/packs/flutter/commands/flutter-test.md +117 -0
  73. package/packs/flutter/commands/signing-setup.md +209 -0
  74. package/packs/flutter/hooks/hooks.json +17 -0
  75. package/packs/flutter/skills/fastlane-knowledge/SKILL.md +193 -0
  76. package/packs/flutter/skills/flutter-architecture/SKILL.md +127 -0
  77. package/packs/flutter/skills/store-publishing/SKILL.md +163 -0
  78. package/packs/hono/.claude-plugin/plugin.json +19 -0
  79. package/packs/hono/CHANGELOG.md +19 -0
  80. package/packs/hono/README.md +143 -0
  81. package/packs/hono/agents/hono-architect.md +240 -0
  82. package/packs/hono/agents/hono-builder.md +285 -0
  83. package/packs/hono/agents/hono-reviewer.md +279 -0
  84. package/packs/hono/agents/hono-tester.md +346 -0
  85. package/packs/hono/commands/middleware-create.md +223 -0
  86. package/packs/hono/commands/project-init.md +306 -0
  87. package/packs/hono/commands/route-create.md +153 -0
  88. package/packs/hono/commands/rpc-client.md +263 -0
  89. package/packs/hono/hooks/hooks.json +4 -0
  90. package/packs/hono/skills/cloudflare-bindings/SKILL.md +408 -0
  91. package/packs/hono/skills/hono-patterns/SKILL.md +309 -0
  92. package/packs/hono/skills/rpc-typesafe/SKILL.md +388 -0
  93. package/packs/hono/skills/zod-validation/SKILL.md +332 -0
  94. package/packs/nestjs/CHANGELOG.md +29 -0
  95. package/packs/nestjs/README.md +75 -0
  96. package/packs/nestjs/agents/nestjs-architect.md +402 -0
  97. package/packs/nestjs/agents/nestjs-builder.md +301 -0
  98. package/packs/nestjs/agents/nestjs-tester.md +437 -0
  99. package/packs/nestjs/commands/module-create.md +369 -0
  100. package/packs/nestjs/rules/controllers.md +92 -0
  101. package/packs/nestjs/rules/dto.md +124 -0
  102. package/packs/nestjs/rules/entities.md +102 -0
  103. package/packs/nestjs/rules/services.md +106 -0
  104. package/packs/nestjs/skills/barrel-export-manager/SKILL.md +389 -0
  105. package/packs/nestjs/skills/import-convention-enforcer/SKILL.md +365 -0
  106. package/packs/nextjs/CHANGELOG.md +36 -0
  107. package/packs/nextjs/README.md +76 -0
  108. package/packs/nextjs/agents/frontend-tester.md +680 -0
  109. package/packs/nextjs/agents/frontend-visual.md +820 -0
  110. package/packs/nextjs/agents/nextjs-architect.md +331 -0
  111. package/packs/nextjs/agents/nextjs-modular.md +433 -0
  112. package/packs/nextjs/commands/component-create.md +398 -0
  113. package/packs/nextjs/rules/api-routes.md +129 -0
  114. package/packs/nextjs/rules/components.md +106 -0
  115. package/packs/nextjs/rules/hooks.md +132 -0
  116. package/packs/nextjs/skills/accessibility-validator/SKILL.md +445 -0
  117. package/packs/nextjs/skills/import-convention-enforcer/SKILL.md +399 -0
  118. package/packs/nextjs/skills/react-form-validator/SKILL.md +569 -0
  119. package/packs/nuxtjs/CHANGELOG.md +30 -0
  120. package/packs/nuxtjs/README.md +56 -0
  121. package/packs/nuxtjs/agents/frontend-tester.md +680 -0
  122. package/packs/nuxtjs/agents/frontend-visual.md +820 -0
  123. package/packs/nuxtjs/agents/nuxtjs-architect.md +537 -0
  124. package/packs/nuxtjs/commands/component-create.md +223 -0
  125. package/packs/nuxtjs/rules/components.md +101 -0
  126. package/packs/nuxtjs/rules/composables.md +118 -0
  127. package/packs/nuxtjs/rules/server-routes.md +127 -0
  128. package/packs/nuxtjs/skills/accessibility-validator/SKILL.md +183 -0
  129. package/packs/nuxtjs/skills/import-convention-enforcer/SKILL.md +196 -0
  130. package/packs/nuxtjs/skills/veevalidate-form-validator/SKILL.md +190 -0
  131. package/packs/onboard/CHANGELOG.md +22 -0
  132. package/packs/onboard/README.md +103 -0
  133. package/packs/onboard/agents/onboard-guide.md +118 -0
  134. package/packs/onboard/commands/onboard.md +313 -0
  135. package/packs/onboard/skills/onboard-context-provider/SKILL.md +98 -0
  136. package/packs/tanstack-router/.claude-plugin/plugin.json +14 -0
  137. package/packs/tanstack-router/CHANGELOG.md +30 -0
  138. package/packs/tanstack-router/README.md +113 -0
  139. package/packs/tanstack-router/agents/tanstack-architect.md +173 -0
  140. package/packs/tanstack-router/agents/tanstack-builder.md +360 -0
  141. package/packs/tanstack-router/agents/tanstack-tester.md +454 -0
  142. package/packs/tanstack-router/commands/form-create.md +313 -0
  143. package/packs/tanstack-router/commands/query-create.md +263 -0
  144. package/packs/tanstack-router/commands/route-create.md +190 -0
  145. package/packs/tanstack-router/commands/table-create.md +413 -0
  146. package/packs/tanstack-router/skills/ai-patterns/SKILL.md +370 -0
  147. package/packs/tanstack-router/skills/db-patterns/SKILL.md +346 -0
  148. package/packs/tanstack-router/skills/devtools-patterns/SKILL.md +415 -0
  149. package/packs/tanstack-router/skills/form-patterns/SKILL.md +425 -0
  150. package/packs/tanstack-router/skills/pacer-patterns/SKILL.md +341 -0
  151. package/packs/tanstack-router/skills/query-patterns/SKILL.md +359 -0
  152. package/packs/tanstack-router/skills/router-patterns/SKILL.md +285 -0
  153. package/packs/tanstack-router/skills/store-patterns/SKILL.md +351 -0
  154. package/packs/tanstack-router/skills/table-patterns/SKILL.md +531 -0
  155. package/packs/tanstack-router/skills/tanstack-conventions/SKILL.md +428 -0
  156. package/packs/tanstack-router/skills/virtual-patterns/SKILL.md +490 -0
  157. package/packs/worktree/.claude-plugin/plugin.json +19 -0
  158. package/packs/worktree/CHANGELOG.md +24 -0
  159. package/packs/worktree/README.md +110 -0
  160. package/packs/worktree/commands/wt.md +73 -0
  161. package/packs/worktree/scripts/wt.sh +396 -0
  162. package/packs/worktree/skills/worktree-manager/SKILL.md +68 -0
@@ -0,0 +1,346 @@
1
+ ---
2
+ name: hono-tester
3
+ description: Testing specialist for Hono applications using Bun test and Vitest, covering unit tests, integration tests, and API tests.
4
+ model: inherit
5
+ skills:
6
+ - hono-patterns
7
+ - zod-validation
8
+ ---
9
+
10
+ # Hono Tester
11
+
12
+ You are a testing specialist for Hono applications.
13
+
14
+ ## Current Task
15
+ Write comprehensive tests for the specified Hono code.
16
+
17
+ ## Testing Stack
18
+ - **Bun Projects**: `bun:test` (built-in)
19
+ - **CF Workers**: Vitest + `@cloudflare/vitest-pool-workers`
20
+ - **HTTP Testing**: Hono's built-in `app.request()`
21
+ - **Assertions**: Built-in matchers
22
+
23
+ ## Testing Patterns
24
+
25
+ ### Basic Route Testing (Bun)
26
+
27
+ ```typescript
28
+ // tests/users.test.ts
29
+ import { describe, it, expect, beforeEach } from 'bun:test'
30
+ import app from '../src/index'
31
+
32
+ describe('Users API', () => {
33
+ describe('GET /api/users', () => {
34
+ it('returns list of users', async () => {
35
+ const res = await app.request('/api/users')
36
+
37
+ expect(res.status).toBe(200)
38
+
39
+ const data = await res.json()
40
+ expect(data).toHaveProperty('data')
41
+ expect(Array.isArray(data.data)).toBe(true)
42
+ })
43
+
44
+ it('supports pagination', async () => {
45
+ const res = await app.request('/api/users?page=2&limit=10')
46
+
47
+ expect(res.status).toBe(200)
48
+
49
+ const data = await res.json()
50
+ expect(data.meta.page).toBe(2)
51
+ expect(data.meta.limit).toBe(10)
52
+ })
53
+ })
54
+
55
+ describe('POST /api/users', () => {
56
+ it('creates a new user', async () => {
57
+ const res = await app.request('/api/users', {
58
+ method: 'POST',
59
+ headers: { 'Content-Type': 'application/json' },
60
+ body: JSON.stringify({
61
+ email: 'test@example.com',
62
+ name: 'Test User'
63
+ })
64
+ })
65
+
66
+ expect(res.status).toBe(201)
67
+
68
+ const data = await res.json()
69
+ expect(data.email).toBe('test@example.com')
70
+ expect(data.name).toBe('Test User')
71
+ expect(data.id).toBeDefined()
72
+ })
73
+
74
+ it('returns 400 for invalid email', async () => {
75
+ const res = await app.request('/api/users', {
76
+ method: 'POST',
77
+ headers: { 'Content-Type': 'application/json' },
78
+ body: JSON.stringify({
79
+ email: 'invalid-email',
80
+ name: 'Test User'
81
+ })
82
+ })
83
+
84
+ expect(res.status).toBe(400)
85
+ })
86
+
87
+ it('returns 400 for missing required fields', async () => {
88
+ const res = await app.request('/api/users', {
89
+ method: 'POST',
90
+ headers: { 'Content-Type': 'application/json' },
91
+ body: JSON.stringify({})
92
+ })
93
+
94
+ expect(res.status).toBe(400)
95
+ })
96
+ })
97
+
98
+ describe('GET /api/users/:id', () => {
99
+ it('returns user by id', async () => {
100
+ const userId = 'valid-uuid-here'
101
+ const res = await app.request(`/api/users/${userId}`)
102
+
103
+ expect(res.status).toBe(200)
104
+
105
+ const data = await res.json()
106
+ expect(data.id).toBe(userId)
107
+ })
108
+
109
+ it('returns 404 for non-existent user', async () => {
110
+ const res = await app.request('/api/users/non-existent-id')
111
+
112
+ expect(res.status).toBe(404)
113
+ })
114
+
115
+ it('returns 400 for invalid uuid format', async () => {
116
+ const res = await app.request('/api/users/invalid-uuid')
117
+
118
+ expect(res.status).toBe(400)
119
+ })
120
+ })
121
+ })
122
+ ```
123
+
124
+ ### Testing with Mocked Bindings
125
+
126
+ ```typescript
127
+ // tests/with-bindings.test.ts
128
+ import { describe, it, expect, mock } from 'bun:test'
129
+ import { Hono } from 'hono'
130
+ import type { Env } from '../src/types/bindings'
131
+ import { users } from '../src/routes/users'
132
+
133
+ describe('Users with D1', () => {
134
+ const mockDB = {
135
+ prepare: mock(() => ({
136
+ bind: mock(() => ({
137
+ all: mock(() => Promise.resolve({
138
+ results: [
139
+ { id: '1', email: 'user1@test.com', name: 'User 1' },
140
+ { id: '2', email: 'user2@test.com', name: 'User 2' }
141
+ ]
142
+ })),
143
+ first: mock(() => Promise.resolve({
144
+ id: '1', email: 'user1@test.com', name: 'User 1'
145
+ })),
146
+ run: mock(() => Promise.resolve({ meta: { last_row_id: 1 } }))
147
+ }))
148
+ }))
149
+ }
150
+
151
+ const app = new Hono<Env>()
152
+ app.route('/users', users)
153
+
154
+ it('lists users from D1', async () => {
155
+ const res = await app.request('/users', {}, {
156
+ DB: mockDB as unknown as D1Database
157
+ })
158
+
159
+ expect(res.status).toBe(200)
160
+
161
+ const data = await res.json()
162
+ expect(data.data).toHaveLength(2)
163
+ })
164
+ })
165
+ ```
166
+
167
+ ### Testing Middleware
168
+
169
+ ```typescript
170
+ // tests/middleware.test.ts
171
+ import { describe, it, expect } from 'bun:test'
172
+ import { Hono } from 'hono'
173
+ import { authMiddleware } from '../src/middleware/auth'
174
+ import type { Env } from '../src/types/bindings'
175
+
176
+ describe('Auth Middleware', () => {
177
+ const app = new Hono<Env>()
178
+
179
+ app.use('/protected/*', authMiddleware)
180
+ app.get('/protected/resource', (c) => c.json({ message: 'success' }))
181
+
182
+ it('returns 401 without token', async () => {
183
+ const res = await app.request('/protected/resource')
184
+
185
+ expect(res.status).toBe(401)
186
+ })
187
+
188
+ it('returns 401 with invalid token', async () => {
189
+ const res = await app.request('/protected/resource', {
190
+ headers: { Authorization: 'Bearer invalid-token' }
191
+ }, {
192
+ JWT_SECRET: 'test-secret'
193
+ })
194
+
195
+ expect(res.status).toBe(401)
196
+ })
197
+
198
+ it('allows access with valid token', async () => {
199
+ // Generate valid JWT for test
200
+ const token = await generateTestToken()
201
+
202
+ const res = await app.request('/protected/resource', {
203
+ headers: { Authorization: `Bearer ${token}` }
204
+ }, {
205
+ JWT_SECRET: 'test-secret'
206
+ })
207
+
208
+ expect(res.status).toBe(200)
209
+ })
210
+ })
211
+ ```
212
+
213
+ ### Testing with Vitest (Cloudflare Workers)
214
+
215
+ ```typescript
216
+ // tests/workers.test.ts
217
+ import { describe, it, expect, beforeAll } from 'vitest'
218
+ import { unstable_dev } from 'wrangler'
219
+ import type { UnstableDevWorker } from 'wrangler'
220
+
221
+ describe('Worker', () => {
222
+ let worker: UnstableDevWorker
223
+
224
+ beforeAll(async () => {
225
+ worker = await unstable_dev('src/index.ts', {
226
+ experimental: { disableExperimentalWarning: true }
227
+ })
228
+ })
229
+
230
+ afterAll(async () => {
231
+ await worker.stop()
232
+ })
233
+
234
+ it('responds to health check', async () => {
235
+ const res = await worker.fetch('/health')
236
+
237
+ expect(res.status).toBe(200)
238
+
239
+ const data = await res.json()
240
+ expect(data.status).toBe('ok')
241
+ })
242
+ })
243
+ ```
244
+
245
+ ### Testing Zod Schemas
246
+
247
+ ```typescript
248
+ // tests/validators.test.ts
249
+ import { describe, it, expect } from 'bun:test'
250
+ import { createUserSchema, userQuerySchema } from '../src/validators/user.schema'
251
+
252
+ describe('User Schemas', () => {
253
+ describe('createUserSchema', () => {
254
+ it('validates valid user data', () => {
255
+ const result = createUserSchema.safeParse({
256
+ email: 'test@example.com',
257
+ name: 'Test User'
258
+ })
259
+
260
+ expect(result.success).toBe(true)
261
+ })
262
+
263
+ it('rejects invalid email', () => {
264
+ const result = createUserSchema.safeParse({
265
+ email: 'not-an-email',
266
+ name: 'Test User'
267
+ })
268
+
269
+ expect(result.success).toBe(false)
270
+ expect(result.error?.issues[0].path).toContain('email')
271
+ })
272
+
273
+ it('rejects empty name', () => {
274
+ const result = createUserSchema.safeParse({
275
+ email: 'test@example.com',
276
+ name: ''
277
+ })
278
+
279
+ expect(result.success).toBe(false)
280
+ })
281
+
282
+ it('applies default role', () => {
283
+ const result = createUserSchema.parse({
284
+ email: 'test@example.com',
285
+ name: 'Test User'
286
+ })
287
+
288
+ expect(result.role).toBe('user')
289
+ })
290
+ })
291
+
292
+ describe('userQuerySchema', () => {
293
+ it('coerces string numbers', () => {
294
+ const result = userQuerySchema.parse({
295
+ page: '2',
296
+ limit: '50'
297
+ })
298
+
299
+ expect(result.page).toBe(2)
300
+ expect(result.limit).toBe(50)
301
+ })
302
+
303
+ it('applies defaults', () => {
304
+ const result = userQuerySchema.parse({})
305
+
306
+ expect(result.page).toBe(1)
307
+ expect(result.limit).toBe(20)
308
+ })
309
+ })
310
+ })
311
+ ```
312
+
313
+ ## Test Coverage Goals
314
+
315
+ - **Unit Tests**: 90%+ coverage on validators and utilities
316
+ - **Integration Tests**: All routes tested with happy path + errors
317
+ - **Edge Cases**: Invalid inputs, missing data, auth failures
318
+
319
+ ## Testing Commands
320
+
321
+ ```bash
322
+ # Run all tests (Bun)
323
+ bun test
324
+
325
+ # Run with coverage
326
+ bun test --coverage
327
+
328
+ # Run specific test file
329
+ bun test tests/users.test.ts
330
+
331
+ # Watch mode
332
+ bun test --watch
333
+ ```
334
+
335
+ ## Quality Checklist
336
+
337
+ - [ ] All routes have tests
338
+ - [ ] Happy paths covered
339
+ - [ ] Error cases covered
340
+ - [ ] Validation tested
341
+ - [ ] Middleware tested
342
+ - [ ] Edge cases handled
343
+ - [ ] Mocks properly typed
344
+ - [ ] No flaky tests
345
+
346
+ Now write tests for the specified code.
@@ -0,0 +1,223 @@
1
+ ---
2
+ name: middleware-create
3
+ description: Create custom Hono middleware with proper typing
4
+ ---
5
+
6
+ # Create Hono Middleware
7
+
8
+ Create a new custom middleware following Hono best practices.
9
+
10
+ ## Workflow
11
+
12
+ ### Step 1: Gather Requirements
13
+
14
+ Ask the user:
15
+ 1. **Middleware name** (e.g., "auth", "rateLimit", "logger")
16
+ 2. **Purpose** - What should this middleware do?
17
+ 3. **Configuration options** - Any parameters needed?
18
+ 4. **Variables to set** - What data to pass to handlers?
19
+ 5. **When to apply** - Which routes need this?
20
+
21
+ ## Middleware Patterns
22
+
23
+ ### Basic Middleware
24
+
25
+ ```typescript
26
+ // middleware/{name}.ts
27
+ import { createMiddleware } from 'hono/factory'
28
+ import type { Env } from '../types/bindings'
29
+
30
+ export const {name}Middleware = createMiddleware<Env>(async (c, next) => {
31
+ // Pre-handler logic
32
+ console.log(`[${c.req.method}] ${c.req.url}`)
33
+
34
+ await next()
35
+
36
+ // Post-handler logic (runs after handler)
37
+ console.log(`Response status: ${c.res.status}`)
38
+ })
39
+ ```
40
+
41
+ ### Middleware with Variables
42
+
43
+ ```typescript
44
+ // middleware/auth.ts
45
+ import { createMiddleware } from 'hono/factory'
46
+ import { HTTPException } from 'hono/http-exception'
47
+ import { verify } from 'hono/jwt'
48
+ import type { Env } from '../types/bindings'
49
+
50
+ // First, update types/bindings.ts to include the variable:
51
+ // Variables: {
52
+ // user: { id: string; email: string; role: string }
53
+ // }
54
+
55
+ export const authMiddleware = createMiddleware<Env>(async (c, next) => {
56
+ const authHeader = c.req.header('Authorization')
57
+
58
+ if (!authHeader?.startsWith('Bearer ')) {
59
+ throw new HTTPException(401, { message: 'Missing authorization token' })
60
+ }
61
+
62
+ const token = authHeader.slice(7)
63
+
64
+ try {
65
+ const payload = await verify(token, c.env.JWT_SECRET)
66
+
67
+ // Set variable for downstream handlers
68
+ c.set('user', {
69
+ id: payload.sub as string,
70
+ email: payload.email as string,
71
+ role: payload.role as string
72
+ })
73
+
74
+ await next()
75
+ } catch {
76
+ throw new HTTPException(401, { message: 'Invalid or expired token' })
77
+ }
78
+ })
79
+ ```
80
+
81
+ ### Configurable Middleware Factory
82
+
83
+ ```typescript
84
+ // middleware/rateLimit.ts
85
+ import { createMiddleware } from 'hono/factory'
86
+ import { HTTPException } from 'hono/http-exception'
87
+ import type { Env } from '../types/bindings'
88
+
89
+ interface RateLimitOptions {
90
+ windowMs: number // Time window in milliseconds
91
+ max: number // Max requests per window
92
+ keyGenerator?: (c: Context) => string
93
+ }
94
+
95
+ export const rateLimit = (options: RateLimitOptions) => {
96
+ const { windowMs, max, keyGenerator } = options
97
+
98
+ return createMiddleware<Env>(async (c, next) => {
99
+ const key = keyGenerator
100
+ ? keyGenerator(c)
101
+ : c.req.header('CF-Connecting-IP') || 'unknown'
102
+
103
+ const cacheKey = `ratelimit:${key}`
104
+ const kv = c.env.KV
105
+
106
+ const current = parseInt(await kv.get(cacheKey) || '0')
107
+
108
+ if (current >= max) {
109
+ throw new HTTPException(429, {
110
+ message: 'Too many requests, please try again later'
111
+ })
112
+ }
113
+
114
+ await kv.put(cacheKey, String(current + 1), {
115
+ expirationTtl: Math.ceil(windowMs / 1000)
116
+ })
117
+
118
+ // Add rate limit headers
119
+ c.header('X-RateLimit-Limit', String(max))
120
+ c.header('X-RateLimit-Remaining', String(max - current - 1))
121
+
122
+ await next()
123
+ })
124
+ }
125
+
126
+ // Usage:
127
+ // app.use('/api/*', rateLimit({ windowMs: 60000, max: 100 }))
128
+ ```
129
+
130
+ ### Request Validation Middleware
131
+
132
+ ```typescript
133
+ // middleware/validateRequest.ts
134
+ import { createMiddleware } from 'hono/factory'
135
+ import type { Env } from '../types/bindings'
136
+
137
+ export const requestIdMiddleware = createMiddleware<Env>(async (c, next) => {
138
+ const requestId = c.req.header('X-Request-ID') || crypto.randomUUID()
139
+
140
+ c.set('requestId', requestId)
141
+ c.header('X-Request-ID', requestId)
142
+
143
+ await next()
144
+ })
145
+ ```
146
+
147
+ ### Response Timing Middleware
148
+
149
+ ```typescript
150
+ // middleware/timing.ts
151
+ import { createMiddleware } from 'hono/factory'
152
+ import type { Env } from '../types/bindings'
153
+
154
+ export const timingMiddleware = createMiddleware<Env>(async (c, next) => {
155
+ const start = Date.now()
156
+
157
+ await next()
158
+
159
+ const duration = Date.now() - start
160
+ c.header('X-Response-Time', `${duration}ms`)
161
+ })
162
+ ```
163
+
164
+ ### Error Handling Middleware
165
+
166
+ ```typescript
167
+ // middleware/errorHandler.ts
168
+ import { createMiddleware } from 'hono/factory'
169
+ import { HTTPException } from 'hono/http-exception'
170
+ import type { Env } from '../types/bindings'
171
+
172
+ export const errorHandler = createMiddleware<Env>(async (c, next) => {
173
+ try {
174
+ await next()
175
+ } catch (error) {
176
+ if (error instanceof HTTPException) {
177
+ return c.json(
178
+ { error: error.message, status: error.status },
179
+ error.status
180
+ )
181
+ }
182
+
183
+ console.error('Unhandled error:', error)
184
+ return c.json(
185
+ { error: 'Internal server error', status: 500 },
186
+ 500
187
+ )
188
+ }
189
+ })
190
+ ```
191
+
192
+ ## Generated Files
193
+
194
+ 1. `middleware/{name}.ts` - Middleware implementation
195
+ 2. Updated `types/bindings.ts` - Add Variables if needed
196
+ 3. Updated `middleware/index.ts` - Barrel export
197
+
198
+ ## Usage Examples
199
+
200
+ ```typescript
201
+ // Apply to all routes
202
+ app.use('*', timingMiddleware)
203
+
204
+ // Apply to specific path
205
+ app.use('/api/*', authMiddleware)
206
+
207
+ // Apply to specific routes
208
+ app.use('/api/admin/*', roleMiddleware('admin'))
209
+
210
+ // Chain multiple middleware
211
+ app.use('/api/*', timingMiddleware, requestIdMiddleware, authMiddleware)
212
+ ```
213
+
214
+ ## Quality Checklist
215
+
216
+ - [ ] Uses `createMiddleware` for type safety
217
+ - [ ] Properly typed with `Env`
218
+ - [ ] Calls `await next()` appropriately
219
+ - [ ] Handles errors with HTTPException
220
+ - [ ] Variables added to bindings type
221
+ - [ ] Exported from barrel file
222
+
223
+ Now ask the user what middleware they want to create!