@kood/claude-code 0.3.6 → 0.3.8

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.
Files changed (120) hide show
  1. package/dist/index.js +1 -1
  2. package/package.json +1 -1
  3. package/templates/.claude/agents/code-reviewer.md +124 -124
  4. package/templates/.claude/agents/dependency-manager.md +85 -85
  5. package/templates/.claude/agents/deployment-validator.md +56 -56
  6. package/templates/.claude/agents/git-operator.md +64 -64
  7. package/templates/.claude/agents/implementation-executor.md +95 -95
  8. package/templates/.claude/agents/ko-to-en-translator.md +74 -0
  9. package/templates/.claude/agents/lint-fixer.md +78 -78
  10. package/templates/.claude/agents/refactor-advisor.md +122 -122
  11. package/templates/.claude/commands/agent-creator.md +185 -185
  12. package/templates/.claude/commands/bug-fix.md +193 -193
  13. package/templates/.claude/commands/command-creator.md +54 -54
  14. package/templates/.claude/commands/docs-creator.md +57 -57
  15. package/templates/.claude/commands/docs-refactor.md +26 -26
  16. package/templates/.claude/commands/execute.md +12 -12
  17. package/templates/.claude/commands/git-all.md +32 -32
  18. package/templates/.claude/commands/git-session.md +42 -42
  19. package/templates/.claude/commands/git.md +34 -34
  20. package/templates/.claude/commands/lint-fix.md +138 -138
  21. package/templates/.claude/commands/lint-init.md +61 -61
  22. package/templates/.claude/commands/plan.md +260 -260
  23. package/templates/.claude/commands/prd.md +24 -24
  24. package/templates/.claude/commands/pre-deploy.md +109 -109
  25. package/templates/.claude/commands/refactor.md +147 -147
  26. package/templates/.claude/commands/version-update.md +17 -17
  27. package/templates/hono/CLAUDE.md +27 -27
  28. package/templates/hono/docs/architecture.md +24 -24
  29. package/templates/hono/docs/deployment/cloudflare.md +18 -18
  30. package/templates/hono/docs/deployment/docker.md +13 -13
  31. package/templates/hono/docs/deployment/index.md +19 -19
  32. package/templates/hono/docs/deployment/railway.md +32 -32
  33. package/templates/hono/docs/deployment/vercel.md +29 -29
  34. package/templates/hono/docs/guides/conventions.md +57 -57
  35. package/templates/hono/docs/guides/env-setup.md +47 -47
  36. package/templates/hono/docs/guides/getting-started.md +27 -27
  37. package/templates/hono/docs/library/hono/error-handling.md +11 -11
  38. package/templates/hono/docs/library/hono/index.md +4 -4
  39. package/templates/hono/docs/library/hono/middleware.md +18 -18
  40. package/templates/hono/docs/library/hono/rpc.md +7 -7
  41. package/templates/hono/docs/library/hono/validation.md +6 -6
  42. package/templates/hono/docs/library/prisma/cloudflare-d1.md +29 -29
  43. package/templates/hono/docs/library/prisma/config.md +16 -16
  44. package/templates/hono/docs/library/prisma/index.md +32 -32
  45. package/templates/hono/docs/library/t3-env/index.md +22 -22
  46. package/templates/hono/docs/library/zod/index.md +31 -31
  47. package/templates/nextjs/CLAUDE.md +228 -0
  48. package/templates/nextjs/docs/design.md +558 -0
  49. package/templates/nextjs/docs/guides/conventions.md +343 -0
  50. package/templates/nextjs/docs/guides/getting-started.md +367 -0
  51. package/templates/nextjs/docs/guides/routes.md +342 -0
  52. package/templates/nextjs/docs/library/better-auth/index.md +541 -0
  53. package/templates/nextjs/docs/library/nextjs/app-router.md +269 -0
  54. package/templates/nextjs/docs/library/nextjs/caching.md +351 -0
  55. package/templates/nextjs/docs/library/nextjs/index.md +291 -0
  56. package/templates/nextjs/docs/library/nextjs/middleware.md +391 -0
  57. package/templates/nextjs/docs/library/nextjs/route-handlers.md +382 -0
  58. package/templates/nextjs/docs/library/nextjs/server-actions.md +366 -0
  59. package/templates/nextjs/docs/library/prisma/cloudflare-d1.md +76 -0
  60. package/templates/nextjs/docs/library/prisma/config.md +77 -0
  61. package/templates/nextjs/docs/library/prisma/crud.md +90 -0
  62. package/templates/nextjs/docs/library/prisma/index.md +73 -0
  63. package/templates/nextjs/docs/library/prisma/relations.md +69 -0
  64. package/templates/nextjs/docs/library/prisma/schema.md +98 -0
  65. package/templates/nextjs/docs/library/prisma/setup.md +49 -0
  66. package/templates/nextjs/docs/library/prisma/transactions.md +50 -0
  67. package/templates/nextjs/docs/library/tanstack-query/index.md +66 -0
  68. package/templates/nextjs/docs/library/tanstack-query/invalidation.md +54 -0
  69. package/templates/nextjs/docs/library/tanstack-query/optimistic-updates.md +77 -0
  70. package/templates/nextjs/docs/library/tanstack-query/use-mutation.md +63 -0
  71. package/templates/nextjs/docs/library/tanstack-query/use-query.md +70 -0
  72. package/templates/nextjs/docs/library/zod/complex-types.md +61 -0
  73. package/templates/nextjs/docs/library/zod/index.md +56 -0
  74. package/templates/nextjs/docs/library/zod/transforms.md +51 -0
  75. package/templates/nextjs/docs/library/zod/validation.md +70 -0
  76. package/templates/npx/CLAUDE.md +37 -37
  77. package/templates/npx/docs/library/commander/index.md +12 -12
  78. package/templates/npx/docs/library/fs-extra/index.md +9 -9
  79. package/templates/npx/docs/library/prompts/index.md +3 -3
  80. package/templates/npx/docs/references/patterns.md +12 -12
  81. package/templates/tanstack-start/CLAUDE.md +53 -49
  82. package/templates/tanstack-start/docs/architecture.md +128 -128
  83. package/templates/tanstack-start/docs/design.md +169 -169
  84. package/templates/tanstack-start/docs/guides/conventions.md +43 -43
  85. package/templates/tanstack-start/docs/guides/env-setup.md +35 -35
  86. package/templates/tanstack-start/docs/guides/getting-started.md +19 -19
  87. package/templates/tanstack-start/docs/guides/hooks.md +63 -35
  88. package/templates/tanstack-start/docs/guides/routes.md +61 -42
  89. package/templates/tanstack-start/docs/guides/services.md +45 -45
  90. package/templates/tanstack-start/docs/library/better-auth/index.md +68 -68
  91. package/templates/tanstack-start/docs/library/prisma/cloudflare-d1.md +19 -19
  92. package/templates/tanstack-start/docs/library/prisma/config.md +16 -16
  93. package/templates/tanstack-start/docs/library/prisma/crud.md +17 -17
  94. package/templates/tanstack-start/docs/library/prisma/index.md +17 -17
  95. package/templates/tanstack-start/docs/library/prisma/relations.md +16 -16
  96. package/templates/tanstack-start/docs/library/prisma/schema.md +23 -23
  97. package/templates/tanstack-start/docs/library/prisma/setup.md +6 -6
  98. package/templates/tanstack-start/docs/library/prisma/transactions.md +10 -10
  99. package/templates/tanstack-start/docs/library/t3-env/index.md +21 -160
  100. package/templates/tanstack-start/docs/library/tanstack-query/index.md +6 -6
  101. package/templates/tanstack-start/docs/library/tanstack-query/invalidation.md +19 -19
  102. package/templates/tanstack-start/docs/library/tanstack-query/optimistic-updates.md +4 -4
  103. package/templates/tanstack-start/docs/library/tanstack-query/use-mutation.md +14 -14
  104. package/templates/tanstack-start/docs/library/tanstack-query/use-query.md +21 -21
  105. package/templates/tanstack-start/docs/library/tanstack-router/error-handling.md +9 -9
  106. package/templates/tanstack-start/docs/library/tanstack-router/hooks.md +11 -11
  107. package/templates/tanstack-start/docs/library/tanstack-router/index.md +18 -18
  108. package/templates/tanstack-start/docs/library/tanstack-router/navigation.md +17 -17
  109. package/templates/tanstack-start/docs/library/tanstack-router/route-context.md +5 -5
  110. package/templates/tanstack-start/docs/library/tanstack-router/search-params.md +10 -10
  111. package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +8 -8
  112. package/templates/tanstack-start/docs/library/tanstack-start/index.md +15 -15
  113. package/templates/tanstack-start/docs/library/tanstack-start/middleware.md +9 -9
  114. package/templates/tanstack-start/docs/library/tanstack-start/routing.md +6 -6
  115. package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +18 -18
  116. package/templates/tanstack-start/docs/library/tanstack-start/setup.md +4 -4
  117. package/templates/tanstack-start/docs/library/zod/complex-types.md +11 -11
  118. package/templates/tanstack-start/docs/library/zod/index.md +8 -8
  119. package/templates/tanstack-start/docs/library/zod/transforms.md +11 -11
  120. package/templates/tanstack-start/docs/library/zod/validation.md +9 -9
@@ -0,0 +1,69 @@
1
+ # Prisma - Relation Queries
2
+
3
+ ## Nested Create
4
+
5
+ ```typescript
6
+ const user = await prisma.user.create({
7
+ data: {
8
+ email: 'user@prisma.io',
9
+ posts: { create: [{ title: 'Post 1' }, { title: 'Post 2' }] },
10
+ },
11
+ include: { posts: true },
12
+ })
13
+ ```
14
+
15
+ ## Connect Relations
16
+
17
+ ```typescript
18
+ // connect - connect existing
19
+ author: { connect: { id: 1 } }
20
+
21
+ // connectOrCreate - connect if exists, create if not
22
+ categories: { connectOrCreate: { where: { name: 'Tech' }, create: { name: 'Tech' } } }
23
+
24
+ // disconnect - disconnect relation
25
+ author: { disconnect: true }
26
+ ```
27
+
28
+ ## Include Relations
29
+
30
+ ```typescript
31
+ // include
32
+ const users = await prisma.user.findMany({ include: { posts: true, profile: true } })
33
+
34
+ // nested
35
+ include: { posts: { include: { categories: true } } }
36
+
37
+ // filter + sort
38
+ include: { posts: { where: { published: true }, orderBy: { createdAt: 'desc' }, take: 5 } }
39
+ ```
40
+
41
+ ## Filter by Relations
42
+
43
+ ```typescript
44
+ // some - at least one matches
45
+ where: { posts: { some: { published: true } } }
46
+
47
+ // every - all match
48
+ where: { posts: { every: { published: true } } }
49
+
50
+ // none - none match
51
+ where: { posts: { none: { published: false } } }
52
+ ```
53
+
54
+ ## Count
55
+
56
+ ```typescript
57
+ include: { _count: { select: { posts: true } } }
58
+ // result: { _count: { posts: 5 } }
59
+ ```
60
+
61
+ ## Nested Update/Delete
62
+
63
+ ```typescript
64
+ // updateMany
65
+ posts: { updateMany: { where: { published: false }, data: { published: true } } }
66
+
67
+ // deleteMany
68
+ posts: { deleteMany: { where: { published: false } } }
69
+ ```
@@ -0,0 +1,98 @@
1
+ # Prisma - Schema Definition (Multi-File)
2
+
3
+ ## ⚠️ Required Rules
4
+
5
+ 1. **Use Multi-File structure**
6
+ 2. **Add comments to all elements** (files, models, fields, enums)
7
+
8
+ ## Structure
9
+
10
+ ```
11
+ prisma/schema/
12
+ ├── +base.prisma # datasource, generator
13
+ ├── +enum.prisma # all enums
14
+ ├── user.prisma # User model
15
+ └── post.prisma # Post model
16
+ ```
17
+
18
+ ## Example
19
+
20
+ ```prisma
21
+ // +base.prisma
22
+ datasource db {
23
+ provider = "postgresql"
24
+ url = env("DATABASE_URL")
25
+ }
26
+
27
+ generator client {
28
+ provider = "prisma-client"
29
+ output = "../generated/prisma"
30
+ }
31
+
32
+ // +enum.prisma
33
+ enum Role {
34
+ USER // regular user
35
+ ADMIN // administrator
36
+ }
37
+
38
+ // user.prisma
39
+ model User {
40
+ id Int @id @default(autoincrement())
41
+ email String @unique // login email
42
+ name String? // display name
43
+ role Role @default(USER)
44
+ posts Post[] // authored posts (1:N)
45
+ profile Profile? // user profile (1:1)
46
+ createdAt DateTime @default(now())
47
+ updatedAt DateTime @updatedAt
48
+ }
49
+ ```
50
+
51
+ ## Relation Types
52
+
53
+ ```prisma
54
+ // 1:1
55
+ model Profile {
56
+ id Int @id @default(autoincrement())
57
+ user User @relation(fields: [userId], references: [id])
58
+ userId Int @unique
59
+ }
60
+
61
+ // 1:N
62
+ model Post {
63
+ author User @relation(fields: [authorId], references: [id])
64
+ authorId Int
65
+ }
66
+
67
+ // M:N (implicit)
68
+ model Post { categories Category[] }
69
+ model Category { posts Post[] }
70
+
71
+ // M:N (explicit)
72
+ model CategoriesOnPosts {
73
+ post Post @relation(fields: [postId], references: [id])
74
+ postId Int
75
+ category Category @relation(fields: [categoryId], references: [id])
76
+ categoryId Int
77
+ @@id([postId, categoryId])
78
+ }
79
+ ```
80
+
81
+ ## Others
82
+
83
+ ```prisma
84
+ // Optional relation
85
+ author User? @relation(fields: [authorId], references: [id])
86
+ authorId Int?
87
+
88
+ // Index
89
+ @@index([authorId])
90
+ @@index([createdAt])
91
+
92
+ // Composite key
93
+ @@id([postId, tagId])
94
+
95
+ // Mapping
96
+ @map("user_id")
97
+ @@map("users")
98
+ ```
@@ -0,0 +1,49 @@
1
+ # Prisma - Installation and Setup
2
+
3
+ ## Installation
4
+
5
+ ```bash
6
+ yarn add @prisma/client@7
7
+ yarn add -D prisma@7
8
+ npx prisma init
9
+ ```
10
+
11
+ ## v6 → v7 Upgrade
12
+
13
+ ```prisma
14
+ // v6 (old)
15
+ generator client {
16
+ provider = "prisma-client-js"
17
+ }
18
+
19
+ // v7 (required)
20
+ generator client {
21
+ provider = "prisma-client"
22
+ output = "../generated/prisma"
23
+ }
24
+ ```
25
+
26
+ ## Prisma Client
27
+
28
+ ```typescript
29
+ // lib/prisma.ts
30
+ import { PrismaClient } from './generated/prisma'
31
+
32
+ const globalForPrisma = globalThis as unknown as { prisma: PrismaClient | undefined }
33
+ export const prisma = globalForPrisma.prisma ?? new PrismaClient({ log: ['query'] })
34
+ if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
35
+ ```
36
+
37
+ ## TanStack Start Integration
38
+
39
+ ```typescript
40
+ import { createServerFn } from '@tanstack/react-start'
41
+ import { prisma } from '@/lib/prisma'
42
+
43
+ export const getUsers = createServerFn({ method: 'GET' })
44
+ .handler(async () => prisma.user.findMany({ include: { posts: true } }))
45
+
46
+ export const createUser = createServerFn({ method: 'POST' })
47
+ .inputValidator((data: { email: string; name: string }) => data)
48
+ .handler(async ({ data }) => prisma.user.create({ data }))
49
+ ```
@@ -0,0 +1,50 @@
1
+ # Prisma - Transactions
2
+
3
+ ## Array-based Transaction
4
+
5
+ Rolls back all if any operation fails.
6
+
7
+ ```typescript
8
+ const deletePosts = prisma.post.deleteMany({ where: { authorId: 7 } })
9
+ const deleteUser = prisma.user.delete({ where: { id: 7 } })
10
+ await prisma.$transaction([deletePosts, deleteUser])
11
+ ```
12
+
13
+ ## Interactive Transaction
14
+
15
+ For complex logic and conditional processing.
16
+
17
+ ```typescript
18
+ const result = await prisma.$transaction(async (tx) => {
19
+ const sender = await tx.account.findUnique({ where: { id: senderId } })
20
+ if (!sender || sender.balance < amount) throw new Error('Insufficient balance')
21
+
22
+ await tx.account.update({ where: { id: senderId }, data: { balance: { decrement: amount } } })
23
+ await tx.account.update({ where: { id: recipientId }, data: { balance: { increment: amount } } })
24
+
25
+ return { success: true }
26
+ })
27
+ ```
28
+
29
+ ## Options
30
+
31
+ ```typescript
32
+ await prisma.$transaction(async (tx) => { ... }, {
33
+ maxWait: 5000, // maximum wait time (ms)
34
+ timeout: 10000, // timeout (ms)
35
+ isolationLevel: 'Serializable', // ReadUncommitted | ReadCommitted | RepeatableRead | Serializable
36
+ })
37
+ ```
38
+
39
+ ## Error Handling
40
+
41
+ ```typescript
42
+ try {
43
+ await prisma.$transaction(async (tx) => {
44
+ await tx.user.create({ data: { email } })
45
+ if (someCondition) throw new Error('Rollback')
46
+ })
47
+ } catch (error) {
48
+ // entire transaction rolled back
49
+ }
50
+ ```
@@ -0,0 +1,66 @@
1
+ # TanStack Query
2
+
3
+ > 5.x | React Data Fetching
4
+
5
+ @use-query.md
6
+ @use-mutation.md
7
+ @invalidation.md
8
+ @optimistic-updates.md
9
+
10
+ ---
11
+
12
+ <quick_reference>
13
+
14
+ ```typescript
15
+ // useQuery
16
+ const { data, isLoading, error } = useQuery({
17
+ queryKey: ['users'],
18
+ queryFn: () => getUsers(),
19
+ })
20
+
21
+ // useMutation + invalidation
22
+ const queryClient = useQueryClient()
23
+ const mutation = useMutation({
24
+ mutationFn: createUser,
25
+ onSuccess: () => queryClient.invalidateQueries({ queryKey: ['users'] }),
26
+ })
27
+ mutation.mutate({ email, name })
28
+
29
+ // Optimistic Update
30
+ const mutation = useMutation({
31
+ mutationFn: updateUser,
32
+ onMutate: async (newUser) => {
33
+ await queryClient.cancelQueries({ queryKey: ['users'] })
34
+ const previous = queryClient.getQueryData(['users'])
35
+ queryClient.setQueryData(['users'], (old) => [...old, newUser])
36
+ return { previous }
37
+ },
38
+ onError: (err, newUser, context) => {
39
+ queryClient.setQueryData(['users'], context.previous)
40
+ },
41
+ })
42
+
43
+ // Setup
44
+ const queryClient = new QueryClient({
45
+ defaultOptions: {
46
+ queries: {
47
+ staleTime: 1000 * 60 * 5, // 5 minutes
48
+ gcTime: 1000 * 60 * 30, // 30 minutes
49
+ retry: 3,
50
+ },
51
+ },
52
+ })
53
+
54
+ const App = () => (
55
+ <QueryClientProvider client={queryClient}>
56
+ <YourApp />
57
+ </QueryClientProvider>
58
+ )
59
+
60
+ // Query Keys
61
+ ['todos'] // simple
62
+ ['todo', { id: 5 }] // with parameter
63
+ ['todos', 'list', { filters }] // hierarchical
64
+ ```
65
+
66
+ </quick_reference>
@@ -0,0 +1,54 @@
1
+ # TanStack Query - Query Invalidation
2
+
3
+ <patterns>
4
+
5
+ ```typescript
6
+ const queryClient = useQueryClient()
7
+
8
+ // Single
9
+ queryClient.invalidateQueries({ queryKey: ['todos'] })
10
+
11
+ // Multiple
12
+ await Promise.all([
13
+ queryClient.invalidateQueries({ queryKey: ['todos'] }),
14
+ queryClient.invalidateQueries({ queryKey: ['reminders'] }),
15
+ ])
16
+
17
+ // All
18
+ queryClient.invalidateQueries()
19
+
20
+ // Options
21
+ queryClient.invalidateQueries({
22
+ queryKey: ['posts'],
23
+ exact: true, // exact key match only
24
+ refetchType: 'active', // 'active' | 'inactive' | 'all' | 'none'
25
+ })
26
+
27
+ // Query key matching
28
+ queryClient.invalidateQueries({ queryKey: ['todos'] }) // prefix matching
29
+ queryClient.invalidateQueries({ queryKey: ['todos', 'list'], exact: true }) // exact matching
30
+
31
+ // With mutation
32
+ useMutation({
33
+ mutationFn: addTodo,
34
+ onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),
35
+ onSettled: () => queryClient.invalidateQueries({ queryKey: ['todos'] }), // regardless of success/failure
36
+ })
37
+
38
+ // Direct update vs invalidation
39
+ queryClient.setQueryData(['todos'], (old) => [...old, newTodo]) // faster
40
+ queryClient.invalidateQueries({ queryKey: ['todos'] }) // guarantees server data
41
+ ```
42
+
43
+ </patterns>
44
+
45
+ <options>
46
+
47
+ | refetchType | Description |
48
+ |-------------|-------------|
49
+ | active | Refetch only queries currently being rendered (default) |
50
+ | inactive | Refetch only inactive queries |
51
+ | all | Refetch all matching queries |
52
+ | none | Invalidate only, no refetch |
53
+
54
+ </options>
@@ -0,0 +1,77 @@
1
+ # TanStack Query - Optimistic Updates
2
+
3
+ <patterns>
4
+
5
+ ```tsx
6
+ // Add
7
+ useMutation({
8
+ mutationFn: addTodo,
9
+ onMutate: async (newTodo) => {
10
+ await queryClient.cancelQueries({ queryKey: ['todos'] })
11
+ const previousTodos = queryClient.getQueryData(['todos'])
12
+ queryClient.setQueryData(['todos'], (old) => [...old, newTodo])
13
+ return { previousTodos }
14
+ },
15
+ onError: (err, newTodo, context) => {
16
+ queryClient.setQueryData(['todos'], context.previousTodos)
17
+ },
18
+ onSettled: () => {
19
+ queryClient.invalidateQueries({ queryKey: ['todos'] })
20
+ },
21
+ })
22
+
23
+ // Delete
24
+ useMutation({
25
+ mutationFn: deleteTodo,
26
+ onMutate: async (todoId) => {
27
+ await queryClient.cancelQueries({ queryKey: ['todos'] })
28
+ const previousTodos = queryClient.getQueryData(['todos'])
29
+ queryClient.setQueryData(['todos'], (old) =>
30
+ old.filter((todo) => todo.id !== todoId)
31
+ )
32
+ return { previousTodos }
33
+ },
34
+ onError: (err, todoId, context) => {
35
+ queryClient.setQueryData(['todos'], context.previousTodos)
36
+ },
37
+ onSettled: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),
38
+ })
39
+
40
+ // Toggle
41
+ useMutation({
42
+ mutationFn: toggleTodo,
43
+ onMutate: async (todoId) => {
44
+ await queryClient.cancelQueries({ queryKey: ['todos'] })
45
+ const previousTodos = queryClient.getQueryData(['todos'])
46
+ queryClient.setQueryData(['todos'], (old) =>
47
+ old.map((todo) =>
48
+ todo.id === todoId ? { ...todo, completed: !todo.completed } : todo
49
+ )
50
+ )
51
+ return { previousTodos }
52
+ },
53
+ onError: (err, todoId, context) => {
54
+ queryClient.setQueryData(['todos'], context.previousTodos)
55
+ },
56
+ onSettled: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),
57
+ })
58
+
59
+ // Single item
60
+ useMutation({
61
+ mutationFn: updateTodo,
62
+ onMutate: async (newTodo) => {
63
+ await queryClient.cancelQueries({ queryKey: ['todos', newTodo.id] })
64
+ const previousTodo = queryClient.getQueryData(['todos', newTodo.id])
65
+ queryClient.setQueryData(['todos', newTodo.id], newTodo)
66
+ return { previousTodo, newTodo }
67
+ },
68
+ onError: (err, newTodo, context) => {
69
+ queryClient.setQueryData(['todos', context.newTodo.id], context.previousTodo)
70
+ },
71
+ onSettled: (newTodo) => {
72
+ queryClient.invalidateQueries({ queryKey: ['todos', newTodo.id] })
73
+ },
74
+ })
75
+ ```
76
+
77
+ </patterns>
@@ -0,0 +1,63 @@
1
+ # TanStack Query - useMutation
2
+
3
+ <patterns>
4
+
5
+ ```tsx
6
+ // Basic
7
+ const queryClient = useQueryClient()
8
+ const mutation = useMutation({
9
+ mutationFn: postTodo,
10
+ onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),
11
+ })
12
+ mutation.mutate({ title: 'New Todo' })
13
+
14
+ // Callbacks
15
+ useMutation({
16
+ mutationFn: updateTodo,
17
+ onMutate: async (newTodo) => {
18
+ // before mutation starts (for optimistic updates)
19
+ return { previousData } // passed to context
20
+ },
21
+ onSuccess: (data, variables, context) => {},
22
+ onError: (error, variables, context) => {},
23
+ onSettled: (data, error, variables, context) => {
24
+ queryClient.invalidateQueries({ queryKey: ['todos'] })
25
+ },
26
+ })
27
+
28
+ // mutate vs mutateAsync
29
+ mutation.mutate(data, {
30
+ onSuccess: (result) => console.log(result),
31
+ onError: (error) => console.log(error),
32
+ })
33
+
34
+ try {
35
+ const result = await mutation.mutateAsync(data)
36
+ } catch (error) { ... }
37
+
38
+ // Cache update
39
+ useMutation({
40
+ mutationFn: patchTodo,
41
+ onSuccess: (data) => {
42
+ queryClient.invalidateQueries({ queryKey: ['todos'] })
43
+ queryClient.setQueryData(['todo', { id: data.id }], data)
44
+ },
45
+ })
46
+ ```
47
+
48
+ </patterns>
49
+
50
+ <returns>
51
+
52
+ | Property | Description |
53
+ |----------|-------------|
54
+ | data | Mutation result |
55
+ | error | Error object |
56
+ | isPending | Execution in progress |
57
+ | isSuccess/isError | Status flags |
58
+ | mutate | Execute (async) |
59
+ | mutateAsync | Execute (Promise) |
60
+ | reset | Reset state |
61
+ | variables | Passed variables |
62
+
63
+ </returns>
@@ -0,0 +1,70 @@
1
+ # TanStack Query - useQuery
2
+
3
+ <patterns>
4
+
5
+ ```tsx
6
+ // Basic
7
+ const { data, isLoading, error } = useQuery({
8
+ queryKey: ['todos'],
9
+ queryFn: getTodos,
10
+ })
11
+ if (isLoading) return <div>Loading...</div>
12
+ if (error) return <div>Error: {error.message}</div>
13
+
14
+ // Options
15
+ useQuery({
16
+ queryKey: ['todos'],
17
+ queryFn: fetchTodos,
18
+ staleTime: 1000 * 60 * 5, // time to keep data fresh
19
+ gcTime: 1000 * 60 * 30, // garbage collection time
20
+ refetchOnWindowFocus: true, // refetch on window focus
21
+ refetchInterval: 1000 * 60, // auto-refetch interval
22
+ retry: 3, // retry attempts
23
+ enabled: !!userId, // conditional execution
24
+ initialData: [], // initial data
25
+ select: (data) => data.filter(t => t.done), // data transformation
26
+ })
27
+
28
+ // With parameter
29
+ useQuery({
30
+ queryKey: ['todo', todoId],
31
+ queryFn: () => fetchTodoById(todoId),
32
+ enabled: !!todoId,
33
+ })
34
+
35
+ // Dependent queries
36
+ const { data: user } = useQuery({ queryKey: ['user', userId], queryFn: ... })
37
+ const { data: posts } = useQuery({
38
+ queryKey: ['posts', user?.id],
39
+ queryFn: () => fetchPostsByUserId(user!.id),
40
+ enabled: !!user?.id,
41
+ })
42
+
43
+ // Parallel
44
+ const usersQuery = useQuery({ queryKey: ['users'], queryFn: fetchUsers })
45
+ const postsQuery = useQuery({ queryKey: ['posts'], queryFn: fetchPosts })
46
+
47
+ // Dynamic parallel
48
+ const userQueries = useQueries({
49
+ queries: userIds.map((id) => ({
50
+ queryKey: ['user', id],
51
+ queryFn: () => fetchUserById(id),
52
+ })),
53
+ })
54
+ ```
55
+
56
+ </patterns>
57
+
58
+ <returns>
59
+
60
+ | Property | Description |
61
+ |----------|-------------|
62
+ | data | Query result |
63
+ | error | Error object |
64
+ | isLoading | First loading state |
65
+ | isFetching | Background fetching state |
66
+ | isError/isSuccess | Status flags |
67
+ | refetch | Manual refetch function |
68
+ | status | 'pending' \| 'error' \| 'success' |
69
+
70
+ </returns>
@@ -0,0 +1,61 @@
1
+ # Zod - Complex Types
2
+
3
+ <patterns>
4
+
5
+ ```typescript
6
+ // Object
7
+ const UserSchema = z.object({
8
+ name: z.string(),
9
+ email: z.email(),
10
+ age: z.number().optional(),
11
+ })
12
+
13
+ UserSchema.partial() // all fields optional
14
+ UserSchema.required() // all fields required
15
+ UserSchema.pick({ name: true }) // specific fields only
16
+ UserSchema.omit({ email: true }) // exclude specific fields
17
+ UserSchema.extend({ role: z.enum(['admin', 'user']) })
18
+ UserSchema.merge(AnotherSchema)
19
+
20
+ z.strictObject({ name: z.string() }) // v4: additional keys throw error
21
+ z.looseObject({ name: z.string() }) // v4: additional keys pass through
22
+
23
+ // Array/Tuple
24
+ z.array(z.string())
25
+ z.array(z.number()).min(1).max(10).length(5).nonempty()
26
+ z.tuple([z.string(), z.number()]) // [string, number]
27
+
28
+ // Union
29
+ z.union([z.string(), z.number()])
30
+ z.string().or(z.number())
31
+
32
+ z.discriminatedUnion('type', [
33
+ z.object({ type: z.literal('circle'), radius: z.number() }),
34
+ z.object({ type: z.literal('rectangle'), width: z.number(), height: z.number() }),
35
+ ])
36
+
37
+ // Enum
38
+ const Status = z.enum(['pending', 'done', 'cancelled'])
39
+ type Status = z.infer<typeof Status> // 'pending' | 'done' | 'cancelled'
40
+
41
+ enum Fruits { Apple, Banana }
42
+ z.nativeEnum(Fruits)
43
+
44
+ // Record/Map/Set
45
+ z.record(z.string(), z.object({ name: z.string() })) // { [key: string]: { name: string } }
46
+ z.map(z.string(), z.number()) // Map<string, number>
47
+ z.set(z.number()) // Set<number>
48
+
49
+ // Recursive
50
+ type Json = string | number | boolean | null | { [key: string]: Json } | Json[]
51
+
52
+ const jsonSchema: z.ZodType<Json> = z.lazy(() =>
53
+ z.union([
54
+ z.string(), z.number(), z.boolean(), z.null(),
55
+ z.array(jsonSchema),
56
+ z.record(jsonSchema)
57
+ ])
58
+ )
59
+ ```
60
+
61
+ </patterns>