@kood/claude-code 0.2.5 → 0.3.1

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 (130) hide show
  1. package/dist/index.js +13 -8
  2. package/package.json +1 -1
  3. package/templates/.claude/agents/code-reviewer.md +371 -19
  4. package/templates/.claude/agents/dependency-manager.md +197 -0
  5. package/templates/.claude/agents/deployment-validator.md +136 -0
  6. package/templates/.claude/agents/git-operator.md +147 -0
  7. package/templates/.claude/agents/implementation-executor.md +202 -0
  8. package/templates/.claude/agents/lint-fixer.md +155 -0
  9. package/templates/.claude/agents/refactor-advisor.md +339 -29
  10. package/templates/.claude/commands/agent-creator.md +355 -0
  11. package/templates/.claude/commands/docs-creator.md +404 -163
  12. package/templates/.claude/commands/docs-refactor.md +400 -113
  13. package/templates/.claude/commands/execute.md +357 -185
  14. package/templates/.claude/commands/git-all.md +65 -71
  15. package/templates/.claude/commands/git-session.md +80 -64
  16. package/templates/.claude/commands/git.md +68 -72
  17. package/templates/.claude/commands/lint-fix.md +224 -109
  18. package/templates/.claude/commands/lint-init.md +142 -168
  19. package/templates/.claude/commands/plan.md +300 -84
  20. package/templates/.claude/commands/prd.md +497 -214
  21. package/templates/.claude/commands/pre-deploy.md +242 -0
  22. package/templates/.claude/commands/subagent-creator.md +118 -0
  23. package/templates/.claude/commands/version-update.md +45 -57
  24. package/templates/hono/CLAUDE.md +99 -54
  25. package/templates/hono/docs/guides/conventions.md +352 -0
  26. package/templates/hono/docs/guides/env-setup.md +347 -0
  27. package/templates/hono/docs/guides/getting-started.md +239 -0
  28. package/templates/hono/docs/library/hono/error-handling.md +20 -29
  29. package/templates/hono/docs/library/hono/index.md +25 -52
  30. package/templates/hono/docs/library/hono/middleware.md +16 -75
  31. package/templates/hono/docs/library/hono/rpc.md +7 -35
  32. package/templates/hono/docs/library/hono/validation.md +25 -45
  33. package/templates/hono/docs/library/t3-env/index.md +374 -0
  34. package/templates/npx/CLAUDE.md +165 -65
  35. package/templates/npx/docs/library/commander/index.md +10 -73
  36. package/templates/npx/docs/library/fs-extra/index.md +21 -113
  37. package/templates/npx/docs/library/prompts/index.md +30 -176
  38. package/templates/npx/docs/references/patterns.md +75 -48
  39. package/templates/tanstack-start/CLAUDE.md +101 -77
  40. package/templates/tanstack-start/docs/architecture.md +427 -0
  41. package/templates/tanstack-start/docs/design.md +558 -0
  42. package/templates/tanstack-start/docs/guides/conventions.md +132 -32
  43. package/templates/tanstack-start/docs/guides/env-setup.md +127 -62
  44. package/templates/tanstack-start/docs/guides/getting-started.md +81 -20
  45. package/templates/tanstack-start/docs/guides/hooks.md +241 -36
  46. package/templates/tanstack-start/docs/guides/routes.md +213 -61
  47. package/templates/tanstack-start/docs/guides/services.md +260 -24
  48. package/templates/tanstack-start/docs/library/better-auth/index.md +469 -16
  49. package/templates/tanstack-start/docs/library/t3-env/index.md +307 -0
  50. package/templates/tanstack-start/docs/library/tanstack-query/index.md +12 -21
  51. package/templates/tanstack-start/docs/library/tanstack-query/invalidation.md +22 -35
  52. package/templates/tanstack-start/docs/library/tanstack-query/optimistic-updates.md +7 -24
  53. package/templates/tanstack-start/docs/library/tanstack-query/use-mutation.md +26 -39
  54. package/templates/tanstack-start/docs/library/tanstack-query/use-query.md +23 -26
  55. package/templates/tanstack-start/docs/library/tanstack-router/error-handling.md +32 -147
  56. package/templates/tanstack-start/docs/library/tanstack-router/hooks.md +25 -167
  57. package/templates/tanstack-start/docs/library/tanstack-router/index.md +39 -74
  58. package/templates/tanstack-start/docs/library/tanstack-router/navigation.md +46 -116
  59. package/templates/tanstack-start/docs/library/tanstack-router/route-context.md +35 -154
  60. package/templates/tanstack-start/docs/library/tanstack-router/search-params.md +32 -171
  61. package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +7 -15
  62. package/templates/tanstack-start/docs/library/tanstack-start/routing.md +16 -23
  63. package/templates/tanstack-start/docs/library/zod/complex-types.md +12 -31
  64. package/templates/tanstack-start/docs/library/zod/index.md +18 -35
  65. package/templates/tanstack-start/docs/library/zod/transforms.md +11 -25
  66. package/templates/tanstack-start/docs/library/zod/validation.md +12 -34
  67. package/templates/.claude/agents/debug-detective.md +0 -37
  68. package/templates/.claude/agents/test-writer.md +0 -41
  69. package/templates/.claude/commands/feedback.md +0 -199
  70. package/templates/.claude/commands/ts-fix.md +0 -176
  71. package/templates/.claude/skills/command-creator/LICENSE.txt +0 -202
  72. package/templates/.claude/skills/command-creator/SKILL.md +0 -245
  73. package/templates/.claude/skills/command-creator/scripts/init_command.py +0 -244
  74. package/templates/.claude/skills/command-creator/scripts/package_command.py +0 -125
  75. package/templates/.claude/skills/command-creator/scripts/quick_validate.py +0 -143
  76. package/templates/.claude/skills/frontend-design/SKILL.md +0 -310
  77. package/templates/.claude/skills/frontend-design/references/animation-patterns.md +0 -446
  78. package/templates/.claude/skills/frontend-design/references/colors-2026.md +0 -244
  79. package/templates/.claude/skills/frontend-design/references/typography-2026.md +0 -302
  80. package/templates/.claude/skills/gemini-review/SKILL.md +0 -118
  81. package/templates/.claude/skills/gemini-review/references/checklists.md +0 -129
  82. package/templates/.claude/skills/gemini-review/references/prompt-templates.md +0 -274
  83. package/templates/.claude/skills/skill-creator/LICENSE.txt +0 -202
  84. package/templates/.claude/skills/skill-creator/SKILL.md +0 -184
  85. package/templates/.claude/skills/skill-creator/scripts/init_skill.py +0 -303
  86. package/templates/.claude/skills/skill-creator/scripts/package_skill.py +0 -110
  87. package/templates/.claude/skills/skill-creator/scripts/quick_validate.py +0 -65
  88. package/templates/hono/docs/library/ai-sdk/index.md +0 -190
  89. package/templates/hono/docs/library/ai-sdk/openrouter.md +0 -111
  90. package/templates/hono/docs/library/ai-sdk/providers.md +0 -102
  91. package/templates/hono/docs/library/ai-sdk/streaming.md +0 -146
  92. package/templates/hono/docs/library/ai-sdk/structured-output.md +0 -161
  93. package/templates/hono/docs/library/ai-sdk/tools.md +0 -144
  94. package/templates/hono/docs/library/drizzle/cloudflare-d1.md +0 -247
  95. package/templates/hono/docs/library/drizzle/config.md +0 -167
  96. package/templates/hono/docs/library/drizzle/index.md +0 -259
  97. package/templates/hono/docs/library/hono/env-setup.md +0 -169
  98. package/templates/hono/docs/library/pino/index.md +0 -146
  99. package/templates/tanstack-start/docs/architecture/architecture.md +0 -243
  100. package/templates/tanstack-start/docs/deployment/cloudflare.md +0 -132
  101. package/templates/tanstack-start/docs/deployment/index.md +0 -163
  102. package/templates/tanstack-start/docs/deployment/nitro.md +0 -110
  103. package/templates/tanstack-start/docs/deployment/railway.md +0 -147
  104. package/templates/tanstack-start/docs/deployment/vercel.md +0 -135
  105. package/templates/tanstack-start/docs/design/components.md +0 -175
  106. package/templates/tanstack-start/docs/design/index.md +0 -151
  107. package/templates/tanstack-start/docs/design/safe-area.md +0 -118
  108. package/templates/tanstack-start/docs/design/tailwind-setup.md +0 -156
  109. package/templates/tanstack-start/docs/library/ai-sdk/hooks.md +0 -472
  110. package/templates/tanstack-start/docs/library/ai-sdk/index.md +0 -264
  111. package/templates/tanstack-start/docs/library/ai-sdk/openrouter.md +0 -371
  112. package/templates/tanstack-start/docs/library/ai-sdk/providers.md +0 -403
  113. package/templates/tanstack-start/docs/library/ai-sdk/streaming.md +0 -320
  114. package/templates/tanstack-start/docs/library/ai-sdk/structured-output.md +0 -454
  115. package/templates/tanstack-start/docs/library/ai-sdk/tools.md +0 -473
  116. package/templates/tanstack-start/docs/library/better-auth/2fa.md +0 -48
  117. package/templates/tanstack-start/docs/library/better-auth/advanced.md +0 -55
  118. package/templates/tanstack-start/docs/library/better-auth/plugins.md +0 -34
  119. package/templates/tanstack-start/docs/library/better-auth/session.md +0 -47
  120. package/templates/tanstack-start/docs/library/better-auth/setup.md +0 -41
  121. package/templates/tanstack-start/docs/library/drizzle/cloudflare-d1.md +0 -147
  122. package/templates/tanstack-start/docs/library/drizzle/config.md +0 -118
  123. package/templates/tanstack-start/docs/library/drizzle/crud.md +0 -205
  124. package/templates/tanstack-start/docs/library/drizzle/index.md +0 -79
  125. package/templates/tanstack-start/docs/library/drizzle/relations.md +0 -202
  126. package/templates/tanstack-start/docs/library/drizzle/schema.md +0 -154
  127. package/templates/tanstack-start/docs/library/drizzle/setup.md +0 -96
  128. package/templates/tanstack-start/docs/library/drizzle/transactions.md +0 -127
  129. package/templates/tanstack-start/docs/library/pino/index.md +0 -320
  130. /package/templates/hono/docs/{architecture/architecture.md → architecture.md} +0 -0
@@ -0,0 +1,307 @@
1
+ # t3-env - Type-Safe Environment Variables
2
+
3
+ > Zod 기반 타입 안전 환경 변수 관리
4
+
5
+ <context>
6
+
7
+ **용도:** 서버/클라이언트 환경 변수 분리, 런타임 검증, 타입 안전성
8
+
9
+ **특징:**
10
+ - Zod 스키마로 검증 + 타입 추론
11
+ - Server 변수 클라이언트 노출 방지
12
+ - Transform & Default 값 지원
13
+ - 프레임워크 무관
14
+
15
+ </context>
16
+
17
+ ---
18
+
19
+ <forbidden>
20
+
21
+ | 분류 | 금지 |
22
+ |------|------|
23
+ | **노출** | Server 변수를 클라이언트에 노출 |
24
+ | **접두사** | Client 변수에 `PUBLIC_` 없이 사용 |
25
+ | **직접 접근** | `process.env` 직접 사용 (env 객체 필수) |
26
+ | **타입** | any 타입으로 env 변수 접근 |
27
+
28
+ </forbidden>
29
+
30
+ ---
31
+
32
+ <required>
33
+
34
+ | 분류 | 필수 |
35
+ |------|------|
36
+ | **설치** | `@t3-oss/env-core zod` |
37
+ | **구조** | `src/env.ts` 파일 생성 |
38
+ | **접두사** | Client 변수: `PUBLIC_` 시작 |
39
+ | **Import** | `import { env } from '@/env'` |
40
+
41
+ </required>
42
+
43
+ ---
44
+
45
+ <setup>
46
+
47
+ ## Installation
48
+
49
+ ```bash
50
+ npm install @t3-oss/env-core zod
51
+ ```
52
+
53
+ ## Basic Setup
54
+
55
+ `src/env.ts`:
56
+
57
+ ```typescript
58
+ import { createEnv } from '@t3-oss/env-core'
59
+ import { z } from 'zod'
60
+
61
+ export const env = createEnv({
62
+ // Server-only variables
63
+ server: {
64
+ DATABASE_URL: z.url(),
65
+ CLERK_SECRET_KEY: z.string().min(1),
66
+ OPENAI_API_KEY: z.string().min(1),
67
+ },
68
+
69
+ // Client-exposed variables (PUBLIC_ prefix required)
70
+ clientPrefix: 'PUBLIC_',
71
+ client: {
72
+ PUBLIC_API_URL: z.url().default('http://localhost:3000'),
73
+ PUBLIC_CLERK_PUBLISHABLE_KEY: z.string().min(1),
74
+ },
75
+
76
+ // Runtime environment
77
+ runtimeEnv: {
78
+ // Server
79
+ DATABASE_URL: process.env.DATABASE_URL,
80
+ CLERK_SECRET_KEY: process.env.CLERK_SECRET_KEY,
81
+ OPENAI_API_KEY: process.env.OPENAI_API_KEY,
82
+ // Client
83
+ PUBLIC_API_URL: import.meta.env.PUBLIC_API_URL,
84
+ PUBLIC_CLERK_PUBLISHABLE_KEY: import.meta.env.PUBLIC_CLERK_PUBLISHABLE_KEY,
85
+ },
86
+
87
+ emptyStringAsUndefined: true,
88
+ })
89
+ ```
90
+
91
+ </setup>
92
+
93
+ ---
94
+
95
+ <patterns>
96
+
97
+ ## Common Patterns
98
+
99
+ ### Server Function
100
+
101
+ ```typescript
102
+ import { createServerFn } from '@tanstack/start'
103
+ import { env } from '@/env'
104
+
105
+ export const getUsers = createServerFn({ method: 'GET' }).handler(async () => {
106
+ const db = await prisma.$connect(env.DATABASE_URL)
107
+ // ^? string (타입 안전)
108
+ return db.user.findMany()
109
+ })
110
+ ```
111
+
112
+ ### Client Component
113
+
114
+ ```typescript
115
+ import { env } from '@/env'
116
+
117
+ export const ApiClient = () => {
118
+ const apiUrl = env.PUBLIC_API_URL
119
+ // ^? string (타입 안전)
120
+
121
+ // ❌ Error: server 변수는 클라이언트에서 접근 불가
122
+ // const dbUrl = env.DATABASE_URL
123
+ }
124
+ ```
125
+
126
+ ### Environment-Specific Defaults
127
+
128
+ ```typescript
129
+ server: {
130
+ NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
131
+ LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
132
+ }
133
+ ```
134
+
135
+ ### Transform Values
136
+
137
+ ```typescript
138
+ server: {
139
+ PORT: z.string().transform((val) => parseInt(val, 10)).pipe(z.number().positive()),
140
+ MAX_CONNECTIONS: z.coerce.number().default(10),
141
+ }
142
+ ```
143
+
144
+ ### Optional with Fallback
145
+
146
+ ```typescript
147
+ client: {
148
+ PUBLIC_ANALYTICS_ID: z.string().optional(),
149
+ PUBLIC_FEATURE_FLAG: z.coerce.boolean().default(false),
150
+ }
151
+ ```
152
+
153
+ </patterns>
154
+
155
+ ---
156
+
157
+ <examples>
158
+
159
+ ## Real-World Examples
160
+
161
+ ### Database + Auth
162
+
163
+ ```typescript
164
+ // src/env.ts
165
+ export const env = createEnv({
166
+ server: {
167
+ DATABASE_URL: z.url(),
168
+ DIRECT_URL: z.url().optional(), // Prisma connection pooling
169
+ CLERK_SECRET_KEY: z.string().min(1),
170
+ RESEND_API_KEY: z.string().min(1),
171
+ },
172
+ clientPrefix: 'PUBLIC_',
173
+ client: {
174
+ PUBLIC_CLERK_PUBLISHABLE_KEY: z.string().min(1),
175
+ },
176
+ runtimeEnv: {
177
+ DATABASE_URL: process.env.DATABASE_URL,
178
+ DIRECT_URL: process.env.DIRECT_URL,
179
+ CLERK_SECRET_KEY: process.env.CLERK_SECRET_KEY,
180
+ RESEND_API_KEY: process.env.RESEND_API_KEY,
181
+ PUBLIC_CLERK_PUBLISHABLE_KEY: import.meta.env.PUBLIC_CLERK_PUBLISHABLE_KEY,
182
+ },
183
+ emptyStringAsUndefined: true,
184
+ })
185
+ ```
186
+
187
+ ### API Integration
188
+
189
+ ```typescript
190
+ // src/env.ts
191
+ export const env = createEnv({
192
+ server: {
193
+ OPENAI_API_KEY: z.string().min(1),
194
+ STRIPE_SECRET_KEY: z.string().min(1),
195
+ STRIPE_WEBHOOK_SECRET: z.string().min(1),
196
+ },
197
+ clientPrefix: 'PUBLIC_',
198
+ client: {
199
+ PUBLIC_STRIPE_PUBLISHABLE_KEY: z.string().min(1),
200
+ PUBLIC_APP_URL: z.url(),
201
+ },
202
+ runtimeEnv: {
203
+ OPENAI_API_KEY: process.env.OPENAI_API_KEY,
204
+ STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY,
205
+ STRIPE_WEBHOOK_SECRET: process.env.STRIPE_WEBHOOK_SECRET,
206
+ PUBLIC_STRIPE_PUBLISHABLE_KEY: import.meta.env.PUBLIC_STRIPE_PUBLISHABLE_KEY,
207
+ PUBLIC_APP_URL: import.meta.env.PUBLIC_APP_URL,
208
+ },
209
+ emptyStringAsUndefined: true,
210
+ })
211
+ ```
212
+
213
+ ### Multi-Environment
214
+
215
+ ```typescript
216
+ // src/env.ts
217
+ export const env = createEnv({
218
+ server: {
219
+ NODE_ENV: z.enum(['development', 'production', 'test']),
220
+ DATABASE_URL: z.url(),
221
+ REDIS_URL: z.url().optional(), // Production only
222
+ },
223
+ clientPrefix: 'PUBLIC_',
224
+ client: {
225
+ PUBLIC_API_URL: z.url(),
226
+ PUBLIC_SENTRY_DSN: z.string().optional(), // Production only
227
+ },
228
+ runtimeEnv: {
229
+ NODE_ENV: process.env.NODE_ENV,
230
+ DATABASE_URL: process.env.DATABASE_URL,
231
+ REDIS_URL: process.env.REDIS_URL,
232
+ PUBLIC_API_URL: import.meta.env.PUBLIC_API_URL,
233
+ PUBLIC_SENTRY_DSN: import.meta.env.PUBLIC_SENTRY_DSN,
234
+ },
235
+ emptyStringAsUndefined: true,
236
+ })
237
+ ```
238
+
239
+ </examples>
240
+
241
+ ---
242
+
243
+ <validation>
244
+
245
+ ## Validation Patterns
246
+
247
+ ### Email
248
+
249
+ ```typescript
250
+ server: {
251
+ ADMIN_EMAIL: z.email(),
252
+ SUPPORT_EMAIL: z.email().default('support@example.com'),
253
+ }
254
+ ```
255
+
256
+ ### URL
257
+
258
+ ```typescript
259
+ server: {
260
+ API_URL: z.url(),
261
+ WEBHOOK_URL: z.url().optional(),
262
+ }
263
+ ```
264
+
265
+ ### Enum
266
+
267
+ ```typescript
268
+ server: {
269
+ LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']),
270
+ DATABASE_PROVIDER: z.enum(['postgresql', 'mysql', 'sqlite']),
271
+ }
272
+ ```
273
+
274
+ ### Number
275
+
276
+ ```typescript
277
+ server: {
278
+ PORT: z.coerce.number().positive().default(3000),
279
+ MAX_UPLOAD_SIZE: z.coerce.number().max(10485760), // 10MB
280
+ }
281
+ ```
282
+
283
+ ### Boolean
284
+
285
+ ```typescript
286
+ server: {
287
+ ENABLE_CACHE: z.coerce.boolean().default(true),
288
+ DEBUG_MODE: z.coerce.boolean().default(false),
289
+ }
290
+ ```
291
+
292
+ </validation>
293
+
294
+ ---
295
+
296
+ <tips>
297
+
298
+ ## Tips
299
+
300
+ | 상황 | 방법 |
301
+ |------|------|
302
+ | **Vercel** | `process.env.VERCEL_URL` → PUBLIC_APP_URL |
303
+ | **Monorepo** | 각 패키지마다 별도 `env.ts` |
304
+ | **Testing** | `.env.test` + `NODE_ENV=test` |
305
+ | **CI/CD** | GitHub Secrets → Environment Variables |
306
+
307
+ </tips>
@@ -1,6 +1,6 @@
1
1
  # TanStack Query
2
2
 
3
- > 5.x | React Data Fetching Library
3
+ > 5.x | React Data Fetching
4
4
 
5
5
  @use-query.md
6
6
  @use-mutation.md
@@ -9,7 +9,7 @@
9
9
 
10
10
  ---
11
11
 
12
- ## Quick Reference
12
+ <quick_reference>
13
13
 
14
14
  ```typescript
15
15
  // useQuery
@@ -39,37 +39,28 @@ const mutation = useMutation({
39
39
  queryClient.setQueryData(['users'], context.previous)
40
40
  },
41
41
  })
42
- ```
43
-
44
- ### 설정
45
-
46
- ```tsx
47
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
48
42
 
43
+ // 설정
49
44
  const queryClient = new QueryClient({
50
45
  defaultOptions: {
51
46
  queries: {
52
47
  staleTime: 1000 * 60 * 5, // 5분
53
- gcTime: 1000 * 60 * 30, // 30분 (이전 cacheTime)
48
+ gcTime: 1000 * 60 * 30, // 30분
54
49
  retry: 3,
55
50
  },
56
51
  },
57
52
  })
58
53
 
59
- function App() {
60
- return (
61
- <QueryClientProvider client={queryClient}>
62
- <YourApp />
63
- </QueryClientProvider>
64
- )
65
- }
66
- ```
54
+ const App = () => (
55
+ <QueryClientProvider client={queryClient}>
56
+ <YourApp />
57
+ </QueryClientProvider>
58
+ )
67
59
 
68
- ### Query Keys 패턴
69
-
70
- ```typescript
60
+ // Query Keys
71
61
  ['todos'] // 단순
72
62
  ['todo', { id: 5 }] // 파라미터
73
63
  ['todos', 'list', { filters }] // 계층적
74
- ['todos', 'detail', todoId]
75
64
  ```
65
+
66
+ </quick_reference>
@@ -1,6 +1,6 @@
1
1
  # TanStack Query - Query 무효화
2
2
 
3
- ## 기본 무효화
3
+ <patterns>
4
4
 
5
5
  ```typescript
6
6
  const queryClient = useQueryClient()
@@ -16,52 +16,39 @@ await Promise.all([
16
16
 
17
17
  // 전체
18
18
  queryClient.invalidateQueries()
19
- ```
20
-
21
- ## 옵션
22
19
 
23
- ```typescript
20
+ // 옵션
24
21
  queryClient.invalidateQueries({
25
22
  queryKey: ['posts'],
26
23
  exact: true, // 정확한 키 매칭만
27
- refetchType: 'active', // 'active'(기본) | 'inactive' | 'all' | 'none'
24
+ refetchType: 'active', // 'active' | 'inactive' | 'all' | 'none'
28
25
  })
29
- ```
30
-
31
- | refetchType | 설명 |
32
- |-------------|------|
33
- | active | 렌더링 중인 쿼리만 재조회 (기본) |
34
- | inactive | 비활성 쿼리만 |
35
- | all | 모든 매칭 쿼리 |
36
- | none | 무효화만, 재조회 안함 |
37
26
 
38
- ## Query Key 매칭
39
-
40
- ```typescript
41
- // prefix 매칭 (todos로 시작하는 모든 쿼리)
42
- queryClient.invalidateQueries({ queryKey: ['todos'] })
27
+ // Query Key 매칭
28
+ queryClient.invalidateQueries({ queryKey: ['todos'] }) // prefix 매칭
29
+ queryClient.invalidateQueries({ queryKey: ['todos', 'list'], exact: true }) // 정확한 매칭
43
30
 
44
- // 정확한 매칭
45
- queryClient.invalidateQueries({ queryKey: ['todos', 'list'], exact: true })
46
- ```
47
-
48
- ## Mutation과 함께
49
-
50
- ```tsx
31
+ // Mutation과 함께
51
32
  useMutation({
52
33
  mutationFn: addTodo,
53
34
  onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),
54
- // 또는 onSettled (성공/실패 무관)
55
- onSettled: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),
35
+ onSettled: () => queryClient.invalidateQueries({ queryKey: ['todos'] }), // 성공/실패 무관
56
36
  })
37
+
38
+ // 직접 업데이트 vs 무효화
39
+ queryClient.setQueryData(['todos'], (old) => [...old, newTodo]) // 더 빠름
40
+ queryClient.invalidateQueries({ queryKey: ['todos'] }) // 서버 데이터 보장
57
41
  ```
58
42
 
59
- ## 캐시 직접 업데이트 vs 무효화
43
+ </patterns>
60
44
 
61
- ```tsx
62
- // 직접 업데이트 (더 빠름)
63
- queryClient.setQueryData(['todos'], (old) => [...old, newTodo])
45
+ <options>
64
46
 
65
- // 무효화 (서버 데이터 보장)
66
- queryClient.invalidateQueries({ queryKey: ['todos'] })
67
- ```
47
+ | refetchType | 설명 |
48
+ |-------------|------|
49
+ | active | 렌더링 중인 쿼리만 재조회 (기본) |
50
+ | inactive | 비활성 쿼리만 |
51
+ | all | 모든 매칭 쿼리 |
52
+ | none | 무효화만, 재조회 안함 |
53
+
54
+ </options>
@@ -1,39 +1,26 @@
1
1
  # TanStack Query - Optimistic Updates
2
2
 
3
- 서버 응답 전 UI 즉시 업데이트.
4
-
5
- ## 패턴
3
+ <patterns>
6
4
 
7
5
  ```tsx
6
+ // 추가
8
7
  useMutation({
9
8
  mutationFn: addTodo,
10
9
  onMutate: async (newTodo) => {
11
- // 1. 진행 중인 refetch 취소
12
10
  await queryClient.cancelQueries({ queryKey: ['todos'] })
13
-
14
- // 2. 이전 값 스냅샷
15
11
  const previousTodos = queryClient.getQueryData(['todos'])
16
-
17
- // 3. 낙관적 업데이트
18
12
  queryClient.setQueryData(['todos'], (old) => [...old, newTodo])
19
-
20
- // 4. context로 이전 값 반환
21
13
  return { previousTodos }
22
14
  },
23
15
  onError: (err, newTodo, context) => {
24
- // 5. 에러 시 롤백
25
16
  queryClient.setQueryData(['todos'], context.previousTodos)
26
17
  },
27
18
  onSettled: () => {
28
- // 6. 서버와 동기화
29
19
  queryClient.invalidateQueries({ queryKey: ['todos'] })
30
20
  },
31
21
  })
32
- ```
33
-
34
- ## 삭제
35
22
 
36
- ```tsx
23
+ // 삭제
37
24
  useMutation({
38
25
  mutationFn: deleteTodo,
39
26
  onMutate: async (todoId) => {
@@ -49,11 +36,8 @@ useMutation({
49
36
  },
50
37
  onSettled: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),
51
38
  })
52
- ```
53
-
54
- ## 토글
55
39
 
56
- ```tsx
40
+ // 토글
57
41
  useMutation({
58
42
  mutationFn: toggleTodo,
59
43
  onMutate: async (todoId) => {
@@ -71,11 +55,8 @@ useMutation({
71
55
  },
72
56
  onSettled: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),
73
57
  })
74
- ```
75
58
 
76
- ## 단일 항목 업데이트
77
-
78
- ```tsx
59
+ // 단일 항목
79
60
  useMutation({
80
61
  mutationFn: updateTodo,
81
62
  onMutate: async (newTodo) => {
@@ -92,3 +73,5 @@ useMutation({
92
73
  },
93
74
  })
94
75
  ```
76
+
77
+ </patterns>
@@ -1,76 +1,63 @@
1
1
  # TanStack Query - useMutation
2
2
 
3
- ## 기본 사용법
3
+ <patterns>
4
4
 
5
5
  ```tsx
6
+ // 기본
6
7
  const queryClient = useQueryClient()
7
-
8
8
  const mutation = useMutation({
9
9
  mutationFn: postTodo,
10
10
  onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),
11
11
  })
12
-
13
12
  mutation.mutate({ title: 'New Todo' })
14
- ```
15
-
16
- ## 반환값
17
-
18
- | 속성 | 설명 |
19
- |------|------|
20
- | data | mutation 결과 |
21
- | error | 에러 객체 |
22
- | isPending | 실행 중 |
23
- | isSuccess/isError | 상태 |
24
- | mutate | 실행 (비동기) |
25
- | mutateAsync | 실행 (Promise) |
26
- | reset | 상태 초기화 |
27
- | variables | 전달된 변수 |
28
13
 
29
- ## 콜백
30
-
31
- ```tsx
14
+ // 콜백
32
15
  useMutation({
33
16
  mutationFn: updateTodo,
34
17
  onMutate: async (newTodo) => {
35
18
  // mutation 시작 전 (optimistic update용)
36
19
  return { previousData } // context로 전달
37
20
  },
38
- onSuccess: (data, variables, context) => {
39
- // 성공
40
- },
41
- onError: (error, variables, context) => {
42
- // 에러 시 (context로 롤백)
43
- },
21
+ onSuccess: (data, variables, context) => {},
22
+ onError: (error, variables, context) => {},
44
23
  onSettled: (data, error, variables, context) => {
45
- // 완료 시 (성공/실패 무관)
46
24
  queryClient.invalidateQueries({ queryKey: ['todos'] })
47
25
  },
48
26
  })
49
- ```
50
27
 
51
- ## mutate vs mutateAsync
52
-
53
- ```tsx
54
- // 콜백 기반
28
+ // mutate vs mutateAsync
55
29
  mutation.mutate(data, {
56
30
  onSuccess: (result) => console.log(result),
57
31
  onError: (error) => console.log(error),
58
32
  })
59
33
 
60
- // Promise 기반
61
34
  try {
62
35
  const result = await mutation.mutateAsync(data)
63
36
  } catch (error) { ... }
64
- ```
65
37
 
66
- ## 캐시 업데이트
67
-
68
- ```tsx
38
+ // 캐시 업데이트
69
39
  useMutation({
70
40
  mutationFn: patchTodo,
71
41
  onSuccess: (data) => {
72
- queryClient.invalidateQueries({ queryKey: ['todos'] }) // 목록 무효화
73
- queryClient.setQueryData(['todo', { id: data.id }], data) // 개별 캐시 업데이트
42
+ queryClient.invalidateQueries({ queryKey: ['todos'] })
43
+ queryClient.setQueryData(['todo', { id: data.id }], data)
74
44
  },
75
45
  })
76
46
  ```
47
+
48
+ </patterns>
49
+
50
+ <returns>
51
+
52
+ | 속성 | 설명 |
53
+ |------|------|
54
+ | data | mutation 결과 |
55
+ | error | 에러 객체 |
56
+ | isPending | 실행 중 |
57
+ | isSuccess/isError | 상태 |
58
+ | mutate | 실행 (비동기) |
59
+ | mutateAsync | 실행 (Promise) |
60
+ | reset | 상태 초기화 |
61
+ | variables | 전달된 변수 |
62
+
63
+ </returns>
@@ -1,32 +1,17 @@
1
1
  # TanStack Query - useQuery
2
2
 
3
- ## 기본 사용법
3
+ <patterns>
4
4
 
5
5
  ```tsx
6
+ // 기본
6
7
  const { data, isLoading, error } = useQuery({
7
8
  queryKey: ['todos'],
8
9
  queryFn: getTodos,
9
10
  })
10
-
11
11
  if (isLoading) return <div>Loading...</div>
12
12
  if (error) return <div>Error: {error.message}</div>
13
- ```
14
-
15
- ## 반환값
16
-
17
- | 속성 | 설명 |
18
- |------|------|
19
- | data | 쿼리 결과 |
20
- | error | 에러 객체 |
21
- | isLoading | 첫 로딩 중 |
22
- | isFetching | 백그라운드 페칭 중 |
23
- | isError/isSuccess | 상태 |
24
- | refetch | 수동 리페치 |
25
- | status | 'pending' \| 'error' \| 'success' |
26
-
27
- ## 주요 옵션
28
13
 
29
- ```tsx
14
+ // 옵션
30
15
  useQuery({
31
16
  queryKey: ['todos'],
32
17
  queryFn: fetchTodos,
@@ -39,12 +24,8 @@ useQuery({
39
24
  initialData: [], // 초기 데이터
40
25
  select: (data) => data.filter(t => t.done), // 데이터 변환
41
26
  })
42
- ```
43
27
 
44
- ## 패턴
45
-
46
- ```tsx
47
- // 파라미터 쿼리
28
+ // 파라미터
48
29
  useQuery({
49
30
  queryKey: ['todo', todoId],
50
31
  queryFn: () => fetchTodoById(todoId),
@@ -56,14 +37,14 @@ const { data: user } = useQuery({ queryKey: ['user', userId], queryFn: ... })
56
37
  const { data: posts } = useQuery({
57
38
  queryKey: ['posts', user?.id],
58
39
  queryFn: () => fetchPostsByUserId(user!.id),
59
- enabled: !!user?.id, // user 로드 후 실행
40
+ enabled: !!user?.id,
60
41
  })
61
42
 
62
- // 병렬 쿼리
43
+ // 병렬
63
44
  const usersQuery = useQuery({ queryKey: ['users'], queryFn: fetchUsers })
64
45
  const postsQuery = useQuery({ queryKey: ['posts'], queryFn: fetchPosts })
65
46
 
66
- // 동적 병렬 쿼리
47
+ // 동적 병렬
67
48
  const userQueries = useQueries({
68
49
  queries: userIds.map((id) => ({
69
50
  queryKey: ['user', id],
@@ -71,3 +52,19 @@ const userQueries = useQueries({
71
52
  })),
72
53
  })
73
54
  ```
55
+
56
+ </patterns>
57
+
58
+ <returns>
59
+
60
+ | 속성 | 설명 |
61
+ |------|------|
62
+ | data | 쿼리 결과 |
63
+ | error | 에러 객체 |
64
+ | isLoading | 첫 로딩 중 |
65
+ | isFetching | 백그라운드 페칭 중 |
66
+ | isError/isSuccess | 상태 |
67
+ | refetch | 수동 리페치 |
68
+ | status | 'pending' \| 'error' \| 'success' |
69
+
70
+ </returns>