@kood/claude-code 0.1.6 → 0.1.9
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 +109 -216
- package/package.json +8 -2
- package/templates/hono/CLAUDE.md +59 -328
- 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 +54 -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 +29 -121
- 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 +67 -320
- package/templates/hono/docs/library/zod/index.md +53 -257
- package/templates/npx/CLAUDE.md +62 -274
- package/templates/npx/docs/references/patterns.md +160 -0
- package/templates/tanstack-start/CLAUDE.md +100 -256
- package/templates/tanstack-start/docs/architecture/architecture.md +44 -589
- package/templates/tanstack-start/docs/deployment/cloudflare.md +37 -424
- package/templates/tanstack-start/docs/deployment/index.md +57 -286
- package/templates/tanstack-start/docs/deployment/nitro.md +36 -318
- package/templates/tanstack-start/docs/deployment/railway.md +40 -409
- package/templates/tanstack-start/docs/deployment/vercel.md +43 -465
- package/templates/tanstack-start/docs/design/components.md +77 -311
- package/templates/tanstack-start/docs/design/index.md +113 -69
- package/templates/tanstack-start/docs/design/safe-area.md +51 -250
- package/templates/tanstack-start/docs/design/tailwind-setup.md +45 -359
- 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/better-auth/2fa.md +27 -115
- package/templates/tanstack-start/docs/library/better-auth/advanced.md +22 -105
- package/templates/tanstack-start/docs/library/better-auth/index.md +17 -66
- package/templates/tanstack-start/docs/library/better-auth/plugins.md +11 -88
- package/templates/tanstack-start/docs/library/better-auth/session.md +12 -92
- package/templates/tanstack-start/docs/library/better-auth/setup.md +9 -91
- package/templates/tanstack-start/docs/library/prisma/cloudflare-d1.md +30 -358
- package/templates/tanstack-start/docs/library/prisma/config.md +27 -327
- package/templates/tanstack-start/docs/library/prisma/crud.md +46 -174
- package/templates/tanstack-start/docs/library/prisma/index.md +23 -113
- package/templates/tanstack-start/docs/library/prisma/relations.md +31 -153
- package/templates/tanstack-start/docs/library/prisma/schema.md +40 -217
- package/templates/tanstack-start/docs/library/prisma/setup.md +12 -112
- package/templates/tanstack-start/docs/library/prisma/transactions.md +20 -110
- package/templates/tanstack-start/docs/library/tanstack-query/index.md +26 -97
- package/templates/tanstack-start/docs/library/tanstack-query/invalidation.md +28 -107
- package/templates/tanstack-start/docs/library/tanstack-query/optimistic-updates.md +44 -146
- package/templates/tanstack-start/docs/library/tanstack-query/use-mutation.md +33 -127
- package/templates/tanstack-start/docs/library/tanstack-query/use-query.md +49 -149
- package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +19 -112
- package/templates/tanstack-start/docs/library/tanstack-start/index.md +33 -80
- package/templates/tanstack-start/docs/library/tanstack-start/middleware.md +28 -106
- package/templates/tanstack-start/docs/library/tanstack-start/routing.md +21 -118
- package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +34 -246
- package/templates/tanstack-start/docs/library/tanstack-start/setup.md +6 -39
- package/templates/tanstack-start/docs/library/zod/complex-types.md +32 -156
- package/templates/tanstack-start/docs/library/zod/index.md +31 -144
- package/templates/tanstack-start/docs/library/zod/transforms.md +20 -129
- package/templates/tanstack-start/docs/library/zod/validation.md +39 -155
- package/templates/hono/docs/commands/git.md +0 -145
- package/templates/hono/docs/mcp/context7.md +0 -106
- package/templates/hono/docs/mcp/index.md +0 -176
- package/templates/hono/docs/mcp/sequential-thinking.md +0 -101
- package/templates/hono/docs/mcp/serena.md +0 -269
- package/templates/hono/docs/mcp/sgrep.md +0 -105
- package/templates/hono/docs/skills/gemini-review/SKILL.md +0 -220
- package/templates/hono/docs/skills/gemini-review/references/checklists.md +0 -136
- package/templates/hono/docs/skills/gemini-review/references/prompt-templates.md +0 -303
- package/templates/npx/docs/commands/git.md +0 -145
- package/templates/npx/docs/mcp/index.md +0 -60
- package/templates/npx/docs/skills/gemini-review/SKILL.md +0 -220
- package/templates/npx/docs/skills/gemini-review/references/checklists.md +0 -134
- package/templates/npx/docs/skills/gemini-review/references/prompt-templates.md +0 -301
- package/templates/tanstack-start/docs/commands/git.md +0 -145
- package/templates/tanstack-start/docs/design/accessibility.md +0 -433
- package/templates/tanstack-start/docs/design/color.md +0 -235
- package/templates/tanstack-start/docs/design/spacing.md +0 -341
- package/templates/tanstack-start/docs/design/typography.md +0 -324
- 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 -107
- package/templates/tanstack-start/docs/library/zod/basic-types.md +0 -186
- package/templates/tanstack-start/docs/mcp/context7.md +0 -204
- package/templates/tanstack-start/docs/mcp/index.md +0 -177
- package/templates/tanstack-start/docs/mcp/sequential-thinking.md +0 -180
- package/templates/tanstack-start/docs/mcp/serena.md +0 -269
- package/templates/tanstack-start/docs/mcp/sgrep.md +0 -174
- package/templates/tanstack-start/docs/skills/gemini-review/SKILL.md +0 -220
- package/templates/tanstack-start/docs/skills/gemini-review/references/checklists.md +0 -144
- package/templates/tanstack-start/docs/skills/gemini-review/references/prompt-templates.md +0 -292
|
@@ -1,53 +1,28 @@
|
|
|
1
1
|
# Prisma - Cloudflare D1
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> SQLite 기반 서버리스 데이터베이스
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
##
|
|
8
|
-
|
|
9
|
-
Cloudflare D1은 **SQLite 기반 서버리스 데이터베이스**입니다. 일반 Prisma 마이그레이션과 **다른 워크플로우**를 사용합니다.
|
|
7
|
+
## 주의사항
|
|
10
8
|
|
|
11
9
|
```
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
D1은 트랜잭션 미지원 (ACID 보장 X)
|
|
11
|
+
prisma migrate dev 사용 불가 → wrangler CLI 사용
|
|
12
|
+
Prisma ORM D1 지원은 Preview 상태
|
|
15
13
|
```
|
|
16
14
|
|
|
17
15
|
---
|
|
18
16
|
|
|
19
|
-
##
|
|
20
|
-
|
|
21
|
-
```typescript
|
|
22
|
-
// Hono + D1 Adapter 설정
|
|
23
|
-
import { Hono } from 'hono'
|
|
24
|
-
import { PrismaClient } from './generated/prisma'
|
|
25
|
-
import { PrismaD1 } from '@prisma/adapter-d1'
|
|
26
|
-
|
|
27
|
-
type Bindings = {
|
|
28
|
-
DB: D1Database
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const app = new Hono<{ Bindings: Bindings }>()
|
|
32
|
-
|
|
33
|
-
app.get('/users', async (c) => {
|
|
34
|
-
const adapter = new PrismaD1(c.env.DB)
|
|
35
|
-
const prisma = new PrismaClient({ adapter })
|
|
36
|
-
|
|
37
|
-
const users = await prisma.user.findMany()
|
|
38
|
-
return c.json(users)
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
export default app
|
|
42
|
-
```
|
|
17
|
+
## Quick Setup
|
|
43
18
|
|
|
44
|
-
### schema.prisma
|
|
19
|
+
### schema.prisma
|
|
45
20
|
|
|
46
21
|
```prisma
|
|
47
22
|
generator client {
|
|
48
23
|
provider = "prisma-client"
|
|
49
24
|
output = "../src/generated/prisma"
|
|
50
|
-
runtime = "cloudflare" // D1
|
|
25
|
+
runtime = "cloudflare" // D1 필수
|
|
51
26
|
}
|
|
52
27
|
|
|
53
28
|
datasource db {
|
|
@@ -61,16 +36,34 @@ model User {
|
|
|
61
36
|
}
|
|
62
37
|
```
|
|
63
38
|
|
|
39
|
+
### Hono + D1
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { Hono } from 'hono'
|
|
43
|
+
import { PrismaClient } from './generated/prisma'
|
|
44
|
+
import { PrismaD1 } from '@prisma/adapter-d1'
|
|
45
|
+
|
|
46
|
+
type Bindings = { DB: D1Database }
|
|
47
|
+
|
|
48
|
+
const app = new Hono<{ Bindings: Bindings }>()
|
|
49
|
+
|
|
50
|
+
app.get('/users', async (c) => {
|
|
51
|
+
const adapter = new PrismaD1(c.env.DB)
|
|
52
|
+
const prisma = new PrismaClient({ adapter })
|
|
53
|
+
const users = await prisma.user.findMany()
|
|
54
|
+
return c.json(users)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
export default app
|
|
58
|
+
```
|
|
59
|
+
|
|
64
60
|
---
|
|
65
61
|
|
|
66
62
|
## 설치
|
|
67
63
|
|
|
68
64
|
```bash
|
|
69
|
-
# 필수 패키지
|
|
70
65
|
npm install hono @prisma/client @prisma/adapter-d1
|
|
71
66
|
npm install -D prisma wrangler
|
|
72
|
-
|
|
73
|
-
# Prisma 초기화
|
|
74
67
|
npx prisma init --datasource-provider sqlite
|
|
75
68
|
```
|
|
76
69
|
|
|
@@ -79,65 +72,22 @@ npx prisma init --datasource-provider sqlite
|
|
|
79
72
|
## D1 데이터베이스 생성
|
|
80
73
|
|
|
81
74
|
```bash
|
|
82
|
-
# Cloudflare D1 데이터베이스 생성
|
|
83
75
|
npx wrangler d1 create my-database
|
|
84
|
-
|
|
85
|
-
# 출력 예시:
|
|
86
|
-
# ✅ Successfully created DB 'my-database'
|
|
87
76
|
# database_id = "xxxx-xxxx-xxxx-xxxx"
|
|
88
77
|
```
|
|
89
78
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
## wrangler.jsonc 설정
|
|
79
|
+
### wrangler.jsonc
|
|
93
80
|
|
|
94
81
|
```jsonc
|
|
95
82
|
{
|
|
96
|
-
"$schema": "node_modules/wrangler/config-schema.json",
|
|
97
83
|
"name": "hono-d1-app",
|
|
98
84
|
"main": "src/index.ts",
|
|
99
85
|
"compatibility_date": "2025-01-01",
|
|
100
|
-
"d1_databases": [
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
]
|
|
107
|
-
}
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
---
|
|
111
|
-
|
|
112
|
-
## Schema 설정
|
|
113
|
-
|
|
114
|
-
### schema.prisma
|
|
115
|
-
|
|
116
|
-
```prisma
|
|
117
|
-
generator client {
|
|
118
|
-
provider = "prisma-client"
|
|
119
|
-
output = "../src/generated/prisma"
|
|
120
|
-
runtime = "cloudflare"
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
datasource db {
|
|
124
|
-
provider = "sqlite"
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
model User {
|
|
128
|
-
id Int @id @default(autoincrement())
|
|
129
|
-
email String @unique
|
|
130
|
-
name String?
|
|
131
|
-
posts Post[]
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
model Post {
|
|
135
|
-
id Int @id @default(autoincrement())
|
|
136
|
-
title String
|
|
137
|
-
content String?
|
|
138
|
-
published Boolean @default(false)
|
|
139
|
-
author User @relation(fields: [authorId], references: [id])
|
|
140
|
-
authorId Int
|
|
86
|
+
"d1_databases": [{
|
|
87
|
+
"binding": "DB",
|
|
88
|
+
"database_name": "my-database",
|
|
89
|
+
"database_id": "YOUR_DATABASE_ID"
|
|
90
|
+
}]
|
|
141
91
|
}
|
|
142
92
|
```
|
|
143
93
|
|
|
@@ -145,92 +95,27 @@ model Post {
|
|
|
145
95
|
|
|
146
96
|
## 마이그레이션 워크플로우
|
|
147
97
|
|
|
148
|
-
D1은 일반 Prisma 마이그레이션(`prisma migrate dev`)을 사용하지 않습니다.
|
|
149
|
-
|
|
150
|
-
### 1단계: 마이그레이션 디렉토리 생성
|
|
151
|
-
|
|
152
|
-
```bash
|
|
153
|
-
mkdir -p prisma/migrations
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
### 2단계: 마이그레이션 파일 생성 (wrangler)
|
|
157
|
-
|
|
158
98
|
```bash
|
|
99
|
+
# 1. 마이그레이션 파일 생성
|
|
159
100
|
npx wrangler d1 migrations create my-database create_user_table
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
### 3단계: SQL 생성 (prisma migrate diff)
|
|
163
101
|
|
|
164
|
-
|
|
165
|
-
# 초기 마이그레이션 (빈 스키마에서)
|
|
102
|
+
# 2. SQL 생성 (초기)
|
|
166
103
|
npx prisma migrate diff \
|
|
167
104
|
--from-empty \
|
|
168
105
|
--to-schema-datamodel prisma/schema.prisma \
|
|
169
106
|
--script \
|
|
170
107
|
--output prisma/migrations/0001_create_user_table.sql
|
|
171
108
|
|
|
172
|
-
#
|
|
173
|
-
npx prisma migrate diff \
|
|
174
|
-
--from-local-d1 \
|
|
175
|
-
--to-schema-datamodel prisma/schema.prisma \
|
|
176
|
-
--script \
|
|
177
|
-
--output prisma/migrations/0002_add_post_table.sql
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
### 4단계: 마이그레이션 적용
|
|
181
|
-
|
|
182
|
-
```bash
|
|
183
|
-
# 로컬 데이터베이스에 적용
|
|
109
|
+
# 3. 로컬 적용
|
|
184
110
|
npx wrangler d1 migrations apply my-database --local
|
|
185
111
|
|
|
186
|
-
# 원격
|
|
112
|
+
# 4. 원격 적용
|
|
187
113
|
npx wrangler d1 migrations apply my-database --remote
|
|
188
114
|
```
|
|
189
115
|
|
|
190
|
-
### 생성된 SQL 예시
|
|
191
|
-
|
|
192
|
-
```sql
|
|
193
|
-
-- 0001_create_user_table.sql
|
|
194
|
-
-- CreateTable
|
|
195
|
-
CREATE TABLE "User" (
|
|
196
|
-
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
197
|
-
"email" TEXT NOT NULL,
|
|
198
|
-
"name" TEXT
|
|
199
|
-
);
|
|
200
|
-
|
|
201
|
-
-- CreateIndex
|
|
202
|
-
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
|
|
203
|
-
```
|
|
204
|
-
|
|
205
116
|
---
|
|
206
117
|
|
|
207
|
-
##
|
|
208
|
-
|
|
209
|
-
### 기본 설정
|
|
210
|
-
|
|
211
|
-
```typescript
|
|
212
|
-
// src/index.ts
|
|
213
|
-
import { Hono } from 'hono'
|
|
214
|
-
import { PrismaClient } from './generated/prisma'
|
|
215
|
-
import { PrismaD1 } from '@prisma/adapter-d1'
|
|
216
|
-
|
|
217
|
-
type Bindings = {
|
|
218
|
-
DB: D1Database
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
const app = new Hono<{ Bindings: Bindings }>()
|
|
222
|
-
|
|
223
|
-
// Prisma 미들웨어
|
|
224
|
-
app.use('*', async (c, next) => {
|
|
225
|
-
const adapter = new PrismaD1(c.env.DB)
|
|
226
|
-
c.set('prisma', new PrismaClient({ adapter }))
|
|
227
|
-
await next()
|
|
228
|
-
})
|
|
229
|
-
|
|
230
|
-
export default app
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
### CRUD API 구현
|
|
118
|
+
## 완전한 CRUD API
|
|
234
119
|
|
|
235
120
|
```typescript
|
|
236
121
|
import { Hono } from 'hono'
|
|
@@ -240,13 +125,8 @@ import { HTTPException } from 'hono/http-exception'
|
|
|
240
125
|
import { PrismaClient } from './generated/prisma'
|
|
241
126
|
import { PrismaD1 } from '@prisma/adapter-d1'
|
|
242
127
|
|
|
243
|
-
type Bindings = {
|
|
244
|
-
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
type Variables = {
|
|
248
|
-
prisma: PrismaClient
|
|
249
|
-
}
|
|
128
|
+
type Bindings = { DB: D1Database }
|
|
129
|
+
type Variables = { prisma: PrismaClient }
|
|
250
130
|
|
|
251
131
|
const app = new Hono<{ Bindings: Bindings; Variables: Variables }>()
|
|
252
132
|
|
|
@@ -257,82 +137,24 @@ app.use('*', async (c, next) => {
|
|
|
257
137
|
await next()
|
|
258
138
|
})
|
|
259
139
|
|
|
260
|
-
// 스키마 정의
|
|
261
|
-
const createUserSchema = z.object({
|
|
262
|
-
email: z.string().email(),
|
|
263
|
-
name: z.string().min(1).optional(),
|
|
264
|
-
})
|
|
265
|
-
|
|
266
|
-
const updateUserSchema = z.object({
|
|
267
|
-
name: z.string().min(1).optional(),
|
|
268
|
-
})
|
|
269
|
-
|
|
270
|
-
// GET /users - 전체 사용자 조회
|
|
271
140
|
app.get('/users', async (c) => {
|
|
272
|
-
const
|
|
273
|
-
const users = await prisma.user.findMany({
|
|
274
|
-
include: { posts: true },
|
|
275
|
-
})
|
|
141
|
+
const users = await c.get('prisma').user.findMany()
|
|
276
142
|
return c.json(users)
|
|
277
143
|
})
|
|
278
144
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
145
|
+
app.post('/users',
|
|
146
|
+
zValidator('json', z.object({ email: z.email(), name: z.string().optional() })),
|
|
147
|
+
async (c) => {
|
|
148
|
+
const prisma = c.get('prisma')
|
|
149
|
+
const data = c.req.valid('json')
|
|
283
150
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
include: { posts: true },
|
|
287
|
-
})
|
|
151
|
+
const existing = await prisma.user.findUnique({ where: { email: data.email } })
|
|
152
|
+
if (existing) throw new HTTPException(409, { message: 'Email already exists' })
|
|
288
153
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
return c.json(user)
|
|
294
|
-
})
|
|
295
|
-
|
|
296
|
-
// POST /users - 사용자 생성
|
|
297
|
-
app.post('/users', zValidator('json', createUserSchema), async (c) => {
|
|
298
|
-
const prisma = c.get('prisma')
|
|
299
|
-
const data = c.req.valid('json')
|
|
300
|
-
|
|
301
|
-
// 중복 체크
|
|
302
|
-
const existing = await prisma.user.findUnique({
|
|
303
|
-
where: { email: data.email },
|
|
304
|
-
})
|
|
305
|
-
|
|
306
|
-
if (existing) {
|
|
307
|
-
throw new HTTPException(409, { message: 'Email already exists' })
|
|
154
|
+
const user = await prisma.user.create({ data })
|
|
155
|
+
return c.json(user, 201)
|
|
308
156
|
}
|
|
309
|
-
|
|
310
|
-
const user = await prisma.user.create({ data })
|
|
311
|
-
return c.json(user, 201)
|
|
312
|
-
})
|
|
313
|
-
|
|
314
|
-
// PATCH /users/:id - 사용자 수정
|
|
315
|
-
app.patch('/users/:id', zValidator('json', updateUserSchema), async (c) => {
|
|
316
|
-
const prisma = c.get('prisma')
|
|
317
|
-
const id = parseInt(c.req.param('id'))
|
|
318
|
-
const data = c.req.valid('json')
|
|
319
|
-
|
|
320
|
-
const user = await prisma.user.update({
|
|
321
|
-
where: { id },
|
|
322
|
-
data,
|
|
323
|
-
})
|
|
324
|
-
|
|
325
|
-
return c.json(user)
|
|
326
|
-
})
|
|
327
|
-
|
|
328
|
-
// DELETE /users/:id - 사용자 삭제
|
|
329
|
-
app.delete('/users/:id', async (c) => {
|
|
330
|
-
const prisma = c.get('prisma')
|
|
331
|
-
const id = parseInt(c.req.param('id'))
|
|
332
|
-
|
|
333
|
-
await prisma.user.delete({ where: { id } })
|
|
334
|
-
return c.json({ message: 'User deleted' })
|
|
335
|
-
})
|
|
157
|
+
)
|
|
336
158
|
|
|
337
159
|
export default app
|
|
338
160
|
```
|
|
@@ -341,17 +163,11 @@ export default app
|
|
|
341
163
|
|
|
342
164
|
## 로컬 개발
|
|
343
165
|
|
|
344
|
-
### 로컬 D1로 개발
|
|
345
|
-
|
|
346
166
|
```bash
|
|
347
|
-
#
|
|
167
|
+
# Worker 실행
|
|
348
168
|
npx wrangler dev
|
|
349
169
|
|
|
350
|
-
#
|
|
351
|
-
npx wrangler d1 execute my-database --local \
|
|
352
|
-
--command "INSERT INTO User (email, name) VALUES ('test@example.com', 'Test User');"
|
|
353
|
-
|
|
354
|
-
# 로컬 D1 조회
|
|
170
|
+
# D1 조회
|
|
355
171
|
npx wrangler d1 execute my-database --local \
|
|
356
172
|
--command "SELECT * FROM User;"
|
|
357
173
|
```
|
|
@@ -361,143 +177,24 @@ npx wrangler d1 execute my-database --local \
|
|
|
361
177
|
## 배포
|
|
362
178
|
|
|
363
179
|
```bash
|
|
364
|
-
# Prisma Client 생성
|
|
365
180
|
npx prisma generate
|
|
366
|
-
|
|
367
|
-
# 원격 D1에 마이그레이션 적용
|
|
368
181
|
npx wrangler d1 migrations apply my-database --remote
|
|
369
|
-
|
|
370
|
-
# Worker 배포
|
|
371
182
|
npx wrangler deploy
|
|
372
183
|
```
|
|
373
184
|
|
|
374
185
|
---
|
|
375
186
|
|
|
376
|
-
##
|
|
377
|
-
|
|
378
|
-
### 트랜잭션 미지원
|
|
379
|
-
|
|
380
|
-
```typescript
|
|
381
|
-
// ❌ 트랜잭션이 무시됨 - ACID 보장 안됨
|
|
382
|
-
const prisma = c.get('prisma')
|
|
187
|
+
## 제한사항
|
|
383
188
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
// ❌ Interactive 트랜잭션도 미지원
|
|
390
|
-
await prisma.$transaction(async (tx) => {
|
|
391
|
-
// 각 쿼리가 독립적으로 실행됨
|
|
392
|
-
})
|
|
393
|
-
```
|
|
394
|
-
|
|
395
|
-
### D1 vs 일반 SQLite 차이점
|
|
396
|
-
|
|
397
|
-
| 항목 | 일반 SQLite | Cloudflare D1 |
|
|
398
|
-
|------|-------------|---------------|
|
|
399
|
-
| 마이그레이션 | `prisma migrate dev` | `wrangler d1 migrations` |
|
|
400
|
-
| 트랜잭션 | ✅ 지원 | ❌ 미지원 |
|
|
401
|
-
| 데이터베이스 위치 | 로컬 파일 | Cloudflare Edge |
|
|
402
|
-
| 접속 방식 | 직접 연결 | HTTP (어댑터) |
|
|
403
|
-
| 환경 | 로컬 `.wrangler/state` | 원격 Cloudflare |
|
|
404
|
-
|
|
405
|
-
---
|
|
406
|
-
|
|
407
|
-
## RPC 클라이언트와 함께 사용
|
|
408
|
-
|
|
409
|
-
```typescript
|
|
410
|
-
// src/index.ts
|
|
411
|
-
import { Hono } from 'hono'
|
|
412
|
-
import { hc } from 'hono/client'
|
|
413
|
-
import { PrismaClient } from './generated/prisma'
|
|
414
|
-
import { PrismaD1 } from '@prisma/adapter-d1'
|
|
415
|
-
|
|
416
|
-
type Bindings = {
|
|
417
|
-
DB: D1Database
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
const app = new Hono<{ Bindings: Bindings }>()
|
|
421
|
-
.get('/users', async (c) => {
|
|
422
|
-
const adapter = new PrismaD1(c.env.DB)
|
|
423
|
-
const prisma = new PrismaClient({ adapter })
|
|
424
|
-
|
|
425
|
-
const users = await prisma.user.findMany()
|
|
426
|
-
return c.json(users)
|
|
427
|
-
})
|
|
428
|
-
.post('/users', async (c) => {
|
|
429
|
-
const adapter = new PrismaD1(c.env.DB)
|
|
430
|
-
const prisma = new PrismaClient({ adapter })
|
|
431
|
-
|
|
432
|
-
const body = await c.req.json()
|
|
433
|
-
const user = await prisma.user.create({ data: body })
|
|
434
|
-
return c.json(user, 201)
|
|
435
|
-
})
|
|
436
|
-
|
|
437
|
-
export type AppType = typeof app
|
|
438
|
-
export default app
|
|
439
|
-
```
|
|
440
|
-
|
|
441
|
-
---
|
|
442
|
-
|
|
443
|
-
## prisma.config.ts (선택사항)
|
|
444
|
-
|
|
445
|
-
Prisma CLI에서 D1에 직접 접근이 필요한 경우:
|
|
446
|
-
|
|
447
|
-
```typescript
|
|
448
|
-
// prisma.config.ts
|
|
449
|
-
import path from 'node:path'
|
|
450
|
-
import type { PrismaConfig } from 'prisma'
|
|
451
|
-
import { PrismaD1 } from '@prisma/adapter-d1'
|
|
452
|
-
|
|
453
|
-
export default {
|
|
454
|
-
experimental: {
|
|
455
|
-
adapter: true,
|
|
456
|
-
},
|
|
457
|
-
engine: 'js',
|
|
458
|
-
schema: path.join('prisma', 'schema.prisma'),
|
|
459
|
-
async adapter() {
|
|
460
|
-
return new PrismaD1({
|
|
461
|
-
CLOUDFLARE_D1_TOKEN: process.env.CLOUDFLARE_D1_TOKEN,
|
|
462
|
-
CLOUDFLARE_ACCOUNT_ID: process.env.CLOUDFLARE_ACCOUNT_ID,
|
|
463
|
-
CLOUDFLARE_DATABASE_ID: process.env.CLOUDFLARE_DATABASE_ID,
|
|
464
|
-
})
|
|
465
|
-
},
|
|
466
|
-
} satisfies PrismaConfig
|
|
467
|
-
```
|
|
468
|
-
|
|
469
|
-
---
|
|
470
|
-
|
|
471
|
-
## 마이그레이션 명령어 요약
|
|
472
|
-
|
|
473
|
-
```bash
|
|
474
|
-
# D1 데이터베이스 생성
|
|
475
|
-
npx wrangler d1 create my-database
|
|
476
|
-
|
|
477
|
-
# 마이그레이션 파일 생성
|
|
478
|
-
npx wrangler d1 migrations create my-database migration_name
|
|
479
|
-
|
|
480
|
-
# SQL 생성 (초기)
|
|
481
|
-
npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script
|
|
482
|
-
|
|
483
|
-
# SQL 생성 (후속)
|
|
484
|
-
npx prisma migrate diff --from-local-d1 --to-schema-datamodel prisma/schema.prisma --script
|
|
485
|
-
|
|
486
|
-
# 로컬 적용
|
|
487
|
-
npx wrangler d1 migrations apply my-database --local
|
|
488
|
-
|
|
489
|
-
# 원격 적용
|
|
490
|
-
npx wrangler d1 migrations apply my-database --remote
|
|
491
|
-
|
|
492
|
-
# Prisma Client 생성
|
|
493
|
-
npx prisma generate
|
|
494
|
-
```
|
|
189
|
+
| 항목 | D1 |
|
|
190
|
+
|------|-----|
|
|
191
|
+
| 트랜잭션 | ❌ 미지원 |
|
|
192
|
+
| 마이그레이션 | wrangler 사용 |
|
|
193
|
+
| 접속 방식 | HTTP (어댑터) |
|
|
495
194
|
|
|
496
195
|
---
|
|
497
196
|
|
|
498
|
-
##
|
|
197
|
+
## 관련 문서
|
|
499
198
|
|
|
500
|
-
- [Prisma
|
|
501
|
-
- [Cloudflare
|
|
502
|
-
- [Prisma D1 가이드](https://www.prisma.io/guides/cloudflare-d1)
|
|
503
|
-
- [Hono Cloudflare Workers](https://hono.dev/docs/getting-started/cloudflare-workers)
|
|
199
|
+
- [Prisma 개요](./index.md)
|
|
200
|
+
- [Cloudflare 배포](../../deployment/cloudflare.md)
|