@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.
- package/dist/index.js +13 -8
- package/package.json +1 -1
- package/templates/.claude/agents/code-reviewer.md +371 -19
- package/templates/.claude/agents/dependency-manager.md +197 -0
- package/templates/.claude/agents/deployment-validator.md +136 -0
- package/templates/.claude/agents/git-operator.md +147 -0
- package/templates/.claude/agents/implementation-executor.md +202 -0
- package/templates/.claude/agents/lint-fixer.md +155 -0
- package/templates/.claude/agents/refactor-advisor.md +339 -29
- package/templates/.claude/commands/agent-creator.md +355 -0
- package/templates/.claude/commands/docs-creator.md +404 -163
- package/templates/.claude/commands/docs-refactor.md +400 -113
- package/templates/.claude/commands/execute.md +357 -185
- package/templates/.claude/commands/git-all.md +16 -70
- package/templates/.claude/commands/git-session.md +36 -68
- package/templates/.claude/commands/git.md +20 -69
- package/templates/.claude/commands/lint-fix.md +164 -107
- package/templates/.claude/commands/lint-init.md +142 -168
- package/templates/.claude/commands/plan.md +300 -84
- package/templates/.claude/commands/prd.md +613 -0
- package/templates/.claude/commands/pre-deploy.md +242 -0
- package/templates/.claude/commands/subagent-creator.md +118 -0
- package/templates/.claude/commands/version-update.md +45 -57
- package/templates/hono/CLAUDE.md +99 -54
- package/templates/hono/docs/guides/conventions.md +352 -0
- package/templates/hono/docs/guides/env-setup.md +347 -0
- package/templates/hono/docs/guides/getting-started.md +239 -0
- package/templates/hono/docs/library/hono/error-handling.md +20 -29
- package/templates/hono/docs/library/hono/index.md +25 -52
- package/templates/hono/docs/library/hono/middleware.md +16 -75
- package/templates/hono/docs/library/hono/rpc.md +7 -35
- package/templates/hono/docs/library/hono/validation.md +25 -45
- package/templates/hono/docs/library/t3-env/index.md +374 -0
- package/templates/npx/CLAUDE.md +165 -65
- package/templates/npx/docs/library/commander/index.md +10 -73
- package/templates/npx/docs/library/fs-extra/index.md +21 -113
- package/templates/npx/docs/library/prompts/index.md +30 -176
- package/templates/npx/docs/references/patterns.md +75 -48
- package/templates/tanstack-start/CLAUDE.md +101 -77
- package/templates/tanstack-start/docs/architecture.md +427 -0
- package/templates/tanstack-start/docs/design.md +558 -0
- package/templates/tanstack-start/docs/guides/conventions.md +132 -32
- package/templates/tanstack-start/docs/guides/env-setup.md +127 -62
- package/templates/tanstack-start/docs/guides/getting-started.md +81 -20
- package/templates/tanstack-start/docs/guides/hooks.md +241 -36
- package/templates/tanstack-start/docs/guides/routes.md +213 -61
- package/templates/tanstack-start/docs/guides/services.md +260 -24
- package/templates/tanstack-start/docs/library/better-auth/index.md +469 -16
- package/templates/tanstack-start/docs/library/t3-env/index.md +307 -0
- package/templates/tanstack-start/docs/library/tanstack-query/index.md +12 -21
- package/templates/tanstack-start/docs/library/tanstack-query/invalidation.md +22 -35
- package/templates/tanstack-start/docs/library/tanstack-query/optimistic-updates.md +7 -24
- package/templates/tanstack-start/docs/library/tanstack-query/use-mutation.md +26 -39
- package/templates/tanstack-start/docs/library/tanstack-query/use-query.md +23 -26
- package/templates/tanstack-start/docs/library/tanstack-router/error-handling.md +32 -147
- package/templates/tanstack-start/docs/library/tanstack-router/hooks.md +25 -167
- package/templates/tanstack-start/docs/library/tanstack-router/index.md +39 -74
- package/templates/tanstack-start/docs/library/tanstack-router/navigation.md +46 -116
- package/templates/tanstack-start/docs/library/tanstack-router/route-context.md +35 -154
- package/templates/tanstack-start/docs/library/tanstack-router/search-params.md +32 -171
- package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +7 -15
- package/templates/tanstack-start/docs/library/tanstack-start/routing.md +16 -23
- package/templates/tanstack-start/docs/library/zod/complex-types.md +12 -31
- package/templates/tanstack-start/docs/library/zod/index.md +18 -35
- package/templates/tanstack-start/docs/library/zod/transforms.md +11 -25
- package/templates/tanstack-start/docs/library/zod/validation.md +12 -34
- package/templates/.claude/agents/debug-detective.md +0 -37
- package/templates/.claude/agents/test-writer.md +0 -41
- package/templates/.claude/commands/feedback.md +0 -199
- package/templates/.claude/commands/ts-fix.md +0 -176
- package/templates/.claude/skills/command-creator/LICENSE.txt +0 -202
- package/templates/.claude/skills/command-creator/SKILL.md +0 -245
- package/templates/.claude/skills/command-creator/scripts/init_command.py +0 -244
- package/templates/.claude/skills/command-creator/scripts/package_command.py +0 -125
- package/templates/.claude/skills/command-creator/scripts/quick_validate.py +0 -143
- package/templates/.claude/skills/frontend-design/SKILL.md +0 -310
- package/templates/.claude/skills/frontend-design/references/animation-patterns.md +0 -446
- package/templates/.claude/skills/frontend-design/references/colors-2026.md +0 -244
- package/templates/.claude/skills/frontend-design/references/typography-2026.md +0 -302
- package/templates/.claude/skills/gemini-review/SKILL.md +0 -118
- package/templates/.claude/skills/gemini-review/references/checklists.md +0 -129
- package/templates/.claude/skills/gemini-review/references/prompt-templates.md +0 -274
- package/templates/.claude/skills/skill-creator/LICENSE.txt +0 -202
- package/templates/.claude/skills/skill-creator/SKILL.md +0 -184
- package/templates/.claude/skills/skill-creator/scripts/init_skill.py +0 -303
- package/templates/.claude/skills/skill-creator/scripts/package_skill.py +0 -110
- package/templates/.claude/skills/skill-creator/scripts/quick_validate.py +0 -65
- package/templates/hono/docs/library/ai-sdk/index.md +0 -190
- package/templates/hono/docs/library/ai-sdk/openrouter.md +0 -111
- package/templates/hono/docs/library/ai-sdk/providers.md +0 -102
- package/templates/hono/docs/library/ai-sdk/streaming.md +0 -146
- package/templates/hono/docs/library/ai-sdk/structured-output.md +0 -161
- package/templates/hono/docs/library/ai-sdk/tools.md +0 -144
- package/templates/hono/docs/library/drizzle/cloudflare-d1.md +0 -247
- package/templates/hono/docs/library/drizzle/config.md +0 -167
- package/templates/hono/docs/library/drizzle/index.md +0 -259
- package/templates/hono/docs/library/hono/env-setup.md +0 -169
- package/templates/hono/docs/library/pino/index.md +0 -146
- package/templates/tanstack-start/docs/architecture/architecture.md +0 -243
- package/templates/tanstack-start/docs/deployment/cloudflare.md +0 -132
- package/templates/tanstack-start/docs/deployment/index.md +0 -163
- package/templates/tanstack-start/docs/deployment/nitro.md +0 -110
- package/templates/tanstack-start/docs/deployment/railway.md +0 -147
- package/templates/tanstack-start/docs/deployment/vercel.md +0 -135
- package/templates/tanstack-start/docs/design/components.md +0 -175
- package/templates/tanstack-start/docs/design/index.md +0 -151
- package/templates/tanstack-start/docs/design/safe-area.md +0 -118
- package/templates/tanstack-start/docs/design/tailwind-setup.md +0 -156
- package/templates/tanstack-start/docs/library/ai-sdk/hooks.md +0 -472
- package/templates/tanstack-start/docs/library/ai-sdk/index.md +0 -264
- package/templates/tanstack-start/docs/library/ai-sdk/openrouter.md +0 -371
- package/templates/tanstack-start/docs/library/ai-sdk/providers.md +0 -403
- package/templates/tanstack-start/docs/library/ai-sdk/streaming.md +0 -320
- package/templates/tanstack-start/docs/library/ai-sdk/structured-output.md +0 -454
- package/templates/tanstack-start/docs/library/ai-sdk/tools.md +0 -473
- package/templates/tanstack-start/docs/library/better-auth/2fa.md +0 -48
- package/templates/tanstack-start/docs/library/better-auth/advanced.md +0 -55
- package/templates/tanstack-start/docs/library/better-auth/plugins.md +0 -34
- package/templates/tanstack-start/docs/library/better-auth/session.md +0 -47
- package/templates/tanstack-start/docs/library/better-auth/setup.md +0 -41
- package/templates/tanstack-start/docs/library/drizzle/cloudflare-d1.md +0 -147
- package/templates/tanstack-start/docs/library/drizzle/config.md +0 -118
- package/templates/tanstack-start/docs/library/drizzle/crud.md +0 -205
- package/templates/tanstack-start/docs/library/drizzle/index.md +0 -79
- package/templates/tanstack-start/docs/library/drizzle/relations.md +0 -202
- package/templates/tanstack-start/docs/library/drizzle/schema.md +0 -154
- package/templates/tanstack-start/docs/library/drizzle/setup.md +0 -96
- package/templates/tanstack-start/docs/library/drizzle/transactions.md +0 -127
- package/templates/tanstack-start/docs/library/pino/index.md +0 -320
- /package/templates/hono/docs/{architecture/architecture.md → architecture.md} +0 -0
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
# 환경 변수 설정
|
|
2
|
+
|
|
3
|
+
> Hono 환경 변수 관리 (Node.js, Cloudflare Workers)
|
|
4
|
+
|
|
5
|
+
<instructions>
|
|
6
|
+
@../library/t3-env/index.md
|
|
7
|
+
</instructions>
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<runtime_differences>
|
|
12
|
+
|
|
13
|
+
| 런타임 | 환경 변수 접근 | 용도 |
|
|
14
|
+
|--------|---------------|------|
|
|
15
|
+
| **Node.js** | `process.env.*` | 일반 서버 |
|
|
16
|
+
| **Cloudflare Workers** | `c.env.*` (Bindings) | Edge Runtime |
|
|
17
|
+
| **Deno** | `Deno.env.get()` | Deno Runtime |
|
|
18
|
+
| **Bun** | `process.env.*` | Bun Runtime |
|
|
19
|
+
|
|
20
|
+
</runtime_differences>
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
<file_structure>
|
|
25
|
+
|
|
26
|
+
## 환경 파일 구조
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
├── .env # 기본 (커밋 O)
|
|
30
|
+
├── .env.development # 개발 (커밋 O)
|
|
31
|
+
├── .env.production # 프로덕션 (커밋 O)
|
|
32
|
+
├── .env.local # 로컬 오버라이드 (커밋 X)
|
|
33
|
+
└── src/lib/env.ts # 검증 및 타입 (t3-env)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
| 우선순위 | 파일 | 설명 |
|
|
37
|
+
|----------|------|------|
|
|
38
|
+
| 1 | `.env.{mode}.local` | 최우선 (gitignore) |
|
|
39
|
+
| 2 | `.env.local` | 로컬 오버라이드 |
|
|
40
|
+
| 3 | `.env.{mode}` | 환경별 설정 |
|
|
41
|
+
| 4 | `.env` | 기본 설정 |
|
|
42
|
+
|
|
43
|
+
</file_structure>
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
<patterns>
|
|
48
|
+
|
|
49
|
+
## 환경 파일 예시
|
|
50
|
+
|
|
51
|
+
### .env.local (gitignore, 시크릿)
|
|
52
|
+
|
|
53
|
+
```env
|
|
54
|
+
DATABASE_URL=postgresql://user:password@localhost:5432/myapp
|
|
55
|
+
JWT_SECRET=your-super-secret-jwt-key-at-least-32-chars
|
|
56
|
+
OPENAI_API_KEY=sk-xxx
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### .env.development
|
|
60
|
+
|
|
61
|
+
```env
|
|
62
|
+
NODE_ENV=development
|
|
63
|
+
PORT=3000
|
|
64
|
+
LOG_LEVEL=debug
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### .env.production
|
|
68
|
+
|
|
69
|
+
```env
|
|
70
|
+
NODE_ENV=production
|
|
71
|
+
PORT=8080
|
|
72
|
+
LOG_LEVEL=info
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Node.js 환경 변수
|
|
76
|
+
|
|
77
|
+
### 타입 안전한 환경 변수 (t3-env)
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
// src/lib/env.ts
|
|
81
|
+
import { createEnv } from '@t3-oss/env-core'
|
|
82
|
+
import { z } from 'zod'
|
|
83
|
+
|
|
84
|
+
export const env = createEnv({
|
|
85
|
+
server: {
|
|
86
|
+
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
|
|
87
|
+
DATABASE_URL: z.string().url(),
|
|
88
|
+
JWT_SECRET: z.string().min(32),
|
|
89
|
+
OPENAI_API_KEY: z.string().optional(),
|
|
90
|
+
PORT: z.coerce.number().default(3000),
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
runtimeEnv: process.env,
|
|
94
|
+
})
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 사용 예시
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
// src/index.ts
|
|
101
|
+
import { Hono } from 'hono'
|
|
102
|
+
import { env } from './lib/env'
|
|
103
|
+
|
|
104
|
+
const app = new Hono()
|
|
105
|
+
|
|
106
|
+
app.get('/', (c) => {
|
|
107
|
+
return c.json({
|
|
108
|
+
env: env.NODE_ENV,
|
|
109
|
+
port: env.PORT,
|
|
110
|
+
})
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
export default {
|
|
114
|
+
port: env.PORT,
|
|
115
|
+
fetch: app.fetch,
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Cloudflare Workers 환경 변수
|
|
120
|
+
|
|
121
|
+
### Bindings 타입 정의
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
// src/types/index.ts
|
|
125
|
+
export type Bindings = {
|
|
126
|
+
DATABASE_URL: string
|
|
127
|
+
JWT_SECRET: string
|
|
128
|
+
OPENAI_API_KEY?: string
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### wrangler.toml
|
|
133
|
+
|
|
134
|
+
```toml
|
|
135
|
+
name = "my-hono-app"
|
|
136
|
+
main = "src/index.ts"
|
|
137
|
+
compatibility_date = "2024-01-01"
|
|
138
|
+
|
|
139
|
+
[vars]
|
|
140
|
+
NODE_ENV = "production"
|
|
141
|
+
|
|
142
|
+
# 시크릿은 wrangler secret put 명령어로 설정
|
|
143
|
+
# wrangler secret put DATABASE_URL
|
|
144
|
+
# wrangler secret put JWT_SECRET
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### 사용 예시
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
// src/index.ts
|
|
151
|
+
import { Hono } from 'hono'
|
|
152
|
+
import type { Bindings } from './types'
|
|
153
|
+
|
|
154
|
+
const app = new Hono<{ Bindings: Bindings }>()
|
|
155
|
+
|
|
156
|
+
app.get('/', (c) => {
|
|
157
|
+
// c.env를 통해 환경 변수 접근
|
|
158
|
+
const dbUrl = c.env.DATABASE_URL
|
|
159
|
+
const jwtSecret = c.env.JWT_SECRET
|
|
160
|
+
|
|
161
|
+
return c.json({
|
|
162
|
+
hasDb: !!dbUrl,
|
|
163
|
+
hasJwt: !!jwtSecret,
|
|
164
|
+
})
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
export default app
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### 미들웨어에서 사용
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
// src/middleware/auth.ts
|
|
174
|
+
import { createMiddleware } from 'hono/factory'
|
|
175
|
+
import { HTTPException } from 'hono/http-exception'
|
|
176
|
+
import type { Bindings } from '@/types'
|
|
177
|
+
|
|
178
|
+
type Variables = {
|
|
179
|
+
userId: string
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export const authMiddleware = createMiddleware<{
|
|
183
|
+
Bindings: Bindings
|
|
184
|
+
Variables: Variables
|
|
185
|
+
}>(async (c, next) => {
|
|
186
|
+
const token = c.req.header('Authorization')?.replace('Bearer ', '')
|
|
187
|
+
if (!token) throw new HTTPException(401, { message: 'Unauthorized' })
|
|
188
|
+
|
|
189
|
+
// JWT Secret 사용
|
|
190
|
+
const jwtSecret = c.env.JWT_SECRET
|
|
191
|
+
// JWT 검증 로직...
|
|
192
|
+
|
|
193
|
+
c.set('userId', 'user-id')
|
|
194
|
+
await next()
|
|
195
|
+
})
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Cloudflare Workers 시크릿 설정
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
# 시크릿 추가
|
|
202
|
+
wrangler secret put DATABASE_URL
|
|
203
|
+
wrangler secret put JWT_SECRET
|
|
204
|
+
|
|
205
|
+
# 시크릿 목록 확인
|
|
206
|
+
wrangler secret list
|
|
207
|
+
|
|
208
|
+
# 시크릿 삭제
|
|
209
|
+
wrangler secret delete DATABASE_URL
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
</patterns>
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
<gitignore>
|
|
217
|
+
|
|
218
|
+
## .gitignore
|
|
219
|
+
|
|
220
|
+
```gitignore
|
|
221
|
+
# 시크릿 포함 (절대 커밋 X)
|
|
222
|
+
.env.local
|
|
223
|
+
.env.*.local
|
|
224
|
+
|
|
225
|
+
# Cloudflare Workers
|
|
226
|
+
.dev.vars
|
|
227
|
+
|
|
228
|
+
# 공개 설정 (커밋 O)
|
|
229
|
+
!.env
|
|
230
|
+
!.env.development
|
|
231
|
+
!.env.production
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
</gitignore>
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
<typescript_types>
|
|
239
|
+
|
|
240
|
+
## TypeScript 타입
|
|
241
|
+
|
|
242
|
+
### Node.js
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
// src/env.d.ts
|
|
246
|
+
declare global {
|
|
247
|
+
namespace NodeJS {
|
|
248
|
+
interface ProcessEnv {
|
|
249
|
+
NODE_ENV: 'development' | 'production' | 'test'
|
|
250
|
+
DATABASE_URL: string
|
|
251
|
+
JWT_SECRET: string
|
|
252
|
+
OPENAI_API_KEY?: string
|
|
253
|
+
PORT?: string
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export {}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Cloudflare Workers
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
// src/types/index.ts
|
|
265
|
+
export type Bindings = {
|
|
266
|
+
// Database
|
|
267
|
+
DATABASE_URL: string
|
|
268
|
+
|
|
269
|
+
// Auth
|
|
270
|
+
JWT_SECRET: string
|
|
271
|
+
|
|
272
|
+
// External APIs
|
|
273
|
+
OPENAI_API_KEY?: string
|
|
274
|
+
|
|
275
|
+
// KV Namespaces (Cloudflare)
|
|
276
|
+
MY_KV: KVNamespace
|
|
277
|
+
|
|
278
|
+
// D1 Database (Cloudflare)
|
|
279
|
+
DB: D1Database
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
</typescript_types>
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
<best_practices>
|
|
288
|
+
|
|
289
|
+
| 원칙 | 설명 |
|
|
290
|
+
|------|------|
|
|
291
|
+
| **시크릿 분리** | `.env.local`에만 시크릿 저장, 커밋 금지 |
|
|
292
|
+
| **타입 안전성** | t3-env 또는 Zod로 검증 |
|
|
293
|
+
| **기본값** | `.env`에 안전한 기본값 설정 |
|
|
294
|
+
| **문서화** | `.env.example` 파일로 필수 변수 목록 제공 |
|
|
295
|
+
| **런타임별 차이** | Node.js는 `process.env`, Cloudflare는 `c.env` |
|
|
296
|
+
|
|
297
|
+
</best_practices>
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
<cloudflare_specific>
|
|
302
|
+
|
|
303
|
+
## Cloudflare Workers 추가 기능
|
|
304
|
+
|
|
305
|
+
### KV Namespace
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
// wrangler.toml
|
|
309
|
+
[[kv_namespaces]]
|
|
310
|
+
binding = "MY_KV"
|
|
311
|
+
id = "your-kv-id"
|
|
312
|
+
|
|
313
|
+
// 사용
|
|
314
|
+
app.get('/cache/:key', async (c) => {
|
|
315
|
+
const key = c.req.param('key')
|
|
316
|
+
const value = await c.env.MY_KV.get(key)
|
|
317
|
+
return c.json({ key, value })
|
|
318
|
+
})
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### D1 Database
|
|
322
|
+
|
|
323
|
+
```typescript
|
|
324
|
+
// wrangler.toml
|
|
325
|
+
[[d1_databases]]
|
|
326
|
+
binding = "DB"
|
|
327
|
+
database_name = "my-database"
|
|
328
|
+
database_id = "your-db-id"
|
|
329
|
+
|
|
330
|
+
// 사용
|
|
331
|
+
app.get('/users', async (c) => {
|
|
332
|
+
const { results } = await c.env.DB.prepare('SELECT * FROM users').all()
|
|
333
|
+
return c.json({ users: results })
|
|
334
|
+
})
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
</cloudflare_specific>
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
<sources>
|
|
342
|
+
|
|
343
|
+
- [Hono Environment Variables](https://hono.dev/guides/env)
|
|
344
|
+
- [Cloudflare Workers Environment Variables](https://developers.cloudflare.com/workers/configuration/environment-variables/)
|
|
345
|
+
- [t3-env Documentation](https://env.t3.gg/docs/introduction)
|
|
346
|
+
|
|
347
|
+
</sources>
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# Getting Started
|
|
2
|
+
|
|
3
|
+
> Hono 프로젝트 빠른 시작
|
|
4
|
+
|
|
5
|
+
<instructions>
|
|
6
|
+
@conventions.md
|
|
7
|
+
@env-setup.md
|
|
8
|
+
@../library/hono/index.md
|
|
9
|
+
</instructions>
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
<prerequisites>
|
|
14
|
+
|
|
15
|
+
| 요구사항 | 버전 |
|
|
16
|
+
|----------|------|
|
|
17
|
+
| Node.js | 18+ |
|
|
18
|
+
| 패키지 관리자 | npm / yarn / pnpm |
|
|
19
|
+
|
|
20
|
+
</prerequisites>
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
<installation>
|
|
25
|
+
|
|
26
|
+
## 프로젝트 생성
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# npm
|
|
30
|
+
npm create hono@latest my-app
|
|
31
|
+
|
|
32
|
+
# 템플릿 선택
|
|
33
|
+
? Which template do you want to use?
|
|
34
|
+
❯ cloudflare-workers
|
|
35
|
+
nodejs
|
|
36
|
+
bun
|
|
37
|
+
deno
|
|
38
|
+
|
|
39
|
+
cd my-app
|
|
40
|
+
npm install
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 필수 패키지
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Validation (Zod 4.x)
|
|
47
|
+
npm install zod @hono/zod-validator
|
|
48
|
+
|
|
49
|
+
# Database (Prisma 7.x)
|
|
50
|
+
npm install @prisma/client@7
|
|
51
|
+
npm install -D prisma@7
|
|
52
|
+
|
|
53
|
+
# Environment Variables
|
|
54
|
+
npm install @t3-oss/env-core
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
</installation>
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
<project_setup>
|
|
62
|
+
|
|
63
|
+
## 프로젝트 구조
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
src/
|
|
67
|
+
├── index.ts # App 진입점
|
|
68
|
+
├── routes/
|
|
69
|
+
│ ├── index.ts # Root routes
|
|
70
|
+
│ ├── users.ts # /users/*
|
|
71
|
+
│ └── posts.ts # /posts/*
|
|
72
|
+
├── middleware/
|
|
73
|
+
│ ├── auth.ts
|
|
74
|
+
│ └── logger.ts
|
|
75
|
+
├── services/
|
|
76
|
+
│ ├── user.ts
|
|
77
|
+
│ └── post.ts
|
|
78
|
+
├── lib/
|
|
79
|
+
│ ├── prisma.ts
|
|
80
|
+
│ └── env.ts
|
|
81
|
+
└── types/
|
|
82
|
+
└── index.ts
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## App 설정
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
// src/index.ts
|
|
89
|
+
import { Hono } from 'hono'
|
|
90
|
+
import { cors } from 'hono/cors'
|
|
91
|
+
import { logger } from 'hono/logger'
|
|
92
|
+
import { HTTPException } from 'hono/http-exception'
|
|
93
|
+
|
|
94
|
+
import users from './routes/users'
|
|
95
|
+
import posts from './routes/posts'
|
|
96
|
+
|
|
97
|
+
type Bindings = {
|
|
98
|
+
DATABASE_URL: string
|
|
99
|
+
JWT_SECRET: string
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const app = new Hono<{ Bindings: Bindings }>()
|
|
103
|
+
|
|
104
|
+
// 미들웨어
|
|
105
|
+
app.use('*', logger())
|
|
106
|
+
app.use('*', cors())
|
|
107
|
+
|
|
108
|
+
// 라우트
|
|
109
|
+
app.route('/users', users)
|
|
110
|
+
app.route('/posts', posts)
|
|
111
|
+
|
|
112
|
+
// 에러 핸들러
|
|
113
|
+
app.onError((err, c) => {
|
|
114
|
+
if (err instanceof HTTPException) {
|
|
115
|
+
return c.json({ error: err.message }, err.status)
|
|
116
|
+
}
|
|
117
|
+
console.error(err)
|
|
118
|
+
return c.json({ error: 'Internal Server Error' }, 500)
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
app.notFound((c) => c.json({ error: 'Not Found' }, 404))
|
|
122
|
+
|
|
123
|
+
export default app
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## 라우트 예시
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
// src/routes/users.ts
|
|
130
|
+
import { Hono } from 'hono'
|
|
131
|
+
import { zValidator } from '@hono/zod-validator'
|
|
132
|
+
import { z } from 'zod'
|
|
133
|
+
import { HTTPException } from 'hono/http-exception'
|
|
134
|
+
|
|
135
|
+
const users = new Hono()
|
|
136
|
+
|
|
137
|
+
// GET /users
|
|
138
|
+
users.get('/', async (c) => {
|
|
139
|
+
const users = [
|
|
140
|
+
{ id: '1', name: 'Alice' },
|
|
141
|
+
{ id: '2', name: 'Bob' },
|
|
142
|
+
]
|
|
143
|
+
return c.json({ users })
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
// GET /users/:id
|
|
147
|
+
users.get('/:id', async (c) => {
|
|
148
|
+
const id = c.req.param('id')
|
|
149
|
+
const user = { id, name: 'Alice' }
|
|
150
|
+
|
|
151
|
+
if (!user) {
|
|
152
|
+
throw new HTTPException(404, { message: 'User not found' })
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return c.json({ user })
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
// POST /users
|
|
159
|
+
const createUserSchema = z.object({
|
|
160
|
+
name: z.string().min(1).trim(),
|
|
161
|
+
email: z.email(),
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
users.post('/', zValidator('json', createUserSchema), async (c) => {
|
|
165
|
+
const data = c.req.valid('json')
|
|
166
|
+
const user = { id: '3', ...data }
|
|
167
|
+
|
|
168
|
+
return c.json({ user }, 201)
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
export default users
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## 미들웨어 예시
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
// src/middleware/auth.ts
|
|
178
|
+
import { createMiddleware } from 'hono/factory'
|
|
179
|
+
import { HTTPException } from 'hono/http-exception'
|
|
180
|
+
|
|
181
|
+
type Variables = {
|
|
182
|
+
userId: string
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export const authMiddleware = createMiddleware<{ Variables: Variables }>(
|
|
186
|
+
async (c, next) => {
|
|
187
|
+
const token = c.req.header('Authorization')?.replace('Bearer ', '')
|
|
188
|
+
|
|
189
|
+
if (!token) {
|
|
190
|
+
throw new HTTPException(401, { message: 'Unauthorized' })
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// JWT 검증 로직
|
|
194
|
+
// const decoded = await verifyJWT(token)
|
|
195
|
+
|
|
196
|
+
c.set('userId', 'user-id')
|
|
197
|
+
await next()
|
|
198
|
+
}
|
|
199
|
+
)
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
</project_setup>
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
<commands>
|
|
207
|
+
|
|
208
|
+
| Command | Description |
|
|
209
|
+
|---------|-------------|
|
|
210
|
+
| `npm run dev` | 개발 서버 시작 |
|
|
211
|
+
| `npm run build` | 프로덕션 빌드 |
|
|
212
|
+
| `npm start` | 프로덕션 서버 실행 |
|
|
213
|
+
| `npm run deploy` | 배포 (Cloudflare Workers 등) |
|
|
214
|
+
|
|
215
|
+
</commands>
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
<next_steps>
|
|
220
|
+
|
|
221
|
+
| 문서 | 내용 |
|
|
222
|
+
|------|------|
|
|
223
|
+
| [conventions.md](./conventions.md) | 코드 컨벤션, 파일명 규칙 |
|
|
224
|
+
| [env-setup.md](./env-setup.md) | 환경 변수 설정 |
|
|
225
|
+
| [../library/hono/](../library/hono/) | Hono API 상세 가이드 |
|
|
226
|
+
| [../library/prisma/](../library/prisma/) | Prisma ORM 사용법 |
|
|
227
|
+
| [../deployment/](../deployment/) | 배포 가이드 |
|
|
228
|
+
|
|
229
|
+
</next_steps>
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
<sources>
|
|
234
|
+
|
|
235
|
+
- [Hono Documentation](https://hono.dev/)
|
|
236
|
+
- [Hono Getting Started](https://hono.dev/getting-started/basic)
|
|
237
|
+
- [Hono Examples](https://github.com/honojs/hono/tree/main/examples)
|
|
238
|
+
|
|
239
|
+
</sources>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Hono 에러 처리
|
|
2
2
|
|
|
3
|
-
> HTTPException과 onError
|
|
3
|
+
> HTTPException과 onError로 체계적 에러 관리
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
<patterns>
|
|
6
6
|
|
|
7
7
|
## HTTPException
|
|
8
8
|
|
|
@@ -20,21 +20,7 @@ app.get('/users/:id', async (c) => {
|
|
|
20
20
|
})
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
```typescript
|
|
26
|
-
throw new HTTPException(400, { message: 'Invalid input' }) // Bad Request
|
|
27
|
-
throw new HTTPException(401, { message: 'Unauthorized' }) // 인증 필요
|
|
28
|
-
throw new HTTPException(403, { message: 'Access denied' }) // 권한 없음
|
|
29
|
-
throw new HTTPException(404, { message: 'Not found' }) // 리소스 없음
|
|
30
|
-
throw new HTTPException(409, { message: 'Already exists' }) // 충돌
|
|
31
|
-
throw new HTTPException(422, { message: 'Validation failed' }) // 검증 실패
|
|
32
|
-
throw new HTTPException(429, { message: 'Rate limit exceeded' })// 요청 제한
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
## 글로벌 에러 핸들러
|
|
23
|
+
## 글로벌 핸들러
|
|
38
24
|
|
|
39
25
|
```typescript
|
|
40
26
|
import { Hono } from 'hono'
|
|
@@ -57,9 +43,7 @@ app.notFound((c) => {
|
|
|
57
43
|
})
|
|
58
44
|
```
|
|
59
45
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
## 상세 에러 응답
|
|
46
|
+
## 상세 응답
|
|
63
47
|
|
|
64
48
|
```typescript
|
|
65
49
|
app.onError((err, c) => {
|
|
@@ -85,13 +69,10 @@ app.onError((err, c) => {
|
|
|
85
69
|
})
|
|
86
70
|
```
|
|
87
71
|
|
|
88
|
-
---
|
|
89
|
-
|
|
90
72
|
## 커스텀 에러 클래스
|
|
91
73
|
|
|
92
|
-
### lib/errors.ts
|
|
93
|
-
|
|
94
74
|
```typescript
|
|
75
|
+
// lib/errors.ts
|
|
95
76
|
import { HTTPException } from 'hono/http-exception'
|
|
96
77
|
|
|
97
78
|
export class NotFoundError extends HTTPException {
|
|
@@ -113,9 +94,8 @@ export class ConflictError extends HTTPException {
|
|
|
113
94
|
}
|
|
114
95
|
```
|
|
115
96
|
|
|
116
|
-
### 사용
|
|
117
|
-
|
|
118
97
|
```typescript
|
|
98
|
+
// 사용
|
|
119
99
|
import { NotFoundError, ConflictError } from '@/lib/errors'
|
|
120
100
|
|
|
121
101
|
app.get('/users/:id', async (c) => {
|
|
@@ -131,9 +111,20 @@ app.post('/users', async (c) => {
|
|
|
131
111
|
})
|
|
132
112
|
```
|
|
133
113
|
|
|
114
|
+
</patterns>
|
|
115
|
+
|
|
134
116
|
---
|
|
135
117
|
|
|
136
|
-
|
|
118
|
+
<status_codes>
|
|
119
|
+
|
|
120
|
+
| 코드 | 사용 |
|
|
121
|
+
|-----|------|
|
|
122
|
+
| 400 | Invalid input |
|
|
123
|
+
| 401 | Unauthorized (인증 필요) |
|
|
124
|
+
| 403 | Access denied (권한 없음) |
|
|
125
|
+
| 404 | Not found |
|
|
126
|
+
| 409 | Already exists (충돌) |
|
|
127
|
+
| 422 | Validation failed |
|
|
128
|
+
| 429 | Rate limit exceeded |
|
|
137
129
|
|
|
138
|
-
|
|
139
|
-
- [미들웨어](./middleware.md)
|
|
130
|
+
</status_codes>
|