@kood/claude-code 0.5.4 → 0.5.6
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 +6 -2
- package/package.json +1 -1
- package/templates/.claude/agents/document-writer.md +2 -2
- package/templates/.claude/skills/docs-creator/SKILL.md +2 -2
- package/templates/.claude/skills/docs-refactor/SKILL.md +1 -1
- package/templates/.claude/skills/plan/SKILL.md +15 -15
- package/templates/.claude/skills/ralph/SKILL.md +425 -72
- package/templates/hono/CLAUDE.md +28 -28
- package/templates/hono/docs/architecture.md +24 -24
- package/templates/hono/docs/deployment/cloudflare.md +18 -18
- package/templates/hono/docs/deployment/docker.md +13 -13
- package/templates/hono/docs/deployment/index.md +19 -19
- package/templates/hono/docs/deployment/railway.md +32 -32
- package/templates/hono/docs/deployment/vercel.md +29 -29
- package/templates/hono/docs/guides/conventions.md +57 -57
- package/templates/hono/docs/guides/env-setup.md +47 -47
- package/templates/hono/docs/guides/getting-started.md +27 -27
- package/templates/hono/docs/library/hono/error-handling.md +11 -11
- package/templates/hono/docs/library/hono/index.md +4 -4
- package/templates/hono/docs/library/hono/middleware.md +18 -18
- package/templates/hono/docs/library/hono/rpc.md +7 -7
- package/templates/hono/docs/library/hono/validation.md +6 -6
- package/templates/hono/docs/library/prisma/cloudflare-d1.md +29 -29
- package/templates/hono/docs/library/prisma/config.md +16 -16
- package/templates/hono/docs/library/prisma/index.md +32 -32
- package/templates/hono/docs/library/t3-env/index.md +22 -22
- package/templates/hono/docs/library/zod/index.md +31 -31
- package/templates/nextjs/CLAUDE.md +54 -54
- package/templates/nextjs/docs/architecture.md +146 -146
- package/templates/nextjs/docs/design.md +183 -183
- package/templates/nextjs/docs/guides/conventions.md +86 -86
- package/templates/nextjs/docs/guides/getting-started.md +28 -28
- package/templates/nextjs/docs/guides/routes.md +32 -32
- package/templates/nextjs/docs/library/better-auth/index.md +70 -70
- package/templates/nextjs/docs/library/nextjs/app-router.md +43 -43
- package/templates/nextjs/docs/library/nextjs/caching.md +73 -73
- package/templates/nextjs/docs/library/nextjs/index.md +51 -51
- package/templates/nextjs/docs/library/nextjs/middleware.md +41 -41
- package/templates/nextjs/docs/library/nextjs/route-handlers.md +31 -31
- package/templates/nextjs/docs/library/nextjs/server-actions.md +34 -34
- package/templates/nextjs/docs/library/prisma/cloudflare-d1.md +20 -20
- package/templates/nextjs/docs/library/prisma/config.md +18 -18
- package/templates/nextjs/docs/library/prisma/crud.md +17 -17
- package/templates/nextjs/docs/library/prisma/index.md +18 -18
- package/templates/nextjs/docs/library/prisma/relations.md +16 -16
- package/templates/nextjs/docs/library/prisma/schema.md +23 -23
- package/templates/nextjs/docs/library/prisma/setup.md +6 -6
- package/templates/nextjs/docs/library/prisma/transactions.md +10 -10
- package/templates/nextjs/docs/library/tanstack-query/index.md +6 -6
- package/templates/nextjs/docs/library/tanstack-query/invalidation.md +20 -20
- package/templates/nextjs/docs/library/tanstack-query/optimistic-updates.md +4 -4
- package/templates/nextjs/docs/library/tanstack-query/use-mutation.md +15 -15
- package/templates/nextjs/docs/library/tanstack-query/use-query.md +22 -22
- package/templates/nextjs/docs/library/zod/complex-types.md +11 -11
- package/templates/nextjs/docs/library/zod/index.md +8 -8
- package/templates/nextjs/docs/library/zod/transforms.md +11 -11
- package/templates/nextjs/docs/library/zod/validation.md +9 -9
- package/templates/npx/CLAUDE.md +38 -38
- package/templates/npx/docs/library/commander/index.md +12 -12
- package/templates/npx/docs/library/fs-extra/index.md +9 -9
- package/templates/npx/docs/library/prompts/index.md +3 -3
- package/templates/npx/docs/references/patterns.md +12 -12
- package/templates/tanstack-start/CLAUDE.md +54 -54
- package/templates/tanstack-start/docs/architecture.md +128 -128
- package/templates/tanstack-start/docs/design.md +169 -169
- package/templates/tanstack-start/docs/guides/conventions.md +43 -43
- package/templates/tanstack-start/docs/guides/env-setup.md +35 -35
- package/templates/tanstack-start/docs/guides/getting-started.md +19 -19
- package/templates/tanstack-start/docs/guides/hooks.md +45 -45
- package/templates/tanstack-start/docs/guides/routes.md +54 -54
- package/templates/tanstack-start/docs/guides/services.md +45 -45
- package/templates/tanstack-start/docs/library/prisma/cloudflare-d1.md +19 -19
- package/templates/tanstack-start/docs/library/prisma/config.md +16 -16
- package/templates/tanstack-start/docs/library/prisma/crud.md +17 -17
- package/templates/tanstack-start/docs/library/prisma/relations.md +16 -16
- package/templates/tanstack-start/docs/library/prisma/schema.md +23 -23
- package/templates/tanstack-start/docs/library/prisma/setup.md +6 -6
- package/templates/tanstack-start/docs/library/prisma/transactions.md +10 -10
- package/templates/tanstack-start/docs/library/tanstack-query/invalidation.md +19 -19
- package/templates/tanstack-start/docs/library/tanstack-query/optimistic-updates.md +4 -4
- package/templates/tanstack-start/docs/library/tanstack-query/use-mutation.md +14 -14
- package/templates/tanstack-start/docs/library/tanstack-query/use-query.md +21 -21
- package/templates/tanstack-start/docs/library/tanstack-router/error-handling.md +9 -9
- package/templates/tanstack-start/docs/library/tanstack-router/hooks.md +11 -11
- package/templates/tanstack-start/docs/library/tanstack-router/navigation.md +17 -17
- package/templates/tanstack-start/docs/library/tanstack-router/route-context.md +5 -5
- package/templates/tanstack-start/docs/library/tanstack-router/search-params.md +10 -10
- package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +8 -8
- package/templates/tanstack-start/docs/library/tanstack-start/middleware.md +9 -9
- package/templates/tanstack-start/docs/library/tanstack-start/routing.md +6 -6
- package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +18 -18
- package/templates/tanstack-start/docs/library/tanstack-start/setup.md +4 -4
- package/templates/tanstack-start/docs/library/zod/complex-types.md +11 -11
- package/templates/tanstack-start/docs/library/zod/transforms.md +11 -11
- package/templates/tanstack-start/docs/library/zod/validation.md +9 -9
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Getting Started
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Hono 프로젝트 빠른 시작
|
|
4
4
|
|
|
5
5
|
<instructions>
|
|
6
6
|
@conventions.md
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
|
|
13
13
|
<prerequisites>
|
|
14
14
|
|
|
15
|
-
|
|
|
16
|
-
|
|
15
|
+
| 요구사항 | 버전 |
|
|
16
|
+
|----------|------|
|
|
17
17
|
| Node.js | 18+ |
|
|
18
|
-
|
|
|
18
|
+
| 패키지 관리자 | npm / yarn / pnpm |
|
|
19
19
|
|
|
20
20
|
</prerequisites>
|
|
21
21
|
|
|
@@ -23,13 +23,13 @@
|
|
|
23
23
|
|
|
24
24
|
<installation>
|
|
25
25
|
|
|
26
|
-
##
|
|
26
|
+
## 프로젝트 생성
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
29
|
# npm
|
|
30
30
|
npm create hono@latest my-app
|
|
31
31
|
|
|
32
|
-
#
|
|
32
|
+
# 템플릿 선택
|
|
33
33
|
? Which template do you want to use?
|
|
34
34
|
❯ cloudflare-workers
|
|
35
35
|
nodejs
|
|
@@ -40,7 +40,7 @@ cd my-app
|
|
|
40
40
|
npm install
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
##
|
|
43
|
+
## 필수 패키지
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
46
|
# Validation (Zod 4.x)
|
|
@@ -60,11 +60,11 @@ npm install @t3-oss/env-core
|
|
|
60
60
|
|
|
61
61
|
<project_setup>
|
|
62
62
|
|
|
63
|
-
##
|
|
63
|
+
## 프로젝트 구조
|
|
64
64
|
|
|
65
65
|
```
|
|
66
66
|
src/
|
|
67
|
-
├── index.ts # App
|
|
67
|
+
├── index.ts # App 진입점
|
|
68
68
|
├── routes/
|
|
69
69
|
│ ├── index.ts # Root routes
|
|
70
70
|
│ ├── users.ts # /users/*
|
|
@@ -82,7 +82,7 @@ src/
|
|
|
82
82
|
└── index.ts
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
## App
|
|
85
|
+
## App 설정
|
|
86
86
|
|
|
87
87
|
```typescript
|
|
88
88
|
// src/index.ts
|
|
@@ -101,15 +101,15 @@ type Bindings = {
|
|
|
101
101
|
|
|
102
102
|
const app = new Hono<{ Bindings: Bindings }>()
|
|
103
103
|
|
|
104
|
-
//
|
|
104
|
+
// 미들웨어
|
|
105
105
|
app.use('*', logger())
|
|
106
106
|
app.use('*', cors())
|
|
107
107
|
|
|
108
|
-
//
|
|
108
|
+
// 라우트
|
|
109
109
|
app.route('/users', users)
|
|
110
110
|
app.route('/posts', posts)
|
|
111
111
|
|
|
112
|
-
//
|
|
112
|
+
// 에러 핸들러
|
|
113
113
|
app.onError((err, c) => {
|
|
114
114
|
if (err instanceof HTTPException) {
|
|
115
115
|
return c.json({ error: err.message }, err.status)
|
|
@@ -123,7 +123,7 @@ app.notFound((c) => c.json({ error: 'Not Found' }, 404))
|
|
|
123
123
|
export default app
|
|
124
124
|
```
|
|
125
125
|
|
|
126
|
-
##
|
|
126
|
+
## 라우트 예시
|
|
127
127
|
|
|
128
128
|
```typescript
|
|
129
129
|
// src/routes/users.ts
|
|
@@ -171,7 +171,7 @@ users.post('/', zValidator('json', createUserSchema), async (c) => {
|
|
|
171
171
|
export default users
|
|
172
172
|
```
|
|
173
173
|
|
|
174
|
-
##
|
|
174
|
+
## 미들웨어 예시
|
|
175
175
|
|
|
176
176
|
```typescript
|
|
177
177
|
// src/middleware/auth.ts
|
|
@@ -190,7 +190,7 @@ export const authMiddleware = createMiddleware<{ Variables: Variables }>(
|
|
|
190
190
|
throw new HTTPException(401, { message: 'Unauthorized' })
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
-
// JWT
|
|
193
|
+
// JWT 검증 로직
|
|
194
194
|
// const decoded = await verifyJWT(token)
|
|
195
195
|
|
|
196
196
|
c.set('userId', 'user-id')
|
|
@@ -207,10 +207,10 @@ export const authMiddleware = createMiddleware<{ Variables: Variables }>(
|
|
|
207
207
|
|
|
208
208
|
| Command | Description |
|
|
209
209
|
|---------|-------------|
|
|
210
|
-
| `npm run dev` |
|
|
211
|
-
| `npm run build` |
|
|
212
|
-
| `npm start` |
|
|
213
|
-
| `npm run deploy` |
|
|
210
|
+
| `npm run dev` | 개발 서버 시작 |
|
|
211
|
+
| `npm run build` | 프로덕션 빌드 |
|
|
212
|
+
| `npm start` | 프로덕션 서버 실행 |
|
|
213
|
+
| `npm run deploy` | 배포 (Cloudflare Workers 등) |
|
|
214
214
|
|
|
215
215
|
</commands>
|
|
216
216
|
|
|
@@ -218,13 +218,13 @@ export const authMiddleware = createMiddleware<{ Variables: Variables }>(
|
|
|
218
218
|
|
|
219
219
|
<next_steps>
|
|
220
220
|
|
|
221
|
-
|
|
|
222
|
-
|
|
223
|
-
| [conventions.md](./conventions.md) |
|
|
224
|
-
| [env-setup.md](./env-setup.md) |
|
|
225
|
-
| [../library/hono/](../library/hono/) |
|
|
226
|
-
| [../library/prisma/](../library/prisma/) | Prisma ORM
|
|
227
|
-
| [../deployment/](../deployment/) |
|
|
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
228
|
|
|
229
229
|
</next_steps>
|
|
230
230
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# Hono
|
|
1
|
+
# Hono 에러 처리
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> HTTPException과 onError로 체계적 에러 관리
|
|
4
4
|
|
|
5
5
|
<patterns>
|
|
6
6
|
|
|
@@ -20,7 +20,7 @@ app.get('/users/:id', async (c) => {
|
|
|
20
20
|
})
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
##
|
|
23
|
+
## 글로벌 핸들러
|
|
24
24
|
|
|
25
25
|
```typescript
|
|
26
26
|
import { Hono } from 'hono'
|
|
@@ -43,7 +43,7 @@ app.notFound((c) => {
|
|
|
43
43
|
})
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
##
|
|
46
|
+
## 상세 응답
|
|
47
47
|
|
|
48
48
|
```typescript
|
|
49
49
|
app.onError((err, c) => {
|
|
@@ -69,7 +69,7 @@ app.onError((err, c) => {
|
|
|
69
69
|
})
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
##
|
|
72
|
+
## 커스텀 에러 클래스
|
|
73
73
|
|
|
74
74
|
```typescript
|
|
75
75
|
// lib/errors.ts
|
|
@@ -95,7 +95,7 @@ export class ConflictError extends HTTPException {
|
|
|
95
95
|
```
|
|
96
96
|
|
|
97
97
|
```typescript
|
|
98
|
-
//
|
|
98
|
+
// 사용
|
|
99
99
|
import { NotFoundError, ConflictError } from '@/lib/errors'
|
|
100
100
|
|
|
101
101
|
app.get('/users/:id', async (c) => {
|
|
@@ -117,13 +117,13 @@ app.post('/users', async (c) => {
|
|
|
117
117
|
|
|
118
118
|
<status_codes>
|
|
119
119
|
|
|
120
|
-
|
|
|
121
|
-
|
|
120
|
+
| 코드 | 사용 |
|
|
121
|
+
|-----|------|
|
|
122
122
|
| 400 | Invalid input |
|
|
123
|
-
| 401 | Unauthorized (
|
|
124
|
-
| 403 | Access denied (
|
|
123
|
+
| 401 | Unauthorized (인증 필요) |
|
|
124
|
+
| 403 | Access denied (권한 없음) |
|
|
125
125
|
| 404 | Not found |
|
|
126
|
-
| 409 | Already exists (
|
|
126
|
+
| 409 | Already exists (충돌) |
|
|
127
127
|
| 422 | Validation failed |
|
|
128
128
|
| 429 | Rate limit exceeded |
|
|
129
129
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Hono
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Web Standards 기반 초경량 프레임워크
|
|
4
4
|
|
|
5
5
|
<references>
|
|
6
6
|
@middleware.md
|
|
@@ -21,7 +21,7 @@ npm install hono
|
|
|
21
21
|
|
|
22
22
|
<quick_patterns>
|
|
23
23
|
|
|
24
|
-
##
|
|
24
|
+
## 라우트
|
|
25
25
|
|
|
26
26
|
```typescript
|
|
27
27
|
import { Hono } from 'hono'
|
|
@@ -39,7 +39,7 @@ app.get('/posts/:postId/comments/:commentId', (c) => {
|
|
|
39
39
|
export default app
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
##
|
|
42
|
+
## 라우트 그룹
|
|
43
43
|
|
|
44
44
|
```typescript
|
|
45
45
|
const users = new Hono()
|
|
@@ -99,7 +99,7 @@ type Variables = {
|
|
|
99
99
|
|
|
100
100
|
const app = new Hono<{ Bindings: Bindings; Variables: Variables }>()
|
|
101
101
|
|
|
102
|
-
//
|
|
102
|
+
// 환경 변수
|
|
103
103
|
app.get('/', (c) => {
|
|
104
104
|
const dbUrl = c.env.DATABASE_URL
|
|
105
105
|
return c.json({ connected: true })
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# Hono
|
|
1
|
+
# Hono 미들웨어
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> 요청/응답 처리 파이프라인
|
|
4
4
|
|
|
5
5
|
<patterns>
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## 기본 사용법
|
|
8
8
|
|
|
9
9
|
```typescript
|
|
10
10
|
import { Hono } from 'hono'
|
|
@@ -13,25 +13,25 @@ import { cors } from 'hono/cors'
|
|
|
13
13
|
|
|
14
14
|
const app = new Hono()
|
|
15
15
|
|
|
16
|
-
app.use(logger()) //
|
|
17
|
-
app.use('/api/*', cors()) //
|
|
16
|
+
app.use(logger()) // 모든 라우트
|
|
17
|
+
app.use('/api/*', cors()) // 특정 경로
|
|
18
18
|
|
|
19
|
-
//
|
|
19
|
+
// 실행 순서
|
|
20
20
|
app.use(async (c, next) => {
|
|
21
|
-
console.log('1.
|
|
21
|
+
console.log('1. 요청 전')
|
|
22
22
|
await next()
|
|
23
|
-
console.log('4.
|
|
23
|
+
console.log('4. 응답 후')
|
|
24
24
|
})
|
|
25
25
|
|
|
26
26
|
app.use(async (c, next) => {
|
|
27
|
-
console.log('2.
|
|
27
|
+
console.log('2. 요청 전')
|
|
28
28
|
await next()
|
|
29
|
-
console.log('3.
|
|
29
|
+
console.log('3. 응답 후')
|
|
30
30
|
})
|
|
31
|
-
//
|
|
31
|
+
// 출력: 1 → 2 → handler → 3 → 4
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
##
|
|
34
|
+
## 커스텀 미들웨어
|
|
35
35
|
|
|
36
36
|
```typescript
|
|
37
37
|
import { createMiddleware } from 'hono/factory'
|
|
@@ -51,13 +51,13 @@ export const authMiddleware = createMiddleware<Env>(async (c, next) => {
|
|
|
51
51
|
await next()
|
|
52
52
|
})
|
|
53
53
|
|
|
54
|
-
//
|
|
54
|
+
// 사용
|
|
55
55
|
app.get('/me', authMiddleware, (c) => {
|
|
56
56
|
return c.json({ userId: c.get('userId') })
|
|
57
57
|
})
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
-
##
|
|
60
|
+
## 타입 안전 미들웨어
|
|
61
61
|
|
|
62
62
|
```typescript
|
|
63
63
|
import { Hono } from 'hono'
|
|
@@ -84,8 +84,8 @@ app.use(dbMiddleware)
|
|
|
84
84
|
app.use(authMiddleware)
|
|
85
85
|
|
|
86
86
|
app.get('/users', (c) => {
|
|
87
|
-
const db = c.get('db') // Database
|
|
88
|
-
const user = c.get('user') // User | null
|
|
87
|
+
const db = c.get('db') // Database 타입
|
|
88
|
+
const user = c.get('user') // User | null 타입
|
|
89
89
|
return c.json({ users: [] })
|
|
90
90
|
})
|
|
91
91
|
```
|
|
@@ -96,8 +96,8 @@ app.get('/users', (c) => {
|
|
|
96
96
|
|
|
97
97
|
<builtin>
|
|
98
98
|
|
|
99
|
-
|
|
|
100
|
-
|
|
99
|
+
| 미들웨어 | 사용 |
|
|
100
|
+
|---------|------|
|
|
101
101
|
| **logger** | `app.use(logger())` |
|
|
102
102
|
| **cors** | `app.use('/api/*', cors({ origin: ['https://example.com'] }))` |
|
|
103
103
|
| **bearerAuth** | `app.use('/api/*', bearerAuth({ verifyToken: async (t) => t === 'valid' }))` |
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Hono RPC Client
|
|
2
2
|
|
|
3
|
-
> Type-safe API
|
|
3
|
+
> Type-safe API 호출
|
|
4
4
|
|
|
5
5
|
<patterns>
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## 서버 설정
|
|
8
8
|
|
|
9
9
|
```typescript
|
|
10
10
|
// server.ts
|
|
@@ -26,11 +26,11 @@ const app = new Hono()
|
|
|
26
26
|
}
|
|
27
27
|
)
|
|
28
28
|
|
|
29
|
-
export type AppType = typeof app // ✅
|
|
29
|
+
export type AppType = typeof app // ✅ 필수
|
|
30
30
|
export default app
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
##
|
|
33
|
+
## 클라이언트
|
|
34
34
|
|
|
35
35
|
```typescript
|
|
36
36
|
// client.ts
|
|
@@ -75,7 +75,7 @@ const client = hc<AppType>('http://localhost:8787/', {
|
|
|
75
75
|
})
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
-
##
|
|
78
|
+
## 타입 추론
|
|
79
79
|
|
|
80
80
|
```typescript
|
|
81
81
|
import type { InferRequestType, InferResponseType } from 'hono/client'
|
|
@@ -87,7 +87,7 @@ type UserResponse = InferResponseType<typeof client.users[':id'].$get>
|
|
|
87
87
|
// { id: string; name: string }
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
-
## CRUD
|
|
90
|
+
## CRUD 래퍼
|
|
91
91
|
|
|
92
92
|
```typescript
|
|
93
93
|
const userApi = {
|
|
@@ -117,7 +117,7 @@ const userApi = {
|
|
|
117
117
|
},
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
// URL
|
|
120
|
+
// URL 생성
|
|
121
121
|
const url = client.posts[':id'].$url({ param: { id: '123' } })
|
|
122
122
|
console.log(url.pathname) // /posts/123
|
|
123
123
|
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# Hono + Zod
|
|
1
|
+
# Hono + Zod 검증
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> @hono/zod-validator로 타입 안전 요청 검증
|
|
4
4
|
|
|
5
5
|
<setup>
|
|
6
6
|
```bash
|
|
@@ -54,7 +54,7 @@ app.get('/users/:id',
|
|
|
54
54
|
}
|
|
55
55
|
)
|
|
56
56
|
|
|
57
|
-
// Header (
|
|
57
|
+
// Header (소문자!)
|
|
58
58
|
app.get('/api/protected',
|
|
59
59
|
zValidator('header', z.object({ 'x-api-key': z.string().uuid() })),
|
|
60
60
|
(c) => {
|
|
@@ -63,7 +63,7 @@ app.get('/api/protected',
|
|
|
63
63
|
)
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
-
##
|
|
66
|
+
## 복합 검증
|
|
67
67
|
|
|
68
68
|
```typescript
|
|
69
69
|
app.post(
|
|
@@ -80,7 +80,7 @@ app.post(
|
|
|
80
80
|
)
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
-
##
|
|
83
|
+
## 커스텀 에러
|
|
84
84
|
|
|
85
85
|
```typescript
|
|
86
86
|
app.post(
|
|
@@ -100,7 +100,7 @@ app.post(
|
|
|
100
100
|
)
|
|
101
101
|
```
|
|
102
102
|
|
|
103
|
-
##
|
|
103
|
+
## 재사용 스키마
|
|
104
104
|
|
|
105
105
|
```typescript
|
|
106
106
|
// validators/user.ts
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# Prisma - Cloudflare D1
|
|
2
2
|
|
|
3
|
-
> SQLite
|
|
3
|
+
> SQLite 기반 서버리스 데이터베이스
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## 주의사항
|
|
8
8
|
|
|
9
9
|
```
|
|
10
|
-
D1
|
|
11
|
-
prisma migrate dev
|
|
12
|
-
Prisma ORM D1
|
|
10
|
+
D1은 트랜잭션 미지원 (ACID 보장 X)
|
|
11
|
+
prisma migrate dev 사용 불가 → wrangler CLI 사용
|
|
12
|
+
Prisma ORM D1 지원은 Preview 상태
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
---
|
|
@@ -22,11 +22,11 @@ Prisma ORM D1 support is in Preview
|
|
|
22
22
|
generator client {
|
|
23
23
|
provider = "prisma-client"
|
|
24
24
|
output = "../src/generated/prisma"
|
|
25
|
-
runtime = "cloudflare" //
|
|
25
|
+
runtime = "cloudflare" // D1 필수
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
datasource db {
|
|
29
|
-
provider = "sqlite" // D1
|
|
29
|
+
provider = "sqlite" // D1은 SQLite 기반
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
model User {
|
|
@@ -59,7 +59,7 @@ export default app
|
|
|
59
59
|
|
|
60
60
|
---
|
|
61
61
|
|
|
62
|
-
##
|
|
62
|
+
## 설치
|
|
63
63
|
|
|
64
64
|
```bash
|
|
65
65
|
npm install hono @prisma/client @prisma/adapter-d1
|
|
@@ -69,7 +69,7 @@ npx prisma init --datasource-provider sqlite
|
|
|
69
69
|
|
|
70
70
|
---
|
|
71
71
|
|
|
72
|
-
##
|
|
72
|
+
## D1 데이터베이스 생성
|
|
73
73
|
|
|
74
74
|
```bash
|
|
75
75
|
npx wrangler d1 create my-database
|
|
@@ -93,29 +93,29 @@ npx wrangler d1 create my-database
|
|
|
93
93
|
|
|
94
94
|
---
|
|
95
95
|
|
|
96
|
-
##
|
|
96
|
+
## 마이그레이션 워크플로우
|
|
97
97
|
|
|
98
98
|
```bash
|
|
99
|
-
# 1.
|
|
99
|
+
# 1. 마이그레이션 파일 생성
|
|
100
100
|
npx wrangler d1 migrations create my-database create_user_table
|
|
101
101
|
|
|
102
|
-
# 2.
|
|
102
|
+
# 2. SQL 생성 (초기)
|
|
103
103
|
npx prisma migrate diff \
|
|
104
104
|
--from-empty \
|
|
105
105
|
--to-schema-datamodel prisma/schema.prisma \
|
|
106
106
|
--script \
|
|
107
107
|
--output prisma/migrations/0001_create_user_table.sql
|
|
108
108
|
|
|
109
|
-
# 3.
|
|
109
|
+
# 3. 로컬 적용
|
|
110
110
|
npx wrangler d1 migrations apply my-database --local
|
|
111
111
|
|
|
112
|
-
# 4.
|
|
112
|
+
# 4. 원격 적용
|
|
113
113
|
npx wrangler d1 migrations apply my-database --remote
|
|
114
114
|
```
|
|
115
115
|
|
|
116
116
|
---
|
|
117
117
|
|
|
118
|
-
##
|
|
118
|
+
## 완전한 CRUD API
|
|
119
119
|
|
|
120
120
|
```typescript
|
|
121
121
|
import { Hono } from 'hono'
|
|
@@ -130,7 +130,7 @@ type Variables = { prisma: PrismaClient }
|
|
|
130
130
|
|
|
131
131
|
const app = new Hono<{ Bindings: Bindings; Variables: Variables }>()
|
|
132
132
|
|
|
133
|
-
// Prisma
|
|
133
|
+
// Prisma 미들웨어
|
|
134
134
|
app.use('*', async (c, next) => {
|
|
135
135
|
const adapter = new PrismaD1(c.env.DB)
|
|
136
136
|
c.set('prisma', new PrismaClient({ adapter }))
|
|
@@ -161,20 +161,20 @@ export default app
|
|
|
161
161
|
|
|
162
162
|
---
|
|
163
163
|
|
|
164
|
-
##
|
|
164
|
+
## 로컬 개발
|
|
165
165
|
|
|
166
166
|
```bash
|
|
167
|
-
#
|
|
167
|
+
# Worker 실행
|
|
168
168
|
npx wrangler dev
|
|
169
169
|
|
|
170
|
-
#
|
|
170
|
+
# D1 조회
|
|
171
171
|
npx wrangler d1 execute my-database --local \
|
|
172
172
|
--command "SELECT * FROM User;"
|
|
173
173
|
```
|
|
174
174
|
|
|
175
175
|
---
|
|
176
176
|
|
|
177
|
-
##
|
|
177
|
+
## 배포
|
|
178
178
|
|
|
179
179
|
```bash
|
|
180
180
|
npx prisma generate
|
|
@@ -184,17 +184,17 @@ npx wrangler deploy
|
|
|
184
184
|
|
|
185
185
|
---
|
|
186
186
|
|
|
187
|
-
##
|
|
187
|
+
## 제한사항
|
|
188
188
|
|
|
189
|
-
|
|
|
190
|
-
|
|
191
|
-
|
|
|
192
|
-
|
|
|
193
|
-
|
|
|
189
|
+
| 항목 | D1 |
|
|
190
|
+
|------|-----|
|
|
191
|
+
| 트랜잭션 | ❌ 미지원 |
|
|
192
|
+
| 마이그레이션 | wrangler 사용 |
|
|
193
|
+
| 접속 방식 | HTTP (어댑터) |
|
|
194
194
|
|
|
195
195
|
---
|
|
196
196
|
|
|
197
|
-
##
|
|
197
|
+
## 관련 문서
|
|
198
198
|
|
|
199
|
-
- [Prisma
|
|
200
|
-
- [Cloudflare
|
|
199
|
+
- [Prisma 개요](./index.md)
|
|
200
|
+
- [Cloudflare 배포](../../deployment/cloudflare.md)
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# Prisma - Config
|
|
1
|
+
# Prisma - Config 파일
|
|
2
2
|
|
|
3
|
-
> prisma.config.ts
|
|
3
|
+
> prisma.config.ts 설정 (v7)
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
## Multi-File
|
|
7
|
+
## Multi-File 스키마 필수 설정
|
|
8
8
|
|
|
9
9
|
```typescript
|
|
10
10
|
// prisma.config.ts
|
|
@@ -12,7 +12,7 @@ import path from 'node:path'
|
|
|
12
12
|
import { defineConfig, env } from 'prisma/config'
|
|
13
13
|
|
|
14
14
|
export default defineConfig({
|
|
15
|
-
schema: path.join('prisma', 'schema'), //
|
|
15
|
+
schema: path.join('prisma', 'schema'), // 폴더 경로
|
|
16
16
|
datasource: {
|
|
17
17
|
url: env('DATABASE_URL'),
|
|
18
18
|
},
|
|
@@ -21,13 +21,13 @@ export default defineConfig({
|
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
24
|
-
##
|
|
24
|
+
## 파일 위치
|
|
25
25
|
|
|
26
26
|
```
|
|
27
|
-
|
|
28
|
-
├── prisma.config.ts #
|
|
27
|
+
프로젝트/
|
|
28
|
+
├── prisma.config.ts # 프로젝트 루트
|
|
29
29
|
├── prisma/
|
|
30
|
-
│ ├── schema/ # Multi-File
|
|
30
|
+
│ ├── schema/ # Multi-File 스키마
|
|
31
31
|
│ │ ├── +base.prisma
|
|
32
32
|
│ │ ├── +enum.prisma
|
|
33
33
|
│ │ └── user.prisma
|
|
@@ -37,7 +37,7 @@ project/
|
|
|
37
37
|
|
|
38
38
|
---
|
|
39
39
|
|
|
40
|
-
##
|
|
40
|
+
## 전체 설정 예시
|
|
41
41
|
|
|
42
42
|
```typescript
|
|
43
43
|
// prisma.config.ts
|
|
@@ -69,14 +69,14 @@ datasource db {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
generator client {
|
|
72
|
-
provider = "prisma-client" // v7
|
|
72
|
+
provider = "prisma-client" // v7 필수
|
|
73
73
|
output = "../../generated/prisma"
|
|
74
74
|
}
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
---
|
|
78
78
|
|
|
79
|
-
##
|
|
79
|
+
## 시드 스크립트
|
|
80
80
|
|
|
81
81
|
```typescript
|
|
82
82
|
// prisma/seed.ts
|
|
@@ -86,7 +86,7 @@ const prisma = new PrismaClient()
|
|
|
86
86
|
|
|
87
87
|
async function main() {
|
|
88
88
|
await prisma.user.create({
|
|
89
|
-
data: { email: 'admin@example.com', name: '
|
|
89
|
+
data: { email: 'admin@example.com', name: '관리자' },
|
|
90
90
|
})
|
|
91
91
|
}
|
|
92
92
|
|
|
@@ -104,18 +104,18 @@ main()
|
|
|
104
104
|
generator client {
|
|
105
105
|
provider = "prisma-client"
|
|
106
106
|
output = "../../generated/prisma"
|
|
107
|
-
runtime = "workerd" // Workers
|
|
107
|
+
runtime = "workerd" // Workers 런타임
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
datasource db {
|
|
111
|
-
provider = "sqlite" // D1
|
|
111
|
+
provider = "sqlite" // D1은 SQLite
|
|
112
112
|
url = env("DATABASE_URL")
|
|
113
113
|
}
|
|
114
114
|
```
|
|
115
115
|
|
|
116
116
|
---
|
|
117
117
|
|
|
118
|
-
##
|
|
118
|
+
## 관련 문서
|
|
119
119
|
|
|
120
|
-
- [Prisma
|
|
120
|
+
- [Prisma 개요](./index.md)
|
|
121
121
|
- [Cloudflare D1](./cloudflare-d1.md)
|