@kood/claude-code 0.3.7 → 0.3.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 +1 -1
- package/package.json +1 -1
- package/templates/.claude/agents/code-reviewer.md +138 -123
- package/templates/.claude/agents/dependency-manager.md +99 -84
- package/templates/.claude/agents/deployment-validator.md +70 -55
- package/templates/.claude/agents/git-operator.md +78 -63
- package/templates/.claude/agents/implementation-executor.md +109 -94
- package/templates/.claude/agents/ko-to-en-translator.md +74 -0
- package/templates/.claude/agents/lint-fixer.md +93 -78
- package/templates/.claude/agents/refactor-advisor.md +136 -121
- package/templates/.claude/commands/agent-creator.md +199 -184
- package/templates/.claude/commands/bug-fix.md +207 -192
- package/templates/.claude/commands/command-creator.md +69 -53
- package/templates/.claude/commands/docs-creator.md +72 -56
- package/templates/.claude/commands/docs-refactor.md +41 -25
- package/templates/.claude/commands/execute.md +27 -11
- package/templates/.claude/commands/git-all.md +46 -31
- package/templates/.claude/commands/git-session.md +57 -41
- package/templates/.claude/commands/git.md +49 -33
- package/templates/.claude/commands/lint-fix.md +153 -137
- package/templates/.claude/commands/lint-init.md +76 -60
- package/templates/.claude/commands/plan.md +275 -259
- package/templates/.claude/commands/prd.md +39 -23
- package/templates/.claude/commands/pre-deploy.md +124 -108
- package/templates/.claude/commands/refactor.md +162 -146
- package/templates/.claude/commands/version-update.md +32 -16
- package/templates/hono/CLAUDE.md +28 -27
- 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 -51
- package/templates/nextjs/docs/architecture.md +812 -0
- 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 -37
- 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 -53
- 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/better-auth/index.md +68 -68
- 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/index.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/t3-env/index.md +21 -160
- package/templates/tanstack-start/docs/library/tanstack-query/index.md +6 -6
- 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/index.md +18 -18
- 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/index.md +15 -15
- 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/index.md +8 -8
- package/templates/tanstack-start/docs/library/zod/transforms.md +11 -11
- package/templates/tanstack-start/docs/library/zod/validation.md +9 -9
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# Server Actions
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Type-safe server functions (React 19 Server Actions)
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Basic Usage
|
|
8
8
|
|
|
9
|
-
###
|
|
9
|
+
### File-level Declaration
|
|
10
10
|
|
|
11
11
|
```typescript
|
|
12
12
|
// app/actions.ts
|
|
@@ -28,7 +28,7 @@ export async function createPost(formData: FormData) {
|
|
|
28
28
|
}
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
###
|
|
31
|
+
### Inline Declaration
|
|
32
32
|
|
|
33
33
|
```typescript
|
|
34
34
|
// app/posts/page.tsx
|
|
@@ -46,7 +46,7 @@ export default function PostsPage() {
|
|
|
46
46
|
|
|
47
47
|
---
|
|
48
48
|
|
|
49
|
-
## Zod
|
|
49
|
+
## Zod Validation
|
|
50
50
|
|
|
51
51
|
```typescript
|
|
52
52
|
"use server"
|
|
@@ -74,7 +74,7 @@ export async function createPost(formData: FormData) {
|
|
|
74
74
|
|
|
75
75
|
---
|
|
76
76
|
|
|
77
|
-
##
|
|
77
|
+
## Authentication
|
|
78
78
|
|
|
79
79
|
```typescript
|
|
80
80
|
"use server"
|
|
@@ -92,7 +92,7 @@ export async function deletePost(id: string) {
|
|
|
92
92
|
await prisma.post.delete({
|
|
93
93
|
where: {
|
|
94
94
|
id,
|
|
95
|
-
userId: session.user.id, //
|
|
95
|
+
userId: session.user.id, // Delete only own posts
|
|
96
96
|
},
|
|
97
97
|
})
|
|
98
98
|
|
|
@@ -102,7 +102,7 @@ export async function deletePost(id: string) {
|
|
|
102
102
|
|
|
103
103
|
---
|
|
104
104
|
|
|
105
|
-
##
|
|
105
|
+
## Error Handling
|
|
106
106
|
|
|
107
107
|
```typescript
|
|
108
108
|
"use server"
|
|
@@ -116,14 +116,14 @@ export async function updatePost(id: string, data: PostInput) {
|
|
|
116
116
|
if (error instanceof z.ZodError) {
|
|
117
117
|
return { success: false, errors: error.errors }
|
|
118
118
|
}
|
|
119
|
-
return { success: false, message: "
|
|
119
|
+
return { success: false, message: "Update failed" }
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
122
|
```
|
|
123
123
|
|
|
124
124
|
---
|
|
125
125
|
|
|
126
|
-
##
|
|
126
|
+
## Client Usage
|
|
127
127
|
|
|
128
128
|
### Form Action
|
|
129
129
|
|
|
@@ -137,7 +137,7 @@ export function CreatePostForm() {
|
|
|
137
137
|
<form action={createPost}>
|
|
138
138
|
<input name="title" required />
|
|
139
139
|
<textarea name="content" required />
|
|
140
|
-
<button type="submit"
|
|
140
|
+
<button type="submit">Submit</button>
|
|
141
141
|
</form>
|
|
142
142
|
)
|
|
143
143
|
}
|
|
@@ -173,7 +173,7 @@ export function CreatePostForm() {
|
|
|
173
173
|
>
|
|
174
174
|
<input name="title" required />
|
|
175
175
|
<button type="submit" disabled={mutation.isPending}>
|
|
176
|
-
{mutation.isPending ? "
|
|
176
|
+
{mutation.isPending ? "Submitting..." : "Submit"}
|
|
177
177
|
</button>
|
|
178
178
|
</form>
|
|
179
179
|
)
|
|
@@ -191,7 +191,7 @@ export async function createPost(prevState: any, formData: FormData) {
|
|
|
191
191
|
const title = formData.get("title") as string
|
|
192
192
|
|
|
193
193
|
if (!title) {
|
|
194
|
-
return { error: "
|
|
194
|
+
return { error: "Please enter a title" }
|
|
195
195
|
}
|
|
196
196
|
|
|
197
197
|
const post = await prisma.post.create({ data: { title } })
|
|
@@ -212,7 +212,7 @@ export function CreatePostForm() {
|
|
|
212
212
|
<form action={formAction}>
|
|
213
213
|
<input name="title" />
|
|
214
214
|
{state?.error && <p>{state.error}</p>}
|
|
215
|
-
<button type="submit"
|
|
215
|
+
<button type="submit">Submit</button>
|
|
216
216
|
</form>
|
|
217
217
|
)
|
|
218
218
|
}
|
|
@@ -220,7 +220,7 @@ export function CreatePostForm() {
|
|
|
220
220
|
|
|
221
221
|
---
|
|
222
222
|
|
|
223
|
-
##
|
|
223
|
+
## Cache Invalidation
|
|
224
224
|
|
|
225
225
|
### revalidatePath
|
|
226
226
|
|
|
@@ -232,11 +232,11 @@ import { revalidatePath } from "next/cache"
|
|
|
232
232
|
export async function createPost(data: PostInput) {
|
|
233
233
|
const post = await prisma.post.create({ data })
|
|
234
234
|
|
|
235
|
-
//
|
|
235
|
+
// Invalidate specific path cache
|
|
236
236
|
revalidatePath("/posts")
|
|
237
237
|
revalidatePath(`/posts/${post.id}`)
|
|
238
238
|
|
|
239
|
-
//
|
|
239
|
+
// Invalidate all caches including layouts
|
|
240
240
|
revalidatePath("/posts", "layout")
|
|
241
241
|
|
|
242
242
|
return post
|
|
@@ -246,19 +246,19 @@ export async function createPost(data: PostInput) {
|
|
|
246
246
|
### revalidateTag
|
|
247
247
|
|
|
248
248
|
```typescript
|
|
249
|
-
//
|
|
249
|
+
// Set tag when fetching data
|
|
250
250
|
const posts = await fetch("https://api.example.com/posts", {
|
|
251
251
|
next: { tags: ["posts"] },
|
|
252
252
|
})
|
|
253
253
|
|
|
254
|
-
// Server Action
|
|
254
|
+
// Invalidate tag in Server Action
|
|
255
255
|
"use server"
|
|
256
256
|
|
|
257
257
|
import { revalidateTag } from "next/cache"
|
|
258
258
|
|
|
259
259
|
export async function createPost(data: PostInput) {
|
|
260
260
|
const post = await prisma.post.create({ data })
|
|
261
|
-
revalidateTag("posts") // "posts"
|
|
261
|
+
revalidateTag("posts") // Invalidate "posts" tag cache
|
|
262
262
|
return post
|
|
263
263
|
}
|
|
264
264
|
```
|
|
@@ -279,13 +279,13 @@ export async function createPost(formData: FormData) {
|
|
|
279
279
|
},
|
|
280
280
|
})
|
|
281
281
|
|
|
282
|
-
redirect(`/posts/${post.id}`) //
|
|
282
|
+
redirect(`/posts/${post.id}`) // Navigate to page
|
|
283
283
|
}
|
|
284
284
|
```
|
|
285
285
|
|
|
286
286
|
---
|
|
287
287
|
|
|
288
|
-
##
|
|
288
|
+
## File Upload
|
|
289
289
|
|
|
290
290
|
```typescript
|
|
291
291
|
"use server"
|
|
@@ -297,7 +297,7 @@ export async function uploadFile(formData: FormData) {
|
|
|
297
297
|
const file = formData.get("file") as File
|
|
298
298
|
|
|
299
299
|
if (!file) {
|
|
300
|
-
throw new Error("
|
|
300
|
+
throw new Error("No file provided")
|
|
301
301
|
}
|
|
302
302
|
|
|
303
303
|
const bytes = await file.arrayBuffer()
|
|
@@ -312,17 +312,17 @@ export async function uploadFile(formData: FormData) {
|
|
|
312
312
|
|
|
313
313
|
---
|
|
314
314
|
|
|
315
|
-
##
|
|
315
|
+
## Best Practices
|
|
316
316
|
|
|
317
317
|
### ✅ DO
|
|
318
318
|
|
|
319
319
|
```typescript
|
|
320
320
|
"use server"
|
|
321
321
|
|
|
322
|
-
// 1. Zod
|
|
322
|
+
// 1. Zod validation
|
|
323
323
|
const schema = z.object({ title: z.string().min(1) })
|
|
324
324
|
|
|
325
|
-
// 2.
|
|
325
|
+
// 2. Authentication check
|
|
326
326
|
const session = await auth()
|
|
327
327
|
if (!session) throw new Error("Unauthorized")
|
|
328
328
|
|
|
@@ -332,35 +332,35 @@ try {
|
|
|
332
332
|
revalidatePath("/posts")
|
|
333
333
|
return { success: true, post }
|
|
334
334
|
} catch (error) {
|
|
335
|
-
return { success: false, message: "
|
|
335
|
+
return { success: false, message: "Creation failed" }
|
|
336
336
|
}
|
|
337
337
|
```
|
|
338
338
|
|
|
339
339
|
### ❌ DON'T
|
|
340
340
|
|
|
341
341
|
```typescript
|
|
342
|
-
// 1.
|
|
342
|
+
// 1. Defining Server Action in Client Component
|
|
343
343
|
"use client"
|
|
344
344
|
|
|
345
345
|
async function createPost() {
|
|
346
|
-
"use server" // ❌
|
|
346
|
+
"use server" // ❌ Error
|
|
347
347
|
}
|
|
348
348
|
|
|
349
|
-
// 2.
|
|
349
|
+
// 2. Using without validation
|
|
350
350
|
export async function createPost(formData: FormData) {
|
|
351
|
-
const title = formData.get("title") // ❌
|
|
351
|
+
const title = formData.get("title") // ❌ Missing validation
|
|
352
352
|
await prisma.post.create({ data: { title } })
|
|
353
353
|
}
|
|
354
354
|
|
|
355
|
-
// 3. try-catch
|
|
355
|
+
// 3. Using without try-catch
|
|
356
356
|
export async function createPost(data: PostInput) {
|
|
357
|
-
const post = await prisma.post.create({ data }) // ❌
|
|
357
|
+
const post = await prisma.post.create({ data }) // ❌ Missing error handling
|
|
358
358
|
return post
|
|
359
359
|
}
|
|
360
360
|
```
|
|
361
361
|
|
|
362
362
|
---
|
|
363
363
|
|
|
364
|
-
##
|
|
364
|
+
## References
|
|
365
365
|
|
|
366
366
|
- [Next.js Server Actions](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations)
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
# Prisma - Cloudflare D1
|
|
2
2
|
|
|
3
|
-
SQLite
|
|
3
|
+
SQLite-based serverless database. Different workflow from standard Prisma migrations.
|
|
4
4
|
|
|
5
|
-
⚠️
|
|
5
|
+
⚠️ No transaction support | Cannot use prisma migrate - use wrangler instead | Preview status
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Setup
|
|
8
8
|
|
|
9
9
|
```prisma
|
|
10
10
|
// schema.prisma
|
|
11
11
|
generator client {
|
|
12
12
|
provider = "prisma-client"
|
|
13
13
|
output = "../src/generated/prisma"
|
|
14
|
-
runtime = "cloudflare" //
|
|
14
|
+
runtime = "cloudflare" // required
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
datasource db {
|
|
@@ -26,7 +26,7 @@ datasource db {
|
|
|
26
26
|
}
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
##
|
|
29
|
+
## Usage
|
|
30
30
|
|
|
31
31
|
```typescript
|
|
32
32
|
import { PrismaClient } from './generated/prisma'
|
|
@@ -44,33 +44,33 @@ export default {
|
|
|
44
44
|
}
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
##
|
|
47
|
+
## Migration Workflow
|
|
48
48
|
|
|
49
49
|
```bash
|
|
50
|
-
# 1. D1
|
|
50
|
+
# 1. Create D1
|
|
51
51
|
npx wrangler d1 create my-database
|
|
52
52
|
|
|
53
|
-
# 2.
|
|
53
|
+
# 2. Create migration
|
|
54
54
|
npx wrangler d1 migrations create my-database init
|
|
55
55
|
|
|
56
|
-
# 3. SQL
|
|
56
|
+
# 3. Generate SQL (initial)
|
|
57
57
|
npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script --output prisma/migrations/0001.sql
|
|
58
58
|
|
|
59
|
-
# 4. SQL
|
|
59
|
+
# 4. Generate SQL (subsequent)
|
|
60
60
|
npx prisma migrate diff --from-local-d1 --to-schema-datamodel prisma/schema.prisma --script
|
|
61
61
|
|
|
62
|
-
# 5.
|
|
63
|
-
npx wrangler d1 migrations apply my-database --local #
|
|
64
|
-
npx wrangler d1 migrations apply my-database --remote #
|
|
62
|
+
# 5. Apply
|
|
63
|
+
npx wrangler d1 migrations apply my-database --local # local
|
|
64
|
+
npx wrangler d1 migrations apply my-database --remote # production
|
|
65
65
|
|
|
66
|
-
# 6.
|
|
66
|
+
# 6. Generate client
|
|
67
67
|
npx prisma generate
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
##
|
|
70
|
+
## Limitations
|
|
71
71
|
|
|
72
|
-
|
|
|
73
|
-
|
|
74
|
-
|
|
|
75
|
-
|
|
|
76
|
-
|
|
|
72
|
+
| Feature | Regular SQLite | D1 |
|
|
73
|
+
|---------|----------------|-----|
|
|
74
|
+
| Migration | prisma migrate | wrangler d1 |
|
|
75
|
+
| Transaction | ✅ | ❌ |
|
|
76
|
+
| Connection | Direct | HTTP adapter |
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# Prisma - Config
|
|
1
|
+
# Prisma - Config File
|
|
2
2
|
|
|
3
|
-
Prisma v7 `prisma.config.ts`
|
|
3
|
+
Prisma v7 `prisma.config.ts` configuration.
|
|
4
4
|
|
|
5
|
-
## Multi-File
|
|
5
|
+
## Multi-File Schema (Required)
|
|
6
6
|
|
|
7
7
|
```typescript
|
|
8
8
|
// prisma.config.ts
|
|
@@ -11,7 +11,7 @@ import path from 'node:path'
|
|
|
11
11
|
import { defineConfig, env } from 'prisma/config'
|
|
12
12
|
|
|
13
13
|
export default defineConfig({
|
|
14
|
-
schema: path.join('prisma', 'schema'), //
|
|
14
|
+
schema: path.join('prisma', 'schema'), // folder path!
|
|
15
15
|
migrations: {
|
|
16
16
|
path: 'prisma/migrations',
|
|
17
17
|
seed: 'tsx prisma/seed.ts',
|
|
@@ -22,16 +22,16 @@ export default defineConfig({
|
|
|
22
22
|
})
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
##
|
|
25
|
+
## Folder Structure
|
|
26
26
|
|
|
27
27
|
```
|
|
28
|
-
|
|
28
|
+
project/
|
|
29
29
|
├── prisma.config.ts
|
|
30
30
|
├── prisma/
|
|
31
31
|
│ ├── schema/
|
|
32
32
|
│ │ ├── +base.prisma # datasource, generator
|
|
33
|
-
│ │ ├── +enum.prisma # enum
|
|
34
|
-
│ │ └── user.prisma #
|
|
33
|
+
│ │ ├── +enum.prisma # enum definitions
|
|
34
|
+
│ │ └── user.prisma # models
|
|
35
35
|
│ └── migrations/
|
|
36
36
|
```
|
|
37
37
|
|
|
@@ -49,17 +49,17 @@ generator client {
|
|
|
49
49
|
}
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
##
|
|
52
|
+
## Configuration Options
|
|
53
53
|
|
|
54
|
-
|
|
|
55
|
-
|
|
56
|
-
| `schema` |
|
|
57
|
-
| `datasource.url` |
|
|
58
|
-
| `datasource.shadowDatabaseUrl` | Shadow
|
|
59
|
-
| `migrations.path` |
|
|
60
|
-
| `migrations.seed` |
|
|
54
|
+
| Option | Description |
|
|
55
|
+
|--------|-------------|
|
|
56
|
+
| `schema` | Schema folder path |
|
|
57
|
+
| `datasource.url` | Database URL (required) |
|
|
58
|
+
| `datasource.shadowDatabaseUrl` | Shadow database URL |
|
|
59
|
+
| `migrations.path` | Migrations folder |
|
|
60
|
+
| `migrations.seed` | Seed command |
|
|
61
61
|
|
|
62
|
-
##
|
|
62
|
+
## Seed File
|
|
63
63
|
|
|
64
64
|
```typescript
|
|
65
65
|
// prisma/seed.ts
|
|
@@ -69,7 +69,7 @@ const prisma = new PrismaClient()
|
|
|
69
69
|
|
|
70
70
|
async function main() {
|
|
71
71
|
await prisma.user.create({
|
|
72
|
-
data: { email: 'admin@example.com', name: '
|
|
72
|
+
data: { email: 'admin@example.com', name: 'Admin', role: 'ADMIN' },
|
|
73
73
|
})
|
|
74
74
|
}
|
|
75
75
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
# Prisma - CRUD
|
|
1
|
+
# Prisma - CRUD Operations
|
|
2
2
|
|
|
3
3
|
## Create
|
|
4
4
|
|
|
5
5
|
```typescript
|
|
6
|
-
//
|
|
6
|
+
// Single
|
|
7
7
|
const user = await prisma.user.create({
|
|
8
8
|
data: { email: 'alice@prisma.io', name: 'Alice' },
|
|
9
9
|
})
|
|
10
10
|
|
|
11
|
-
//
|
|
11
|
+
// With relations
|
|
12
12
|
const user = await prisma.user.create({
|
|
13
13
|
data: {
|
|
14
14
|
email: 'bob@prisma.io',
|
|
@@ -27,22 +27,22 @@ posts: { create: [{
|
|
|
27
27
|
## Read
|
|
28
28
|
|
|
29
29
|
```typescript
|
|
30
|
-
//
|
|
30
|
+
// Single
|
|
31
31
|
const user = await prisma.user.findUnique({ where: { email } })
|
|
32
32
|
|
|
33
|
-
//
|
|
33
|
+
// Multiple
|
|
34
34
|
const users = await prisma.user.findMany({ where: { name: 'Alice' } })
|
|
35
35
|
|
|
36
|
-
//
|
|
36
|
+
// With relations
|
|
37
37
|
const users = await prisma.user.findMany({ where: { role: 'ADMIN' }, include: { posts: true } })
|
|
38
38
|
|
|
39
|
-
//
|
|
39
|
+
// Select fields
|
|
40
40
|
const user = await prisma.user.findUnique({
|
|
41
41
|
where: { email },
|
|
42
42
|
select: { email: true, posts: { select: { title: true } } },
|
|
43
43
|
})
|
|
44
44
|
|
|
45
|
-
//
|
|
45
|
+
// Filter by relation
|
|
46
46
|
const users = await prisma.user.findMany({
|
|
47
47
|
where: { posts: { some: { published: false } } },
|
|
48
48
|
})
|
|
@@ -51,10 +51,10 @@ const users = await prisma.user.findMany({
|
|
|
51
51
|
## Update
|
|
52
52
|
|
|
53
53
|
```typescript
|
|
54
|
-
//
|
|
54
|
+
// Single
|
|
55
55
|
const user = await prisma.user.update({ where: { id }, data: { name: 'Updated' } })
|
|
56
56
|
|
|
57
|
-
//
|
|
57
|
+
// Multiple
|
|
58
58
|
await prisma.user.updateMany({ where: { role: 'USER' }, data: { role: 'ADMIN' } })
|
|
59
59
|
|
|
60
60
|
// Upsert
|
|
@@ -69,22 +69,22 @@ const user = await prisma.user.upsert({
|
|
|
69
69
|
|
|
70
70
|
```typescript
|
|
71
71
|
await prisma.user.delete({ where: { id } })
|
|
72
|
-
await prisma.user.deleteMany({}) //
|
|
73
|
-
await prisma.post.deleteMany({ where: { published: false } }) //
|
|
72
|
+
await prisma.user.deleteMany({}) // all
|
|
73
|
+
await prisma.post.deleteMany({ where: { published: false } }) // conditional
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
##
|
|
76
|
+
## Filter Operators
|
|
77
77
|
|
|
78
78
|
```typescript
|
|
79
|
-
//
|
|
79
|
+
// String
|
|
80
80
|
{ contains: 'prisma', startsWith: 'A', endsWith: 'io' }
|
|
81
81
|
|
|
82
|
-
//
|
|
82
|
+
// Number
|
|
83
83
|
{ gt: 18, gte: 18, lt: 65, lte: 65 }
|
|
84
84
|
|
|
85
|
-
//
|
|
85
|
+
// Array
|
|
86
86
|
{ in: [1, 2, 3], notIn: [4, 5] }
|
|
87
87
|
|
|
88
|
-
//
|
|
88
|
+
// Logical
|
|
89
89
|
{ OR: [...], AND: [...], NOT: {...} }
|
|
90
90
|
```
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
## Quick Reference
|
|
16
16
|
|
|
17
17
|
```typescript
|
|
18
|
-
import { PrismaClient } from './generated/prisma' // v7
|
|
18
|
+
import { PrismaClient } from './generated/prisma' // v7 path!
|
|
19
19
|
export const prisma = new PrismaClient()
|
|
20
20
|
|
|
21
21
|
// CRUD
|
|
@@ -24,34 +24,34 @@ const user = await prisma.user.create({ data: { email, name } })
|
|
|
24
24
|
const updated = await prisma.user.update({ where: { id }, data: { name } })
|
|
25
25
|
const deleted = await prisma.user.delete({ where: { id } })
|
|
26
26
|
|
|
27
|
-
//
|
|
27
|
+
// With relations
|
|
28
28
|
const userWithPosts = await prisma.user.findUnique({
|
|
29
29
|
where: { id },
|
|
30
30
|
include: { posts: true },
|
|
31
31
|
})
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
### v7 schema.prisma (⚠️
|
|
34
|
+
### v7 schema.prisma (⚠️ Important)
|
|
35
35
|
|
|
36
36
|
```prisma
|
|
37
37
|
generator client {
|
|
38
|
-
provider = "prisma-client" // v7! (prisma-client-js
|
|
39
|
-
output = "../generated/prisma" // output
|
|
38
|
+
provider = "prisma-client" // v7! (not prisma-client-js)
|
|
39
|
+
output = "../generated/prisma" // output required!
|
|
40
40
|
}
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
### ⛔ Claude Code
|
|
43
|
+
### ⛔ Claude Code Forbidden
|
|
44
44
|
|
|
45
|
-
|
|
|
46
|
-
|
|
47
|
-
| prisma db push
|
|
48
|
-
| prisma migrate
|
|
49
|
-
| prisma generate
|
|
50
|
-
| schema.prisma
|
|
45
|
+
| Forbidden Actions |
|
|
46
|
+
|-------------------|
|
|
47
|
+
| Auto-running prisma db push |
|
|
48
|
+
| Auto-running prisma migrate |
|
|
49
|
+
| Auto-running prisma generate |
|
|
50
|
+
| Unauthorized schema.prisma modifications |
|
|
51
51
|
|
|
52
52
|
---
|
|
53
53
|
|
|
54
|
-
## Prisma Client
|
|
54
|
+
## Prisma Client Setup
|
|
55
55
|
|
|
56
56
|
```typescript
|
|
57
57
|
// lib/prisma.ts
|
|
@@ -62,12 +62,12 @@ export const prisma = globalForPrisma.prisma ?? new PrismaClient({ log: ['query'
|
|
|
62
62
|
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
##
|
|
65
|
+
## Migration Commands
|
|
66
66
|
|
|
67
67
|
```bash
|
|
68
|
-
npx prisma migrate dev --name init #
|
|
69
|
-
npx prisma migrate deploy #
|
|
70
|
-
npx prisma db push #
|
|
71
|
-
npx prisma generate #
|
|
68
|
+
npx prisma migrate dev --name init # development migration
|
|
69
|
+
npx prisma migrate deploy # production migration
|
|
70
|
+
npx prisma db push # schema sync (dev only)
|
|
71
|
+
npx prisma generate # generate client
|
|
72
72
|
npx prisma studio # GUI
|
|
73
73
|
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# Prisma -
|
|
1
|
+
# Prisma - Relation Queries
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Nested Create
|
|
4
4
|
|
|
5
5
|
```typescript
|
|
6
6
|
const user = await prisma.user.create({
|
|
@@ -12,53 +12,53 @@ const user = await prisma.user.create({
|
|
|
12
12
|
})
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## Connect Relations
|
|
16
16
|
|
|
17
17
|
```typescript
|
|
18
|
-
// connect -
|
|
18
|
+
// connect - connect existing
|
|
19
19
|
author: { connect: { id: 1 } }
|
|
20
20
|
|
|
21
|
-
// connectOrCreate -
|
|
21
|
+
// connectOrCreate - connect if exists, create if not
|
|
22
22
|
categories: { connectOrCreate: { where: { name: 'Tech' }, create: { name: 'Tech' } } }
|
|
23
23
|
|
|
24
|
-
// disconnect -
|
|
24
|
+
// disconnect - disconnect relation
|
|
25
25
|
author: { disconnect: true }
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
##
|
|
28
|
+
## Include Relations
|
|
29
29
|
|
|
30
30
|
```typescript
|
|
31
31
|
// include
|
|
32
32
|
const users = await prisma.user.findMany({ include: { posts: true, profile: true } })
|
|
33
33
|
|
|
34
|
-
//
|
|
34
|
+
// nested
|
|
35
35
|
include: { posts: { include: { categories: true } } }
|
|
36
36
|
|
|
37
|
-
//
|
|
37
|
+
// filter + sort
|
|
38
38
|
include: { posts: { where: { published: true }, orderBy: { createdAt: 'desc' }, take: 5 } }
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
##
|
|
41
|
+
## Filter by Relations
|
|
42
42
|
|
|
43
43
|
```typescript
|
|
44
|
-
// some -
|
|
44
|
+
// some - at least one matches
|
|
45
45
|
where: { posts: { some: { published: true } } }
|
|
46
46
|
|
|
47
|
-
// every -
|
|
47
|
+
// every - all match
|
|
48
48
|
where: { posts: { every: { published: true } } }
|
|
49
49
|
|
|
50
|
-
// none -
|
|
50
|
+
// none - none match
|
|
51
51
|
where: { posts: { none: { published: false } } }
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
##
|
|
54
|
+
## Count
|
|
55
55
|
|
|
56
56
|
```typescript
|
|
57
57
|
include: { _count: { select: { posts: true } } }
|
|
58
|
-
//
|
|
58
|
+
// result: { _count: { posts: 5 } }
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
-
##
|
|
61
|
+
## Nested Update/Delete
|
|
62
62
|
|
|
63
63
|
```typescript
|
|
64
64
|
// updateMany
|