@kood/claude-code 0.1.7 → 0.1.10
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 +137 -3
- package/package.json +8 -2
- package/templates/hono/CLAUDE.md +53 -326
- package/templates/hono/docs/architecture/architecture.md +93 -747
- package/templates/hono/docs/deployment/cloudflare.md +59 -513
- package/templates/hono/docs/deployment/docker.md +41 -356
- package/templates/hono/docs/deployment/index.md +49 -190
- package/templates/hono/docs/deployment/railway.md +36 -306
- package/templates/hono/docs/deployment/vercel.md +49 -434
- package/templates/hono/docs/library/ai-sdk/index.md +53 -290
- package/templates/hono/docs/library/ai-sdk/openrouter.md +19 -387
- package/templates/hono/docs/library/ai-sdk/providers.md +28 -394
- package/templates/hono/docs/library/ai-sdk/streaming.md +52 -353
- package/templates/hono/docs/library/ai-sdk/structured-output.md +63 -395
- package/templates/hono/docs/library/ai-sdk/tools.md +62 -431
- package/templates/hono/docs/library/hono/env-setup.md +24 -313
- package/templates/hono/docs/library/hono/error-handling.md +34 -295
- package/templates/hono/docs/library/hono/index.md +24 -122
- package/templates/hono/docs/library/hono/middleware.md +21 -188
- package/templates/hono/docs/library/hono/rpc.md +40 -341
- package/templates/hono/docs/library/hono/validation.md +35 -195
- package/templates/hono/docs/library/pino/index.md +42 -333
- package/templates/hono/docs/library/prisma/cloudflare-d1.md +64 -367
- package/templates/hono/docs/library/prisma/config.md +19 -260
- package/templates/hono/docs/library/prisma/index.md +64 -320
- package/templates/hono/docs/library/zod/index.md +53 -257
- package/templates/npx/CLAUDE.md +58 -276
- package/templates/npx/docs/references/patterns.md +160 -0
- package/templates/tanstack-start/CLAUDE.md +0 -4
- package/templates/tanstack-start/docs/architecture/architecture.md +44 -589
- package/templates/tanstack-start/docs/design/index.md +119 -12
- package/templates/tanstack-start/docs/guides/conventions.md +103 -0
- package/templates/tanstack-start/docs/guides/env-setup.md +34 -340
- package/templates/tanstack-start/docs/guides/getting-started.md +22 -209
- package/templates/tanstack-start/docs/guides/hooks.md +166 -0
- package/templates/tanstack-start/docs/guides/routes.md +166 -0
- package/templates/tanstack-start/docs/guides/services.md +143 -0
- package/templates/tanstack-start/docs/library/tanstack-query/index.md +18 -2
- package/templates/tanstack-start/docs/library/zod/index.md +16 -1
- package/templates/tanstack-start/docs/design/accessibility.md +0 -163
- package/templates/tanstack-start/docs/design/color.md +0 -93
- package/templates/tanstack-start/docs/design/spacing.md +0 -122
- package/templates/tanstack-start/docs/design/typography.md +0 -80
- package/templates/tanstack-start/docs/guides/best-practices.md +0 -950
- package/templates/tanstack-start/docs/guides/husky-lint-staged.md +0 -303
- package/templates/tanstack-start/docs/guides/prettier.md +0 -189
- package/templates/tanstack-start/docs/guides/project-templates.md +0 -710
- package/templates/tanstack-start/docs/library/tanstack-query/setup.md +0 -48
- package/templates/tanstack-start/docs/library/zod/basic-types.md +0 -74
|
@@ -7,27 +7,25 @@
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
##
|
|
11
|
-
|
|
12
|
-
이 문서는 **Prisma v7** 기준입니다. v6 이하와 설정이 다릅니다.
|
|
10
|
+
## 버전 주의
|
|
13
11
|
|
|
14
12
|
```prisma
|
|
15
13
|
generator client {
|
|
16
|
-
provider = "prisma-client"
|
|
17
|
-
output = "./generated/client"
|
|
14
|
+
provider = "prisma-client" // ✅ v7 (prisma-client-js 아님!)
|
|
15
|
+
output = "./generated/client" // ✅ output 필수
|
|
18
16
|
}
|
|
19
17
|
```
|
|
20
18
|
|
|
21
19
|
---
|
|
22
20
|
|
|
23
|
-
##
|
|
21
|
+
## 금지 사항
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
| 명령 | 설명 |
|
|
24
|
+
|------|------|
|
|
25
|
+
| `prisma db push` | 자동 실행 금지 |
|
|
26
|
+
| `prisma migrate` | 자동 실행 금지 |
|
|
27
|
+
| `prisma generate` | 자동 실행 금지 |
|
|
28
|
+
| schema 변경 | 요청된 것만 |
|
|
31
29
|
|
|
32
30
|
---
|
|
33
31
|
|
|
@@ -40,108 +38,40 @@ npm install -D prisma
|
|
|
40
38
|
|
|
41
39
|
---
|
|
42
40
|
|
|
43
|
-
##
|
|
44
|
-
|
|
45
|
-
### ⚠️ 필수: Multi-File 구조 사용
|
|
46
|
-
|
|
47
|
-
Prisma 스키마는 **반드시 Multi-File 구조**로 작성합니다.
|
|
48
|
-
|
|
49
|
-
```
|
|
50
|
-
prisma/
|
|
51
|
-
├── schema/
|
|
52
|
-
│ ├── +base.prisma # datasource, generator 설정
|
|
53
|
-
│ ├── +enum.prisma # 모든 enum 정의
|
|
54
|
-
│ ├── user.prisma # User 모델
|
|
55
|
-
│ ├── post.prisma # Post 모델
|
|
56
|
-
│ └── ... # 기타 모델별 파일
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
### ⚠️ 필수: 한글 주석 작성
|
|
60
|
-
|
|
61
|
-
**Prisma Multi-File의 모든 요소에 한글 주석을 작성해야 합니다.**
|
|
41
|
+
## Multi-File 구조 (필수)
|
|
62
42
|
|
|
63
43
|
```
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
44
|
+
prisma/schema/
|
|
45
|
+
├── +base.prisma # datasource, generator
|
|
46
|
+
├── +enum.prisma # enum 정의
|
|
47
|
+
├── user.prisma # User 모델 (한글 주석 필수)
|
|
48
|
+
└── post.prisma # Post 모델
|
|
69
49
|
```
|
|
70
50
|
|
|
71
|
-
###
|
|
72
|
-
|
|
73
|
-
#### +base.prisma (기본 설정)
|
|
51
|
+
### +base.prisma
|
|
74
52
|
|
|
75
53
|
```prisma
|
|
76
|
-
//
|
|
77
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
78
|
-
// Prisma 기본 설정 파일
|
|
79
|
-
// datasource 및 generator 설정
|
|
80
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
81
|
-
|
|
82
|
-
// 데이터베이스 연결 설정
|
|
54
|
+
// datasource, generator 설정
|
|
83
55
|
datasource db {
|
|
84
56
|
provider = "postgresql"
|
|
85
57
|
url = env("DATABASE_URL")
|
|
86
58
|
}
|
|
87
59
|
|
|
88
|
-
// Prisma Client 생성 설정
|
|
89
60
|
generator client {
|
|
90
|
-
provider = "prisma-client"
|
|
61
|
+
provider = "prisma-client"
|
|
91
62
|
output = "./generated/client"
|
|
92
63
|
}
|
|
93
64
|
```
|
|
94
65
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
```prisma
|
|
98
|
-
// prisma/schema/+enum.prisma
|
|
99
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
100
|
-
// 모든 열거형(enum) 정의 파일
|
|
101
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
102
|
-
|
|
103
|
-
// 사용자 권한 열거형
|
|
104
|
-
enum Role {
|
|
105
|
-
USER // 일반 사용자
|
|
106
|
-
ADMIN // 관리자
|
|
107
|
-
}
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
#### user.prisma (User 모델)
|
|
66
|
+
### user.prisma
|
|
111
67
|
|
|
112
68
|
```prisma
|
|
113
|
-
// prisma/schema/user.prisma
|
|
114
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
115
69
|
// 사용자 모델
|
|
116
|
-
// 시스템의 모든 사용자 정보를 저장
|
|
117
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
118
|
-
|
|
119
70
|
model User {
|
|
120
71
|
id String @id @default(cuid())
|
|
121
|
-
email String @unique // 로그인 이메일
|
|
122
|
-
name String? // 표시 이름
|
|
123
|
-
posts Post[] //
|
|
124
|
-
createdAt DateTime @default(now())
|
|
125
|
-
updatedAt DateTime @updatedAt
|
|
126
|
-
}
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
#### post.prisma (Post 모델)
|
|
130
|
-
|
|
131
|
-
```prisma
|
|
132
|
-
// prisma/schema/post.prisma
|
|
133
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
134
|
-
// 게시글 모델
|
|
135
|
-
// 사용자가 작성한 게시글 정보
|
|
136
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
137
|
-
|
|
138
|
-
model Post {
|
|
139
|
-
id String @id @default(cuid())
|
|
140
|
-
title String // 게시글 제목
|
|
141
|
-
content String? // 게시글 본문 (선택)
|
|
142
|
-
published Boolean @default(false) // 공개 여부
|
|
143
|
-
author User @relation(fields: [authorId], references: [id]) // 작성자 관계
|
|
144
|
-
authorId String // 작성자 ID (외래키)
|
|
72
|
+
email String @unique // 로그인 이메일
|
|
73
|
+
name String? // 표시 이름
|
|
74
|
+
posts Post[] // 작성 게시글
|
|
145
75
|
createdAt DateTime @default(now())
|
|
146
76
|
updatedAt DateTime @updatedAt
|
|
147
77
|
}
|
|
@@ -149,14 +79,11 @@ model Post {
|
|
|
149
79
|
|
|
150
80
|
---
|
|
151
81
|
|
|
152
|
-
## Prisma Client
|
|
153
|
-
|
|
154
|
-
### database/prisma.ts
|
|
82
|
+
## Prisma Client
|
|
155
83
|
|
|
156
84
|
```typescript
|
|
157
85
|
import { PrismaClient } from '../prisma/generated/client'
|
|
158
86
|
|
|
159
|
-
// 싱글톤 패턴
|
|
160
87
|
const globalForPrisma = globalThis as unknown as {
|
|
161
88
|
prisma: PrismaClient | undefined
|
|
162
89
|
}
|
|
@@ -174,235 +101,79 @@ if (process.env.NODE_ENV !== 'production') {
|
|
|
174
101
|
|
|
175
102
|
---
|
|
176
103
|
|
|
177
|
-
## CRUD
|
|
104
|
+
## CRUD
|
|
178
105
|
|
|
179
106
|
### Create
|
|
180
107
|
|
|
181
108
|
```typescript
|
|
182
|
-
// 단일 생성
|
|
183
109
|
const user = await prisma.user.create({
|
|
184
|
-
data: {
|
|
185
|
-
email: 'user@example.com',
|
|
186
|
-
name: 'John',
|
|
187
|
-
},
|
|
110
|
+
data: { email: 'user@example.com', name: 'John' },
|
|
188
111
|
})
|
|
189
112
|
|
|
190
|
-
// 관계와 함께
|
|
113
|
+
// 관계와 함께
|
|
191
114
|
const userWithPosts = await prisma.user.create({
|
|
192
115
|
data: {
|
|
193
116
|
email: 'user@example.com',
|
|
194
|
-
|
|
195
|
-
posts: {
|
|
196
|
-
create: [
|
|
197
|
-
{ title: 'Post 1', content: 'Content 1' },
|
|
198
|
-
{ title: 'Post 2', content: 'Content 2' },
|
|
199
|
-
],
|
|
200
|
-
},
|
|
201
|
-
},
|
|
202
|
-
include: {
|
|
203
|
-
posts: true,
|
|
117
|
+
posts: { create: [{ title: 'Post 1' }] },
|
|
204
118
|
},
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// 다수 생성
|
|
208
|
-
const users = await prisma.user.createMany({
|
|
209
|
-
data: [
|
|
210
|
-
{ email: 'user1@example.com', name: 'User 1' },
|
|
211
|
-
{ email: 'user2@example.com', name: 'User 2' },
|
|
212
|
-
],
|
|
213
|
-
skipDuplicates: true,
|
|
119
|
+
include: { posts: true },
|
|
214
120
|
})
|
|
215
121
|
```
|
|
216
122
|
|
|
217
123
|
### Read
|
|
218
124
|
|
|
219
125
|
```typescript
|
|
220
|
-
|
|
221
|
-
const user = await prisma.user.
|
|
222
|
-
where: { id: 'user-id' },
|
|
223
|
-
})
|
|
224
|
-
|
|
225
|
-
// 필수 조회 (없으면 에러)
|
|
226
|
-
const user = await prisma.user.findUniqueOrThrow({
|
|
227
|
-
where: { id: 'user-id' },
|
|
228
|
-
})
|
|
229
|
-
|
|
230
|
-
// 조건 조회
|
|
231
|
-
const user = await prisma.user.findFirst({
|
|
232
|
-
where: { email: { contains: '@example.com' } },
|
|
233
|
-
})
|
|
234
|
-
|
|
235
|
-
// 다수 조회
|
|
126
|
+
const user = await prisma.user.findUnique({ where: { id } })
|
|
127
|
+
const user = await prisma.user.findUniqueOrThrow({ where: { id } })
|
|
236
128
|
const users = await prisma.user.findMany({
|
|
237
129
|
where: { name: { not: null } },
|
|
238
130
|
orderBy: { createdAt: 'desc' },
|
|
239
131
|
take: 10,
|
|
240
|
-
skip: 0,
|
|
241
132
|
})
|
|
242
133
|
|
|
243
134
|
// 관계 포함
|
|
244
135
|
const userWithPosts = await prisma.user.findUnique({
|
|
245
|
-
where: { id
|
|
246
|
-
include: {
|
|
247
|
-
posts: {
|
|
248
|
-
where: { published: true },
|
|
249
|
-
orderBy: { createdAt: 'desc' },
|
|
250
|
-
},
|
|
251
|
-
},
|
|
252
|
-
})
|
|
253
|
-
|
|
254
|
-
// 특정 필드만 선택
|
|
255
|
-
const userEmail = await prisma.user.findUnique({
|
|
256
|
-
where: { id: 'user-id' },
|
|
257
|
-
select: {
|
|
258
|
-
id: true,
|
|
259
|
-
email: true,
|
|
260
|
-
},
|
|
136
|
+
where: { id },
|
|
137
|
+
include: { posts: { where: { published: true } } },
|
|
261
138
|
})
|
|
262
139
|
```
|
|
263
140
|
|
|
264
141
|
### Update
|
|
265
142
|
|
|
266
143
|
```typescript
|
|
267
|
-
// 단일 수정
|
|
268
144
|
const user = await prisma.user.update({
|
|
269
|
-
where: { id
|
|
145
|
+
where: { id },
|
|
270
146
|
data: { name: 'New Name' },
|
|
271
147
|
})
|
|
272
148
|
|
|
273
|
-
//
|
|
274
|
-
const users = await prisma.user.updateMany({
|
|
275
|
-
where: { name: null },
|
|
276
|
-
data: { name: 'Anonymous' },
|
|
277
|
-
})
|
|
278
|
-
|
|
279
|
-
// 없으면 생성 (Upsert)
|
|
149
|
+
// Upsert
|
|
280
150
|
const user = await prisma.user.upsert({
|
|
281
151
|
where: { email: 'user@example.com' },
|
|
282
|
-
update: { name: 'Updated
|
|
283
|
-
create: { email: 'user@example.com', name: 'New
|
|
152
|
+
update: { name: 'Updated' },
|
|
153
|
+
create: { email: 'user@example.com', name: 'New' },
|
|
284
154
|
})
|
|
285
155
|
```
|
|
286
156
|
|
|
287
157
|
### Delete
|
|
288
158
|
|
|
289
159
|
```typescript
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
where: { id: 'user-id' },
|
|
293
|
-
})
|
|
294
|
-
|
|
295
|
-
// 다수 삭제
|
|
296
|
-
const users = await prisma.user.deleteMany({
|
|
297
|
-
where: { email: { contains: '@test.com' } },
|
|
298
|
-
})
|
|
160
|
+
await prisma.user.delete({ where: { id } })
|
|
161
|
+
await prisma.user.deleteMany({ where: { email: { contains: '@test.com' } } })
|
|
299
162
|
```
|
|
300
163
|
|
|
301
164
|
---
|
|
302
165
|
|
|
303
166
|
## 필터링
|
|
304
167
|
|
|
305
|
-
### 비교 연산자
|
|
306
|
-
|
|
307
|
-
```typescript
|
|
308
|
-
await prisma.user.findMany({
|
|
309
|
-
where: {
|
|
310
|
-
age: { gt: 18 }, // >
|
|
311
|
-
age: { gte: 18 }, // >=
|
|
312
|
-
age: { lt: 65 }, // <
|
|
313
|
-
age: { lte: 65 }, // <=
|
|
314
|
-
age: { not: 30 }, // !=
|
|
315
|
-
name: { equals: 'John' },
|
|
316
|
-
},
|
|
317
|
-
})
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
### 문자열 필터
|
|
321
|
-
|
|
322
|
-
```typescript
|
|
323
|
-
await prisma.user.findMany({
|
|
324
|
-
where: {
|
|
325
|
-
email: { contains: '@gmail.com' },
|
|
326
|
-
email: { startsWith: 'admin' },
|
|
327
|
-
email: { endsWith: '.com' },
|
|
328
|
-
name: { mode: 'insensitive' }, // 대소문자 무시
|
|
329
|
-
},
|
|
330
|
-
})
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
### 논리 연산자
|
|
334
|
-
|
|
335
|
-
```typescript
|
|
336
|
-
await prisma.user.findMany({
|
|
337
|
-
where: {
|
|
338
|
-
AND: [
|
|
339
|
-
{ email: { contains: '@' } },
|
|
340
|
-
{ name: { not: null } },
|
|
341
|
-
],
|
|
342
|
-
OR: [
|
|
343
|
-
{ role: 'admin' },
|
|
344
|
-
{ role: 'moderator' },
|
|
345
|
-
],
|
|
346
|
-
NOT: {
|
|
347
|
-
status: 'banned',
|
|
348
|
-
},
|
|
349
|
-
},
|
|
350
|
-
})
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
### 배열 필터
|
|
354
|
-
|
|
355
168
|
```typescript
|
|
356
169
|
await prisma.user.findMany({
|
|
357
170
|
where: {
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
---
|
|
365
|
-
|
|
366
|
-
## 관계 쿼리
|
|
367
|
-
|
|
368
|
-
### Include (전체 데이터)
|
|
369
|
-
|
|
370
|
-
```typescript
|
|
371
|
-
const user = await prisma.user.findUnique({
|
|
372
|
-
where: { id: 'user-id' },
|
|
373
|
-
include: {
|
|
374
|
-
posts: true,
|
|
375
|
-
profile: true,
|
|
376
|
-
},
|
|
377
|
-
})
|
|
378
|
-
```
|
|
379
|
-
|
|
380
|
-
### Select (특정 필드)
|
|
381
|
-
|
|
382
|
-
```typescript
|
|
383
|
-
const user = await prisma.user.findUnique({
|
|
384
|
-
where: { id: 'user-id' },
|
|
385
|
-
select: {
|
|
386
|
-
id: true,
|
|
387
|
-
email: true,
|
|
388
|
-
posts: {
|
|
389
|
-
select: { id: true, title: true },
|
|
390
|
-
},
|
|
391
|
-
},
|
|
392
|
-
})
|
|
393
|
-
```
|
|
394
|
-
|
|
395
|
-
### 관계 필터링
|
|
396
|
-
|
|
397
|
-
```typescript
|
|
398
|
-
// 관계 조건으로 필터
|
|
399
|
-
const usersWithPublishedPosts = await prisma.user.findMany({
|
|
400
|
-
where: {
|
|
401
|
-
posts: {
|
|
402
|
-
some: { published: true }, // 하나라도 만족
|
|
403
|
-
// every: { published: true }, // 모두 만족
|
|
404
|
-
// none: { published: true }, // 하나도 없음
|
|
405
|
-
},
|
|
171
|
+
age: { gt: 18, lte: 65 }, // 비교
|
|
172
|
+
email: { contains: '@gmail.com' }, // 문자열
|
|
173
|
+
AND: [{ email: { contains: '@' } }, { name: { not: null } }],
|
|
174
|
+
OR: [{ role: 'admin' }, { role: 'moderator' }],
|
|
175
|
+
id: { in: ['id1', 'id2'] }, // 배열
|
|
176
|
+
posts: { some: { published: true } }, // 관계
|
|
406
177
|
},
|
|
407
178
|
})
|
|
408
179
|
```
|
|
@@ -411,33 +182,18 @@ const usersWithPublishedPosts = await prisma.user.findMany({
|
|
|
411
182
|
|
|
412
183
|
## 트랜잭션
|
|
413
184
|
|
|
414
|
-
### Sequential 트랜잭션
|
|
415
|
-
|
|
416
185
|
```typescript
|
|
186
|
+
// Sequential
|
|
417
187
|
const [user, post] = await prisma.$transaction([
|
|
418
188
|
prisma.user.create({ data: { email: 'user@example.com' } }),
|
|
419
189
|
prisma.post.create({ data: { title: 'New Post', authorId: 'user-id' } }),
|
|
420
190
|
])
|
|
421
|
-
```
|
|
422
191
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
```typescript
|
|
192
|
+
// Interactive
|
|
426
193
|
const result = await prisma.$transaction(async (tx) => {
|
|
427
|
-
const user = await tx.user.findUnique({ where: { id
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
throw new Error('User not found')
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
const post = await tx.post.create({
|
|
434
|
-
data: {
|
|
435
|
-
title: 'New Post',
|
|
436
|
-
authorId: user.id,
|
|
437
|
-
},
|
|
438
|
-
})
|
|
439
|
-
|
|
440
|
-
return { user, post }
|
|
194
|
+
const user = await tx.user.findUnique({ where: { id } })
|
|
195
|
+
if (!user) throw new Error('User not found')
|
|
196
|
+
return tx.post.create({ data: { title: 'Post', authorId: user.id } })
|
|
441
197
|
})
|
|
442
198
|
```
|
|
443
199
|
|
|
@@ -454,31 +210,24 @@ import { prisma } from '@/database/prisma'
|
|
|
454
210
|
|
|
455
211
|
const app = new Hono()
|
|
456
212
|
|
|
457
|
-
|
|
458
|
-
email: z.email(),
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
app.post('/users', zValidator('json', createUserSchema), async (c) => {
|
|
463
|
-
const data = c.req.valid('json')
|
|
213
|
+
app.post('/users',
|
|
214
|
+
zValidator('json', z.object({ email: z.email(), name: z.string().optional() })),
|
|
215
|
+
async (c) => {
|
|
216
|
+
const data = c.req.valid('json')
|
|
464
217
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
218
|
+
const existing = await prisma.user.findUnique({ where: { email: data.email } })
|
|
219
|
+
if (existing) {
|
|
220
|
+
throw new HTTPException(409, { message: 'Email already exists' })
|
|
221
|
+
}
|
|
469
222
|
|
|
470
|
-
|
|
471
|
-
|
|
223
|
+
const user = await prisma.user.create({ data })
|
|
224
|
+
return c.json({ user }, 201)
|
|
472
225
|
}
|
|
473
|
-
|
|
474
|
-
const user = await prisma.user.create({ data })
|
|
475
|
-
return c.json({ user }, 201)
|
|
476
|
-
})
|
|
226
|
+
)
|
|
477
227
|
|
|
478
228
|
app.get('/users/:id', async (c) => {
|
|
479
|
-
const id = c.req.param('id')
|
|
480
229
|
const user = await prisma.user.findUnique({
|
|
481
|
-
where: { id },
|
|
230
|
+
where: { id: c.req.param('id') },
|
|
482
231
|
include: { posts: true },
|
|
483
232
|
})
|
|
484
233
|
|
|
@@ -488,16 +237,11 @@ app.get('/users/:id', async (c) => {
|
|
|
488
237
|
|
|
489
238
|
return c.json({ user })
|
|
490
239
|
})
|
|
491
|
-
|
|
492
|
-
export default app
|
|
493
240
|
```
|
|
494
241
|
|
|
495
242
|
---
|
|
496
243
|
|
|
497
244
|
## 관련 문서
|
|
498
245
|
|
|
499
|
-
- [Config 파일](./config.md) - prisma.config.ts 설정
|
|
500
|
-
- [
|
|
501
|
-
- [Relations](./relations.md)
|
|
502
|
-
- [Transactions](./transactions.md)
|
|
503
|
-
- [Cloudflare D1](./cloudflare-d1.md) - D1 서버리스 데이터베이스 연동
|
|
246
|
+
- [Config 파일](./config.md) - prisma.config.ts 설정
|
|
247
|
+
- [Cloudflare D1](./cloudflare-d1.md)
|