@smicolon/ai-kit 0.3.2 → 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.
Files changed (155) hide show
  1. package/README.md +73 -40
  2. package/dist/index.js +260 -126
  3. package/package.json +5 -5
  4. package/.claude-plugin/marketplace.json +0 -369
  5. package/packs/architect/CHANGELOG.md +0 -17
  6. package/packs/architect/README.md +0 -58
  7. package/packs/architect/agents/system-architect.md +0 -768
  8. package/packs/architect/commands/diagram-create.md +0 -300
  9. package/packs/better-auth/.mcp.json +0 -14
  10. package/packs/better-auth/CHANGELOG.md +0 -26
  11. package/packs/better-auth/README.md +0 -125
  12. package/packs/better-auth/agents/auth-architect.md +0 -278
  13. package/packs/better-auth/commands/auth-provider-add.md +0 -265
  14. package/packs/better-auth/commands/auth-setup.md +0 -298
  15. package/packs/better-auth/skills/auth-security/SKILL.md +0 -425
  16. package/packs/better-auth/skills/better-auth-patterns/SKILL.md +0 -455
  17. package/packs/dev-loop/CHANGELOG.md +0 -69
  18. package/packs/dev-loop/README.md +0 -155
  19. package/packs/dev-loop/commands/cancel-dev.md +0 -21
  20. package/packs/dev-loop/commands/dev-loop.md +0 -72
  21. package/packs/dev-loop/commands/dev-plan.md +0 -351
  22. package/packs/dev-loop/hooks/hooks.json +0 -15
  23. package/packs/dev-loop/hooks/stop-hook.sh +0 -178
  24. package/packs/dev-loop/scripts/setup-dev-loop.sh +0 -194
  25. package/packs/dev-loop/skills/tdd-planner/SKILL.md +0 -249
  26. package/packs/dev-loop/skills/tdd-planner/references/framework-patterns.md +0 -874
  27. package/packs/dev-loop/skills/tdd-planner/references/good-example.md +0 -260
  28. package/packs/dev-loop/skills/tdd-planner/references/plan-template.md +0 -275
  29. package/packs/django/CHANGELOG.md +0 -39
  30. package/packs/django/README.md +0 -92
  31. package/packs/django/agents/django-architect.md +0 -182
  32. package/packs/django/agents/django-builder.md +0 -250
  33. package/packs/django/agents/django-feature-based.md +0 -420
  34. package/packs/django/agents/django-reviewer.md +0 -253
  35. package/packs/django/agents/django-tester.md +0 -230
  36. package/packs/django/commands/api-endpoint.md +0 -285
  37. package/packs/django/commands/model-create.md +0 -178
  38. package/packs/django/commands/test-generate.md +0 -325
  39. package/packs/django/rules/migrations.md +0 -138
  40. package/packs/django/rules/models.md +0 -167
  41. package/packs/django/rules/serializers.md +0 -126
  42. package/packs/django/rules/services.md +0 -131
  43. package/packs/django/rules/tests.md +0 -140
  44. package/packs/django/rules/views.md +0 -102
  45. package/packs/django/skills/import-convention-enforcer/SKILL.md +0 -226
  46. package/packs/django/skills/import-convention-enforcer/patterns/django-imports.md +0 -343
  47. package/packs/django/skills/migration-safety-checker/SKILL.md +0 -375
  48. package/packs/django/skills/model-entity-validator/SKILL.md +0 -298
  49. package/packs/django/skills/performance-optimizer/SKILL.md +0 -447
  50. package/packs/django/skills/red-phase-verifier/SKILL.md +0 -180
  51. package/packs/django/skills/security-first-validator/SKILL.md +0 -435
  52. package/packs/django/skills/test-coverage-advisor/SKILL.md +0 -394
  53. package/packs/django/skills/test-validity-checker/SKILL.md +0 -194
  54. package/packs/failure-log/CHANGELOG.md +0 -20
  55. package/packs/failure-log/README.md +0 -168
  56. package/packs/failure-log/commands/failure-add.md +0 -106
  57. package/packs/failure-log/commands/failure-list.md +0 -89
  58. package/packs/failure-log/hooks/hooks.json +0 -16
  59. package/packs/failure-log/hooks/scripts/inject-failures.sh +0 -64
  60. package/packs/failure-log/skills/failure-log-manager/SKILL.md +0 -164
  61. package/packs/flutter/CHANGELOG.md +0 -19
  62. package/packs/flutter/README.md +0 -170
  63. package/packs/flutter/agents/flutter-architect.md +0 -166
  64. package/packs/flutter/agents/flutter-builder.md +0 -303
  65. package/packs/flutter/agents/release-manager.md +0 -355
  66. package/packs/flutter/commands/fastlane-setup.md +0 -188
  67. package/packs/flutter/commands/flutter-build.md +0 -90
  68. package/packs/flutter/commands/flutter-deploy.md +0 -133
  69. package/packs/flutter/commands/flutter-test.md +0 -117
  70. package/packs/flutter/commands/signing-setup.md +0 -209
  71. package/packs/flutter/hooks/hooks.json +0 -17
  72. package/packs/flutter/skills/fastlane-knowledge/SKILL.md +0 -193
  73. package/packs/flutter/skills/flutter-architecture/SKILL.md +0 -127
  74. package/packs/flutter/skills/store-publishing/SKILL.md +0 -163
  75. package/packs/hono/CHANGELOG.md +0 -19
  76. package/packs/hono/README.md +0 -143
  77. package/packs/hono/agents/hono-architect.md +0 -240
  78. package/packs/hono/agents/hono-builder.md +0 -285
  79. package/packs/hono/agents/hono-reviewer.md +0 -279
  80. package/packs/hono/agents/hono-tester.md +0 -346
  81. package/packs/hono/commands/middleware-create.md +0 -223
  82. package/packs/hono/commands/project-init.md +0 -306
  83. package/packs/hono/commands/route-create.md +0 -153
  84. package/packs/hono/commands/rpc-client.md +0 -263
  85. package/packs/hono/skills/cloudflare-bindings/SKILL.md +0 -408
  86. package/packs/hono/skills/hono-patterns/SKILL.md +0 -309
  87. package/packs/hono/skills/rpc-typesafe/SKILL.md +0 -388
  88. package/packs/hono/skills/zod-validation/SKILL.md +0 -332
  89. package/packs/nestjs/CHANGELOG.md +0 -29
  90. package/packs/nestjs/README.md +0 -75
  91. package/packs/nestjs/agents/nestjs-architect.md +0 -402
  92. package/packs/nestjs/agents/nestjs-builder.md +0 -301
  93. package/packs/nestjs/agents/nestjs-tester.md +0 -437
  94. package/packs/nestjs/commands/module-create.md +0 -369
  95. package/packs/nestjs/rules/controllers.md +0 -92
  96. package/packs/nestjs/rules/dto.md +0 -124
  97. package/packs/nestjs/rules/entities.md +0 -102
  98. package/packs/nestjs/rules/services.md +0 -106
  99. package/packs/nestjs/skills/barrel-export-manager/SKILL.md +0 -389
  100. package/packs/nestjs/skills/import-convention-enforcer/SKILL.md +0 -365
  101. package/packs/nextjs/CHANGELOG.md +0 -36
  102. package/packs/nextjs/README.md +0 -76
  103. package/packs/nextjs/agents/frontend-tester.md +0 -680
  104. package/packs/nextjs/agents/frontend-visual.md +0 -820
  105. package/packs/nextjs/agents/nextjs-architect.md +0 -331
  106. package/packs/nextjs/agents/nextjs-modular.md +0 -433
  107. package/packs/nextjs/commands/component-create.md +0 -398
  108. package/packs/nextjs/rules/api-routes.md +0 -129
  109. package/packs/nextjs/rules/components.md +0 -106
  110. package/packs/nextjs/rules/hooks.md +0 -132
  111. package/packs/nextjs/skills/accessibility-validator/SKILL.md +0 -445
  112. package/packs/nextjs/skills/import-convention-enforcer/SKILL.md +0 -399
  113. package/packs/nextjs/skills/react-form-validator/SKILL.md +0 -569
  114. package/packs/nuxtjs/CHANGELOG.md +0 -30
  115. package/packs/nuxtjs/README.md +0 -56
  116. package/packs/nuxtjs/agents/frontend-tester.md +0 -680
  117. package/packs/nuxtjs/agents/frontend-visual.md +0 -820
  118. package/packs/nuxtjs/agents/nuxtjs-architect.md +0 -537
  119. package/packs/nuxtjs/commands/component-create.md +0 -223
  120. package/packs/nuxtjs/rules/components.md +0 -101
  121. package/packs/nuxtjs/rules/composables.md +0 -118
  122. package/packs/nuxtjs/rules/server-routes.md +0 -127
  123. package/packs/nuxtjs/skills/accessibility-validator/SKILL.md +0 -183
  124. package/packs/nuxtjs/skills/import-convention-enforcer/SKILL.md +0 -196
  125. package/packs/nuxtjs/skills/veevalidate-form-validator/SKILL.md +0 -190
  126. package/packs/onboard/CHANGELOG.md +0 -22
  127. package/packs/onboard/README.md +0 -103
  128. package/packs/onboard/agents/onboard-guide.md +0 -118
  129. package/packs/onboard/commands/onboard.md +0 -313
  130. package/packs/onboard/skills/onboard-context-provider/SKILL.md +0 -98
  131. package/packs/tanstack-router/CHANGELOG.md +0 -30
  132. package/packs/tanstack-router/README.md +0 -113
  133. package/packs/tanstack-router/agents/tanstack-architect.md +0 -173
  134. package/packs/tanstack-router/agents/tanstack-builder.md +0 -360
  135. package/packs/tanstack-router/agents/tanstack-tester.md +0 -454
  136. package/packs/tanstack-router/commands/form-create.md +0 -313
  137. package/packs/tanstack-router/commands/query-create.md +0 -263
  138. package/packs/tanstack-router/commands/route-create.md +0 -190
  139. package/packs/tanstack-router/commands/table-create.md +0 -413
  140. package/packs/tanstack-router/skills/ai-patterns/SKILL.md +0 -370
  141. package/packs/tanstack-router/skills/db-patterns/SKILL.md +0 -346
  142. package/packs/tanstack-router/skills/devtools-patterns/SKILL.md +0 -415
  143. package/packs/tanstack-router/skills/form-patterns/SKILL.md +0 -425
  144. package/packs/tanstack-router/skills/pacer-patterns/SKILL.md +0 -341
  145. package/packs/tanstack-router/skills/query-patterns/SKILL.md +0 -359
  146. package/packs/tanstack-router/skills/router-patterns/SKILL.md +0 -285
  147. package/packs/tanstack-router/skills/store-patterns/SKILL.md +0 -351
  148. package/packs/tanstack-router/skills/table-patterns/SKILL.md +0 -531
  149. package/packs/tanstack-router/skills/tanstack-conventions/SKILL.md +0 -428
  150. package/packs/tanstack-router/skills/virtual-patterns/SKILL.md +0 -490
  151. package/packs/worktree/CHANGELOG.md +0 -45
  152. package/packs/worktree/README.md +0 -219
  153. package/packs/worktree/commands/wt.md +0 -93
  154. package/packs/worktree/scripts/wt.sh +0 -957
  155. package/packs/worktree/skills/worktree-manager/SKILL.md +0 -113
@@ -1,346 +0,0 @@
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.
@@ -1,223 +0,0 @@
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!