@kood/claude-code 0.2.4 → 0.3.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 (130) hide show
  1. package/dist/index.js +13 -8
  2. package/package.json +1 -1
  3. package/templates/.claude/agents/code-reviewer.md +371 -19
  4. package/templates/.claude/agents/dependency-manager.md +197 -0
  5. package/templates/.claude/agents/deployment-validator.md +136 -0
  6. package/templates/.claude/agents/git-operator.md +147 -0
  7. package/templates/.claude/agents/implementation-executor.md +202 -0
  8. package/templates/.claude/agents/lint-fixer.md +155 -0
  9. package/templates/.claude/agents/refactor-advisor.md +339 -29
  10. package/templates/.claude/commands/agent-creator.md +355 -0
  11. package/templates/.claude/commands/docs-creator.md +404 -163
  12. package/templates/.claude/commands/docs-refactor.md +400 -113
  13. package/templates/.claude/commands/execute.md +357 -185
  14. package/templates/.claude/commands/git-all.md +16 -70
  15. package/templates/.claude/commands/git-session.md +36 -68
  16. package/templates/.claude/commands/git.md +20 -69
  17. package/templates/.claude/commands/lint-fix.md +164 -107
  18. package/templates/.claude/commands/lint-init.md +142 -168
  19. package/templates/.claude/commands/plan.md +300 -84
  20. package/templates/.claude/commands/prd.md +613 -0
  21. package/templates/.claude/commands/pre-deploy.md +242 -0
  22. package/templates/.claude/commands/subagent-creator.md +118 -0
  23. package/templates/.claude/commands/version-update.md +45 -57
  24. package/templates/hono/CLAUDE.md +99 -54
  25. package/templates/hono/docs/guides/conventions.md +352 -0
  26. package/templates/hono/docs/guides/env-setup.md +347 -0
  27. package/templates/hono/docs/guides/getting-started.md +239 -0
  28. package/templates/hono/docs/library/hono/error-handling.md +20 -29
  29. package/templates/hono/docs/library/hono/index.md +25 -52
  30. package/templates/hono/docs/library/hono/middleware.md +16 -75
  31. package/templates/hono/docs/library/hono/rpc.md +7 -35
  32. package/templates/hono/docs/library/hono/validation.md +25 -45
  33. package/templates/hono/docs/library/t3-env/index.md +374 -0
  34. package/templates/npx/CLAUDE.md +165 -65
  35. package/templates/npx/docs/library/commander/index.md +10 -73
  36. package/templates/npx/docs/library/fs-extra/index.md +21 -113
  37. package/templates/npx/docs/library/prompts/index.md +30 -176
  38. package/templates/npx/docs/references/patterns.md +75 -48
  39. package/templates/tanstack-start/CLAUDE.md +101 -77
  40. package/templates/tanstack-start/docs/architecture.md +427 -0
  41. package/templates/tanstack-start/docs/design.md +558 -0
  42. package/templates/tanstack-start/docs/guides/conventions.md +132 -32
  43. package/templates/tanstack-start/docs/guides/env-setup.md +127 -62
  44. package/templates/tanstack-start/docs/guides/getting-started.md +81 -20
  45. package/templates/tanstack-start/docs/guides/hooks.md +241 -36
  46. package/templates/tanstack-start/docs/guides/routes.md +213 -61
  47. package/templates/tanstack-start/docs/guides/services.md +260 -24
  48. package/templates/tanstack-start/docs/library/better-auth/index.md +469 -16
  49. package/templates/tanstack-start/docs/library/t3-env/index.md +307 -0
  50. package/templates/tanstack-start/docs/library/tanstack-query/index.md +12 -21
  51. package/templates/tanstack-start/docs/library/tanstack-query/invalidation.md +22 -35
  52. package/templates/tanstack-start/docs/library/tanstack-query/optimistic-updates.md +7 -24
  53. package/templates/tanstack-start/docs/library/tanstack-query/use-mutation.md +26 -39
  54. package/templates/tanstack-start/docs/library/tanstack-query/use-query.md +23 -26
  55. package/templates/tanstack-start/docs/library/tanstack-router/error-handling.md +32 -147
  56. package/templates/tanstack-start/docs/library/tanstack-router/hooks.md +25 -167
  57. package/templates/tanstack-start/docs/library/tanstack-router/index.md +39 -74
  58. package/templates/tanstack-start/docs/library/tanstack-router/navigation.md +46 -116
  59. package/templates/tanstack-start/docs/library/tanstack-router/route-context.md +35 -154
  60. package/templates/tanstack-start/docs/library/tanstack-router/search-params.md +32 -171
  61. package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +7 -15
  62. package/templates/tanstack-start/docs/library/tanstack-start/routing.md +16 -23
  63. package/templates/tanstack-start/docs/library/zod/complex-types.md +12 -31
  64. package/templates/tanstack-start/docs/library/zod/index.md +18 -35
  65. package/templates/tanstack-start/docs/library/zod/transforms.md +11 -25
  66. package/templates/tanstack-start/docs/library/zod/validation.md +12 -34
  67. package/templates/.claude/agents/debug-detective.md +0 -37
  68. package/templates/.claude/agents/test-writer.md +0 -41
  69. package/templates/.claude/commands/feedback.md +0 -199
  70. package/templates/.claude/commands/ts-fix.md +0 -176
  71. package/templates/.claude/skills/command-creator/LICENSE.txt +0 -202
  72. package/templates/.claude/skills/command-creator/SKILL.md +0 -245
  73. package/templates/.claude/skills/command-creator/scripts/init_command.py +0 -244
  74. package/templates/.claude/skills/command-creator/scripts/package_command.py +0 -125
  75. package/templates/.claude/skills/command-creator/scripts/quick_validate.py +0 -143
  76. package/templates/.claude/skills/frontend-design/SKILL.md +0 -310
  77. package/templates/.claude/skills/frontend-design/references/animation-patterns.md +0 -446
  78. package/templates/.claude/skills/frontend-design/references/colors-2026.md +0 -244
  79. package/templates/.claude/skills/frontend-design/references/typography-2026.md +0 -302
  80. package/templates/.claude/skills/gemini-review/SKILL.md +0 -118
  81. package/templates/.claude/skills/gemini-review/references/checklists.md +0 -129
  82. package/templates/.claude/skills/gemini-review/references/prompt-templates.md +0 -274
  83. package/templates/.claude/skills/skill-creator/LICENSE.txt +0 -202
  84. package/templates/.claude/skills/skill-creator/SKILL.md +0 -184
  85. package/templates/.claude/skills/skill-creator/scripts/init_skill.py +0 -303
  86. package/templates/.claude/skills/skill-creator/scripts/package_skill.py +0 -110
  87. package/templates/.claude/skills/skill-creator/scripts/quick_validate.py +0 -65
  88. package/templates/hono/docs/library/ai-sdk/index.md +0 -190
  89. package/templates/hono/docs/library/ai-sdk/openrouter.md +0 -111
  90. package/templates/hono/docs/library/ai-sdk/providers.md +0 -102
  91. package/templates/hono/docs/library/ai-sdk/streaming.md +0 -146
  92. package/templates/hono/docs/library/ai-sdk/structured-output.md +0 -161
  93. package/templates/hono/docs/library/ai-sdk/tools.md +0 -144
  94. package/templates/hono/docs/library/drizzle/cloudflare-d1.md +0 -247
  95. package/templates/hono/docs/library/drizzle/config.md +0 -167
  96. package/templates/hono/docs/library/drizzle/index.md +0 -259
  97. package/templates/hono/docs/library/hono/env-setup.md +0 -169
  98. package/templates/hono/docs/library/pino/index.md +0 -146
  99. package/templates/tanstack-start/docs/architecture/architecture.md +0 -243
  100. package/templates/tanstack-start/docs/deployment/cloudflare.md +0 -132
  101. package/templates/tanstack-start/docs/deployment/index.md +0 -163
  102. package/templates/tanstack-start/docs/deployment/nitro.md +0 -110
  103. package/templates/tanstack-start/docs/deployment/railway.md +0 -147
  104. package/templates/tanstack-start/docs/deployment/vercel.md +0 -135
  105. package/templates/tanstack-start/docs/design/components.md +0 -175
  106. package/templates/tanstack-start/docs/design/index.md +0 -151
  107. package/templates/tanstack-start/docs/design/safe-area.md +0 -118
  108. package/templates/tanstack-start/docs/design/tailwind-setup.md +0 -156
  109. package/templates/tanstack-start/docs/library/ai-sdk/hooks.md +0 -472
  110. package/templates/tanstack-start/docs/library/ai-sdk/index.md +0 -264
  111. package/templates/tanstack-start/docs/library/ai-sdk/openrouter.md +0 -371
  112. package/templates/tanstack-start/docs/library/ai-sdk/providers.md +0 -403
  113. package/templates/tanstack-start/docs/library/ai-sdk/streaming.md +0 -320
  114. package/templates/tanstack-start/docs/library/ai-sdk/structured-output.md +0 -454
  115. package/templates/tanstack-start/docs/library/ai-sdk/tools.md +0 -473
  116. package/templates/tanstack-start/docs/library/better-auth/2fa.md +0 -48
  117. package/templates/tanstack-start/docs/library/better-auth/advanced.md +0 -55
  118. package/templates/tanstack-start/docs/library/better-auth/plugins.md +0 -34
  119. package/templates/tanstack-start/docs/library/better-auth/session.md +0 -47
  120. package/templates/tanstack-start/docs/library/better-auth/setup.md +0 -41
  121. package/templates/tanstack-start/docs/library/drizzle/cloudflare-d1.md +0 -147
  122. package/templates/tanstack-start/docs/library/drizzle/config.md +0 -118
  123. package/templates/tanstack-start/docs/library/drizzle/crud.md +0 -205
  124. package/templates/tanstack-start/docs/library/drizzle/index.md +0 -79
  125. package/templates/tanstack-start/docs/library/drizzle/relations.md +0 -202
  126. package/templates/tanstack-start/docs/library/drizzle/schema.md +0 -154
  127. package/templates/tanstack-start/docs/library/drizzle/setup.md +0 -96
  128. package/templates/tanstack-start/docs/library/drizzle/transactions.md +0 -127
  129. package/templates/tanstack-start/docs/library/pino/index.md +0 -320
  130. /package/templates/hono/docs/{architecture/architecture.md → architecture.md} +0 -0
@@ -1,61 +1,105 @@
1
- # CLAUDE.md - Hono Server Framework
1
+ # CLAUDE.md - Hono
2
2
 
3
- > Web Standards 기반 초경량 서버 프레임워크
4
-
5
- ## Instructions
3
+ > Web Standards 기반 초경량 프레임워크
6
4
 
5
+ <instructions>
7
6
  @../../commands/git.md
7
+ @docs/guides/getting-started.md
8
8
  @docs/library/hono/index.md
9
9
  @docs/library/prisma/index.md
10
+ @docs/library/t3-env/index.md
10
11
  @docs/library/zod/index.md
11
- @docs/deployment/index.md
12
+ </instructions>
12
13
 
13
14
  ---
14
15
 
15
- ## STOP - 금지 사항
16
+ <forbidden>
17
+
18
+ | 분류 | 금지 |
19
+ |------|------|
20
+ | **Git** | `Generated with Claude Code`, `🤖`, `Co-Authored-By:`, 여러 줄, 이모지 |
21
+ | **Prisma** | `db push/migrate/generate` 자동 실행, schema 임의 변경 |
22
+ | **API** | handler 내 수동 검증/인증, 일반 Error throw |
23
+ | **검색** | grep, rg, find |
16
24
 
17
- | 분류 | 금지 항목 |
18
- |------|----------|
19
- | **Git** | `Generated with Claude Code`, `🤖`, `Co-Authored-By:`, 여러 줄 커밋, 이모지 |
20
- | **Prisma** | `db push`, `migrate`, `generate` 자동 실행, schema 임의 변경 |
21
- | **API** | handler 내부 수동 검증 (→ zValidator), 수동 인증 (→ middleware), 일반 Error throw (→ HTTPException) |
22
- | **검색** | grep, rg, find (→ ast-grep 사용) |
25
+ </forbidden>
23
26
 
24
27
  ---
25
28
 
26
- ## ALWAYS - 필수 사항
29
+ <required>
27
30
 
28
31
  | 작업 | 필수 |
29
32
  |------|------|
30
- | 작업 전 | 관련 docs 읽기 |
31
- | 코드 검색 | ast-grep 사용 |
32
- | 복잡한 분석 | Sequential Thinking MCP |
33
- | 3+ 파일 수정 | gemini-review 실행 |
34
- | 코드 작성 | UTF-8, 코드 묶음별 한글 주석 |
35
- | Prisma | Multi-File 구조, 모든 요소 한글 주석 |
33
+ | 작업 전 | 관련 docs 읽기 (API→hono, DB→prisma) |
34
+ | 코드 검색 | ast-grep |
35
+ | 복잡한 작업 | Sequential Thinking MCP |
36
+ | 3+ 파일 수정 | gemini-review |
37
+ | Validation | zValidator, HTTPException 에러 처리 |
38
+ | 코드 작성 | UTF-8, 코드 묶음별 한글 주석, Prisma Multi-File 모든 요소 주석 |
39
+
40
+ </required>
36
41
 
37
42
  ---
38
43
 
39
- ## Tech Stack
44
+ <tech_stack>
40
45
 
41
- | 기술 | 버전 | 주의사항 |
42
- |------|------|----------|
43
- | Hono | 최신 | Web Standards 기반 |
44
- | TypeScript | 5.x | strict mode |
46
+ | 기술 | 버전 | 주의 |
47
+ |------|------|------|
48
+ | Hono | 최신 | - |
49
+ | TypeScript | 5.x | strict |
45
50
  | Prisma | **7.x** | `prisma-client`, output 필수 |
46
- | Zod | **4.x** | `z.email()`, `z.url()` (v4 문법) |
51
+ | Zod | **4.x** | `z.email()`, `z.url()` |
52
+
53
+ </tech_stack>
47
54
 
48
55
  ---
49
56
 
50
- ## Quick Patterns
57
+ <structure>
58
+ ```
59
+ src/
60
+ ├── routes/
61
+ │ ├── index.ts # Root routes
62
+ │ ├── users.ts # /users/*
63
+ │ └── posts.ts # /posts/*
64
+ ├── middleware/ # Auth, CORS, Logger
65
+ ├── services/ # Business logic
66
+ ├── lib/
67
+ │ ├── prisma.ts
68
+ │ └── env.ts
69
+ └── types/
70
+ ```
71
+
72
+ 공통 로직 → `src/services/`, 라우트별 로직 → 각 route 파일
73
+ </structure>
74
+
75
+ ---
76
+
77
+ <conventions>
78
+
79
+ 파일명: kebab-case
80
+ TypeScript: const 선언, 명시적 return type, interface(객체)/type(유니온), any→unknown
81
+ Import 순서: 외부 → 내부 → 상대경로 → type
82
+
83
+ Prisma Multi-File:
84
+ ```
85
+ prisma/schema/
86
+ ├── +base.prisma # datasource, generator
87
+ ├── +enum.prisma # enum
88
+ └── [model].prisma # 모델별 (한글 주석!)
89
+ ```
90
+
91
+ </conventions>
92
+
93
+ ---
51
94
 
52
- ### App + 에러 핸들러
95
+ <quick_patterns>
53
96
 
54
97
  ```typescript
98
+ // App + 에러 핸들러
55
99
  import { Hono } from 'hono'
56
100
  import { HTTPException } from 'hono/http-exception'
57
101
 
58
- type Bindings = { DATABASE_URL: string; JWT_SECRET: string }
102
+ type Bindings = { DATABASE_URL: string }
59
103
 
60
104
  const app = new Hono<{ Bindings: Bindings }>()
61
105
 
@@ -67,21 +111,18 @@ app.onError((err, c) => {
67
111
  return c.json({ error: 'Internal Server Error' }, 500)
68
112
  })
69
113
 
70
- app.notFound((c) => c.json({ error: 'Not Found' }, 404))
71
-
72
114
  export default app
73
115
  ```
74
116
 
75
- ### Zod 검증 (v4 문법)
76
-
77
117
  ```typescript
118
+ // Zod v4 + Validation
78
119
  import { zValidator } from '@hono/zod-validator'
79
120
  import { z } from 'zod'
80
121
 
81
122
  const schema = z.object({
82
- email: z.email(), // ✅ v4
123
+ email: z.email(),
83
124
  name: z.string().min(1).trim(),
84
- website: z.url().optional() // ✅ v4
125
+ website: z.url().optional()
85
126
  })
86
127
 
87
128
  app.post('/users', zValidator('json', schema), (c) => {
@@ -90,36 +131,40 @@ app.post('/users', zValidator('json', schema), (c) => {
90
131
  })
91
132
  ```
92
133
 
93
- ### Prisma Multi-File 구조
134
+ ```typescript
135
+ // Middleware
136
+ import { createMiddleware } from 'hono/factory'
137
+ import { HTTPException } from 'hono/http-exception'
94
138
 
95
- ```
96
- prisma/schema/
97
- ├── +base.prisma # datasource, generator
98
- ├── +enum.prisma # enum 정의
99
- ├── user.prisma # User 모델 (한글 주석 필수)
100
- └── post.prisma # Post 모델
139
+ export const authMiddleware = createMiddleware(async (c, next) => {
140
+ const token = c.req.header('Authorization')?.replace('Bearer ', '')
141
+ if (!token) throw new HTTPException(401, { message: 'Unauthorized' })
142
+
143
+ c.set('userId', decoded.sub)
144
+ await next()
145
+ })
146
+
147
+ // 사용
148
+ app.use('/api/*', authMiddleware)
101
149
  ```
102
150
 
103
151
  ```prisma
104
- // +base.prisma
152
+ // +base.prisma (Prisma 7.x)
105
153
  generator client {
106
- provider = "prisma-client" // ✅ v7
107
- output = "./generated/client" // ✅ 필수
154
+ provider = "prisma-client"
155
+ output = "./generated/client"
108
156
  }
109
157
  ```
110
158
 
111
- ---
159
+ </quick_patterns>
112
160
 
113
- ## 문서 구조
161
+ ---
114
162
 
163
+ <docs_structure>
115
164
  ```
116
165
  docs/
117
- ├── library/
118
- ├── hono/ # 라우팅, 미들웨어, 검증, RPC
119
- │ ├── prisma/ # CRUD, 관계, D1 연동
120
- │ ├── zod/ # v4 문법, 검증 패턴
121
- │ ├── ai-sdk/ # LLM 통합 (streaming, tools)
122
- │ └── pino/ # 로깅
123
- ├── deployment/ # Docker, Railway, Vercel, Cloudflare
124
- └── architecture/ # 아키텍처 패턴
166
+ ├── guides/ # getting-started, conventions, env-setup
167
+ ├── library/ # hono, prisma, t3-env, zod
168
+ └── deployment/ # cloudflare, docker, railway, vercel
125
169
  ```
170
+ </docs_structure>
@@ -0,0 +1,352 @@
1
+ # 코드 컨벤션
2
+
3
+ > Hono 프로젝트 코드 작성 규칙
4
+
5
+ ---
6
+
7
+ <naming>
8
+
9
+ ## 파일 네이밍
10
+
11
+ | 타입 | 규칙 | 예시 |
12
+ |------|------|------|
13
+ | **일반 파일** | kebab-case | `user-service.ts`, `auth-middleware.ts` |
14
+ | **Route 파일** | kebab-case | `users.ts`, `posts.ts` |
15
+ | **타입 파일** | kebab-case | `user-types.ts`, `api-types.ts` |
16
+
17
+ </naming>
18
+
19
+ ---
20
+
21
+ <typescript>
22
+
23
+ ## TypeScript 규칙
24
+
25
+ | 규칙 | 설명 | 예시 |
26
+ |------|------|------|
27
+ | **함수 선언** | const 함수, 명시적 return type | `const fn = (): ReturnType => {}` |
28
+ | **타입 정의** | interface (객체), type (유니온) | `interface User {}`, `type Status = 'a' \| 'b'` |
29
+ | **any 금지** | unknown 사용 | `const data: unknown = JSON.parse(str)` |
30
+ | **Import 타입** | type import 분리 | `import type { User } from '@/types'` |
31
+
32
+ ## 패턴
33
+
34
+ ```typescript
35
+ // ✅ const 함수, 명시적 타입
36
+ const getUserById = async (id: string): Promise<User | null> => {
37
+ return prisma.user.findUnique({ where: { id } })
38
+ }
39
+
40
+ // ✅ 간단한 함수도 명시적 타입
41
+ const formatDate = (date: Date): string => {
42
+ return date.toISOString()
43
+ }
44
+
45
+ // ✅ any 금지 → unknown 사용
46
+ const parseJSON = (data: string): unknown => {
47
+ return JSON.parse(data)
48
+ }
49
+
50
+ // ❌ any 사용 금지
51
+ const badParse = (data: string): any => { // ❌
52
+ return JSON.parse(data)
53
+ }
54
+
55
+ // ❌ function 키워드 금지
56
+ function badFunction() { // ❌
57
+ return 'use const arrow function'
58
+ }
59
+ ```
60
+
61
+ </typescript>
62
+
63
+ ---
64
+
65
+ <imports>
66
+
67
+ ## Import 순서
68
+
69
+ ```typescript
70
+ // 1. External libraries
71
+ import { Hono } from 'hono'
72
+ import { zValidator } from '@hono/zod-validator'
73
+ import { z } from 'zod'
74
+
75
+ // 2. Internal modules
76
+ import { authMiddleware } from './middleware/auth'
77
+ import { prisma } from './lib/prisma'
78
+ import { env } from './lib/env'
79
+
80
+ // 3. Type imports
81
+ import type { User } from './types'
82
+ import type { Context } from 'hono'
83
+ ```
84
+
85
+ </imports>
86
+
87
+ ---
88
+
89
+ <comments>
90
+
91
+ ## 한글 주석 (묶음 단위)
92
+
93
+ ```typescript
94
+ // ✅ 코드 묶음 단위 주석
95
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
96
+ // 사용자 조회
97
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
98
+ users.get('/', async (c) => {
99
+ const users = await prisma.user.findMany()
100
+ return c.json({ users })
101
+ })
102
+
103
+ users.get('/:id', async (c) => {
104
+ const id = c.req.param('id')
105
+ const user = await prisma.user.findUnique({ where: { id } })
106
+ if (!user) throw new HTTPException(404, { message: 'User not found' })
107
+ return c.json({ user })
108
+ })
109
+
110
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
111
+ // 사용자 생성/수정
112
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
113
+ users.post('/', zValidator('json', createUserSchema), async (c) => {
114
+ const data = c.req.valid('json')
115
+ const user = await prisma.user.create({ data })
116
+ return c.json({ user }, 201)
117
+ })
118
+ ```
119
+
120
+ ```typescript
121
+ // ❌ 세세한 주석 (금지)
122
+ users.get('/', async (c) => { // 사용자 목록 조회
123
+ const users = await prisma.user.findMany() // DB에서 조회
124
+ return c.json({ users }) // JSON 반환
125
+ })
126
+ ```
127
+
128
+ </comments>
129
+
130
+ ---
131
+
132
+ <error_handling>
133
+
134
+ ## 에러 처리 패턴
135
+
136
+ ### HTTPException 사용
137
+
138
+ ```typescript
139
+ import { HTTPException } from 'hono/http-exception'
140
+
141
+ // ✅ HTTPException 사용
142
+ users.get('/:id', async (c) => {
143
+ const id = c.req.param('id')
144
+ const user = await prisma.user.findUnique({ where: { id } })
145
+
146
+ if (!user) {
147
+ throw new HTTPException(404, { message: 'User not found' })
148
+ }
149
+
150
+ return c.json({ user })
151
+ })
152
+
153
+ // ❌ 일반 Error 사용 금지
154
+ users.get('/:id', async (c) => {
155
+ const id = c.req.param('id')
156
+ const user = await prisma.user.findUnique({ where: { id } })
157
+
158
+ if (!user) {
159
+ throw new Error('User not found') // ❌
160
+ }
161
+
162
+ return c.json({ user })
163
+ })
164
+ ```
165
+
166
+ ### 전역 에러 핸들러
167
+
168
+ ```typescript
169
+ // src/index.ts
170
+ import { Hono } from 'hono'
171
+ import { HTTPException } from 'hono/http-exception'
172
+
173
+ const app = new Hono()
174
+
175
+ app.onError((err, c) => {
176
+ if (err instanceof HTTPException) {
177
+ return c.json(
178
+ {
179
+ error: err.message,
180
+ status: err.status,
181
+ },
182
+ err.status
183
+ )
184
+ }
185
+
186
+ console.error('Unexpected error:', err)
187
+ return c.json(
188
+ {
189
+ error: 'Internal Server Error',
190
+ status: 500,
191
+ },
192
+ 500
193
+ )
194
+ })
195
+
196
+ app.notFound((c) => {
197
+ return c.json(
198
+ {
199
+ error: 'Not Found',
200
+ status: 404,
201
+ },
202
+ 404
203
+ )
204
+ })
205
+ ```
206
+
207
+ ### 커스텀 에러 클래스
208
+
209
+ ```typescript
210
+ // lib/errors.ts
211
+ import { HTTPException } from 'hono/http-exception'
212
+
213
+ export class NotFoundError extends HTTPException {
214
+ constructor(resource: string) {
215
+ super(404, { message: `${resource} not found` })
216
+ }
217
+ }
218
+
219
+ export class ValidationError extends HTTPException {
220
+ constructor(message: string) {
221
+ super(400, { message })
222
+ }
223
+ }
224
+
225
+ export class UnauthorizedError extends HTTPException {
226
+ constructor() {
227
+ super(401, { message: 'Unauthorized' })
228
+ }
229
+ }
230
+
231
+ // 사용
232
+ import { NotFoundError } from '@/lib/errors'
233
+
234
+ users.get('/:id', async (c) => {
235
+ const user = await prisma.user.findUnique({ where: { id } })
236
+ if (!user) throw new NotFoundError('User')
237
+ return c.json({ user })
238
+ })
239
+ ```
240
+
241
+ </error_handling>
242
+
243
+ ---
244
+
245
+ <validation>
246
+
247
+ ## Validation 패턴
248
+
249
+ ### zValidator 사용
250
+
251
+ ```typescript
252
+ import { zValidator } from '@hono/zod-validator'
253
+ import { z } from 'zod'
254
+
255
+ // ✅ zValidator 사용
256
+ const createUserSchema = z.object({
257
+ name: z.string().min(1).trim(),
258
+ email: z.email(),
259
+ age: z.number().int().min(18).optional(),
260
+ })
261
+
262
+ users.post('/', zValidator('json', createUserSchema), async (c) => {
263
+ const data = c.req.valid('json') // 타입 안전
264
+ const user = await prisma.user.create({ data })
265
+ return c.json({ user }, 201)
266
+ })
267
+
268
+ // ❌ 수동 검증 금지
269
+ users.post('/', async (c) => {
270
+ const body = await c.req.json()
271
+
272
+ if (!body.name || !body.email) { // ❌
273
+ return c.json({ error: 'Invalid input' }, 400)
274
+ }
275
+
276
+ const user = await prisma.user.create({ data: body })
277
+ return c.json({ user }, 201)
278
+ })
279
+ ```
280
+
281
+ ### 여러 Validator
282
+
283
+ ```typescript
284
+ // Query Params
285
+ users.get('/', zValidator('query', z.object({ page: z.string() })), (c) => {
286
+ const { page } = c.req.valid('query')
287
+ return c.json({ page })
288
+ })
289
+
290
+ // Path Params
291
+ users.get('/:id', zValidator('param', z.object({ id: z.string() })), (c) => {
292
+ const { id } = c.req.valid('param')
293
+ return c.json({ id })
294
+ })
295
+
296
+ // JSON Body
297
+ users.post('/', zValidator('json', createUserSchema), (c) => {
298
+ const data = c.req.valid('json')
299
+ return c.json({ data }, 201)
300
+ })
301
+ ```
302
+
303
+ </validation>
304
+
305
+ ---
306
+
307
+ <examples>
308
+
309
+ ## 파일명 예시
310
+
311
+ | 타입 | ❌ 잘못된 예시 | ✅ 올바른 예시 |
312
+ |------|---------------|---------------|
313
+ | Route | `Users.ts` | `users.ts` |
314
+ | Service | `userService.ts` | `user-service.ts` |
315
+ | Middleware | `authMiddleware.ts` | `auth-middleware.ts` |
316
+ | Utility | `formatUtils.ts` | `format-utils.ts` |
317
+ | Type | `UserTypes.ts` | `user-types.ts` |
318
+
319
+ ## 디렉토리 구조
320
+
321
+ ```
322
+ src/
323
+ ├── routes/
324
+ │ ├── users.ts # /users/*
325
+ │ ├── posts.ts # /posts/*
326
+ │ └── auth.ts # /auth/*
327
+ ├── middleware/
328
+ │ ├── auth.ts # 인증 미들웨어
329
+ │ ├── logger.ts # 로깅 미들웨어
330
+ │ └── cors.ts # CORS 미들웨어
331
+ ├── services/
332
+ │ ├── user-service.ts # 사용자 비즈니스 로직
333
+ │ └── post-service.ts # 게시글 비즈니스 로직
334
+ ├── lib/
335
+ │ ├── prisma.ts # Prisma 클라이언트
336
+ │ ├── env.ts # 환경 변수
337
+ │ └── errors.ts # 커스텀 에러
338
+ └── types/
339
+ ├── user-types.ts # 사용자 타입
340
+ └── api-types.ts # API 타입
341
+ ```
342
+
343
+ </examples>
344
+
345
+ ---
346
+
347
+ <sources>
348
+
349
+ - [Hono Best Practices](https://hono.dev/guides/best-practices)
350
+ - [TypeScript Style Guide](https://google.github.io/styleguide/tsguide.html)
351
+
352
+ </sources>