@kood/claude-code 0.6.6 → 0.6.7
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 +7 -1
- package/package.json +1 -1
- package/templates/.claude/agents/researcher.md +8 -1
- package/templates/.claude/instructions/sourcing/reliable-search.md +49 -2
- package/templates/.claude/skills/docs-fetch/SKILL.md +5 -4
- package/templates/.claude/skills/project-optimizer/AGENTS.md +275 -0
- package/templates/.claude/skills/project-optimizer/SKILL.md +374 -0
- package/templates/.claude/skills/project-optimizer/rules/arch-config-centralize.md +66 -0
- package/templates/.claude/skills/project-optimizer/rules/arch-hot-path.md +35 -0
- package/templates/.claude/skills/project-optimizer/rules/arch-interface-segregation.md +51 -0
- package/templates/.claude/skills/project-optimizer/rules/arch-module-boundary.md +42 -0
- package/templates/.claude/skills/project-optimizer/rules/build-cache.md +57 -0
- package/templates/.claude/skills/project-optimizer/rules/build-code-split.md +56 -0
- package/templates/.claude/skills/project-optimizer/rules/build-incremental.md +65 -0
- package/templates/.claude/skills/project-optimizer/rules/build-minify.md +61 -0
- package/templates/.claude/skills/project-optimizer/rules/build-tree-shake.md +60 -0
- package/templates/.claude/skills/project-optimizer/rules/code-complexity.md +65 -0
- package/templates/.claude/skills/project-optimizer/rules/code-dead-elimination.md +32 -0
- package/templates/.claude/skills/project-optimizer/rules/code-duplication.md +54 -0
- package/templates/.claude/skills/project-optimizer/rules/code-error-handling.md +75 -0
- package/templates/.claude/skills/project-optimizer/rules/code-naming.md +52 -0
- package/templates/.claude/skills/project-optimizer/rules/concurrency-defer-await.md +54 -0
- package/templates/.claude/skills/project-optimizer/rules/concurrency-parallel.md +90 -0
- package/templates/.claude/skills/project-optimizer/rules/concurrency-pipeline.md +68 -0
- package/templates/.claude/skills/project-optimizer/rules/concurrency-pool.md +68 -0
- package/templates/.claude/skills/project-optimizer/rules/deps-lightweight-alt.md +37 -0
- package/templates/.claude/skills/project-optimizer/rules/deps-peer-align.md +44 -0
- package/templates/.claude/skills/project-optimizer/rules/deps-security-audit.md +45 -0
- package/templates/.claude/skills/project-optimizer/rules/deps-unused-removal.md +25 -0
- package/templates/.claude/skills/project-optimizer/rules/deps-version-pin.md +40 -0
- package/templates/.claude/skills/project-optimizer/rules/dx-ci-speed.md +47 -0
- package/templates/.claude/skills/project-optimizer/rules/dx-dev-server.md +35 -0
- package/templates/.claude/skills/project-optimizer/rules/dx-lint-config.md +36 -0
- package/templates/.claude/skills/project-optimizer/rules/dx-test-coverage.md +34 -0
- package/templates/.claude/skills/project-optimizer/rules/dx-type-safety.md +49 -0
- package/templates/.claude/skills/project-optimizer/rules/io-batch-queries.md +67 -0
- package/templates/.claude/skills/project-optimizer/rules/io-cache-layer.md +67 -0
- package/templates/.claude/skills/project-optimizer/rules/io-connection-reuse.md +67 -0
- package/templates/.claude/skills/project-optimizer/rules/io-serialize-minimal.md +61 -0
- package/templates/.claude/skills/project-optimizer/rules/io-stream.md +75 -0
- package/templates/.claude/skills/project-optimizer/rules/memory-bounded-cache.md +65 -0
- package/templates/.claude/skills/project-optimizer/rules/memory-large-data.md +64 -0
- package/templates/.claude/skills/project-optimizer/rules/memory-lazy-init.md +78 -0
- package/templates/.claude/skills/project-optimizer/rules/memory-leak-prevention.md +79 -0
- package/templates/.claude/skills/project-optimizer/rules/memory-pool-reuse.md +70 -0
- package/templates/.claude/skills/sql-optimizer/SKILL.md +437 -0
- package/templates/.claude/skills/sql-optimizer/orm-patterns.md +218 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/AGENTS.md +53 -14
- package/templates/.claude/skills/tanstack-start-react-best-practices/SKILL.md +93 -27
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/bundle-defer-third-party.md +42 -19
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/client-optimistic-updates.md +109 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/client-suspense-query.md +74 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/client-use-hook.md +81 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/rerender-react-compiler.md +81 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-beforeload-auth.md +121 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-file-conventions.md +104 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-link-navigation.md +119 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-nested-layouts.md +155 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-path-params.md +89 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-pending-component.md +110 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-preload-strategy.md +91 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-router-context.md +120 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/routing-search-params.md +114 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-deferred-data.md +1 -1
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-error-boundaries.md +79 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-middleware.md +85 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-serialization.md +56 -21
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-streaming.md +84 -0
- package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-validator.md +71 -0
- package/templates/.claude/skills/tauri-react-best-practices/AGENTS.md +527 -0
- package/templates/.claude/skills/tauri-react-best-practices/SKILL.md +570 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/bundle-barrel-imports.md +140 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/bundle-cargo-profile.md +96 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/bundle-frontend-treeshake.md +242 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/bundle-lazy-components.md +255 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/bundle-remove-unused-commands.md +160 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/deploy-ci-pipeline.md +269 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/deploy-signing.md +207 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/deploy-updater.md +226 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-async-commands.md +172 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-batch-commands.md +133 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-binary-response.md +198 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-channel-streaming.md +186 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-error-handling.md +250 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/ipc-type-safe.md +227 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/perf-derived-state.md +231 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/perf-functional-setstate.md +191 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/perf-index-maps.md +276 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/perf-lazy-state-init.md +196 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/plugin-lifecycle.md +265 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/plugin-mobile-compat.md +199 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/plugin-permission-scope.md +193 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/react-error-boundary.md +239 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/react-event-listener.md +151 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/react-file-src.md +155 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/react-invoke-hook.md +139 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/react-optimistic-update.md +211 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/security-capability-split.md +205 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/security-csp.md +207 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/security-least-privilege.md +106 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/security-no-wildcard.md +253 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/security-scope-paths.md +160 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/state-async-mutex.md +270 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/state-mutex-pattern.md +265 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/state-react-sync.md +375 -0
- package/templates/.claude/skills/tauri-react-best-practices/rules/state-single-container.md +275 -0
- package/templates/tanstack-start/docs/architecture.md +238 -167
- package/templates/tanstack-start/docs/library/tanstack-router/error-handling.md +777 -38
- package/templates/tanstack-start/docs/library/tanstack-router/hooks.md +549 -37
- package/templates/tanstack-start/docs/library/tanstack-router/index.md +895 -111
- package/templates/tanstack-start/docs/library/tanstack-router/navigation.md +641 -43
- package/templates/tanstack-start/docs/library/tanstack-router/route-context.md +889 -38
- package/templates/tanstack-start/docs/library/tanstack-router/search-params.md +891 -29
- package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +972 -36
- package/templates/tanstack-start/docs/library/tanstack-start/index.md +1525 -881
- package/templates/tanstack-start/docs/library/tanstack-start/middleware.md +1099 -20
- package/templates/tanstack-start/docs/library/tanstack-start/routing.md +796 -30
- package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +953 -35
- package/templates/tanstack-start/docs/library/tanstack-start/setup.md +371 -15
- package/templates/tauri/CLAUDE.md +189 -0
- package/templates/tauri/docs/guides/distribution.md +261 -0
- package/templates/tauri/docs/guides/getting-started.md +302 -0
- package/templates/tauri/docs/guides/mobile.md +288 -0
- package/templates/tauri/docs/library/tauri/index.md +510 -0
package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-serialization.md
CHANGED
|
@@ -1,38 +1,73 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: Minimize Serialization
|
|
2
|
+
title: Minimize Serialization in Loader Data
|
|
3
3
|
impact: HIGH
|
|
4
4
|
impactDescription: reduces data transfer size
|
|
5
|
-
tags: server,
|
|
5
|
+
tags: server, loader, serialization, tanstack-start
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
##
|
|
8
|
+
## Loader 데이터 직렬화 최소화
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
TanStack Start의 loader에서 반환하는 데이터는 서버 → 클라이언트로 직렬화되어 전달됩니다. 이 직렬화된 데이터는 HTML 응답 크기와 하이드레이션 시간에 직접 영향을 미치므로 **클라이언트가 실제로 사용하는 필드만 반환하세요**.
|
|
11
11
|
|
|
12
12
|
**❌ 잘못된 예시 (50개 필드 모두 직렬화):**
|
|
13
13
|
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
```typescript
|
|
15
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
16
|
+
import { createFileRoute } from '@tanstack/react-router'
|
|
17
|
+
|
|
18
|
+
const getUser = createServerFn().handler(async () => {
|
|
19
|
+
return await db.user.findUnique({ where: { id: '1' } }) // 50개 필드
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
export const Route = createFileRoute('/profile')({
|
|
23
|
+
loader: async () => {
|
|
24
|
+
const user = await getUser()
|
|
25
|
+
return { user } // 50개 필드 모두 직렬화
|
|
26
|
+
}
|
|
27
|
+
})
|
|
19
28
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return <div>{user.name}</div>
|
|
29
|
+
function ProfilePage() {
|
|
30
|
+
const { user } = Route.useLoaderData()
|
|
31
|
+
return <div>{user.name}</div> // 1개 필드만 사용
|
|
23
32
|
}
|
|
24
33
|
```
|
|
25
34
|
|
|
26
|
-
**✅ 올바른 예시 (
|
|
35
|
+
**✅ 올바른 예시 (필요한 필드만 직렬화):**
|
|
27
36
|
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
const user = await
|
|
31
|
-
return
|
|
32
|
-
}
|
|
37
|
+
```typescript
|
|
38
|
+
const getUser = createServerFn().handler(async () => {
|
|
39
|
+
const user = await db.user.findUnique({ where: { id: '1' } })
|
|
40
|
+
return { name: user.name, email: user.email } // 필요한 필드만
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
export const Route = createFileRoute('/profile')({
|
|
44
|
+
loader: async () => {
|
|
45
|
+
const user = await getUser()
|
|
46
|
+
return { userName: user.name, userEmail: user.email }
|
|
47
|
+
}
|
|
48
|
+
})
|
|
33
49
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return
|
|
50
|
+
function ProfilePage() {
|
|
51
|
+
const { userName, userEmail } = Route.useLoaderData()
|
|
52
|
+
return (
|
|
53
|
+
<div>
|
|
54
|
+
<div>{userName}</div>
|
|
55
|
+
<div>{userEmail}</div>
|
|
56
|
+
</div>
|
|
57
|
+
)
|
|
37
58
|
}
|
|
38
59
|
```
|
|
60
|
+
|
|
61
|
+
**✅ Server Function에서 select로 필드 제한:**
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
const getUser = createServerFn().handler(async () => {
|
|
65
|
+
// DB 쿼리 자체에서 필드 제한 (가장 효율적)
|
|
66
|
+
return await db.user.findUnique({
|
|
67
|
+
where: { id: '1' },
|
|
68
|
+
select: { name: true, email: true, avatar: true }
|
|
69
|
+
})
|
|
70
|
+
})
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
loader 데이터가 클수록 SSR HTML 크기, 하이드레이션 시간, 클라이언트 네비게이션 데이터 전송량이 모두 증가합니다.
|
package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-streaming.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Stream Data from Server Functions
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: progressive data delivery
|
|
5
|
+
tags: server, streaming, async-generator, ReadableStream, tanstack-start
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Server Functions에서 데이터 스트리밍
|
|
9
|
+
|
|
10
|
+
대량 데이터나 실시간 업데이트가 필요한 경우, Server Function에서 스트리밍으로 데이터를 점진적 전달합니다.
|
|
11
|
+
|
|
12
|
+
**❌ 잘못된 예시 (전체 데이터 대기):**
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
const generateReport = createServerFn({ method: 'POST' })
|
|
16
|
+
.handler(async () => {
|
|
17
|
+
const items = []
|
|
18
|
+
for (const chunk of await processLargeDataset()) {
|
|
19
|
+
items.push(chunk)
|
|
20
|
+
}
|
|
21
|
+
return items // 전체 처리 완료까지 대기
|
|
22
|
+
})
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**✅ 올바른 예시 (async generator로 스트리밍):**
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
29
|
+
|
|
30
|
+
const generateReport = createServerFn({ method: 'POST' })
|
|
31
|
+
.handler(async function* () {
|
|
32
|
+
yield { status: 'processing', progress: 0 }
|
|
33
|
+
|
|
34
|
+
for await (const chunk of processLargeDataset()) {
|
|
35
|
+
yield { status: 'processing', data: chunk, progress: chunk.index }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
yield { status: 'complete', progress: 100 }
|
|
39
|
+
})
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**✅ ReadableStream 방식 (세밀한 제어):**
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
const streamResponse = createServerFn({ method: 'POST' })
|
|
46
|
+
.handler(async () => {
|
|
47
|
+
return new ReadableStream({
|
|
48
|
+
start(controller) {
|
|
49
|
+
const encoder = new TextEncoder()
|
|
50
|
+
controller.enqueue(encoder.encode(JSON.stringify({ msg: 'chunk 1' })))
|
|
51
|
+
controller.enqueue(encoder.encode(JSON.stringify({ msg: 'chunk 2' })))
|
|
52
|
+
controller.close()
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
})
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**클라이언트에서 스트림 소비:**
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
function ReportGenerator() {
|
|
62
|
+
const [chunks, setChunks] = useState<ReportChunk[]>([])
|
|
63
|
+
|
|
64
|
+
const handleGenerate = async () => {
|
|
65
|
+
const stream = await generateReport()
|
|
66
|
+
for await (const chunk of stream) {
|
|
67
|
+
setChunks(prev => [...prev, chunk])
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<div>
|
|
73
|
+
<button onClick={handleGenerate}>Generate</button>
|
|
74
|
+
{chunks.map((chunk, i) => <ChunkDisplay key={i} chunk={chunk} />)}
|
|
75
|
+
</div>
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**사용 시점:** AI 응답 스트리밍, 대용량 CSV/JSON 내보내기, 실시간 진행률 표시, 로그 스트리밍.
|
|
81
|
+
|
|
82
|
+
**주의:** ReadableStream 사용 시 UTF-8 인코딩을 위해 `TextEncoder.encode()` 필수. async generator가 더 간결하고 타입 안전합니다.
|
|
83
|
+
|
|
84
|
+
참고: [Streaming Data from Server Functions](https://tanstack.com/start/latest/docs/framework/react/guide/streaming-data-from-server-functions)
|
package/templates/.claude/skills/tanstack-start-react-best-practices/rules/server-validator.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use inputValidator for Type-Safe Server Functions
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: runtime type safety with Zod
|
|
5
|
+
tags: server, validation, inputValidator, zod, tanstack-start
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## inputValidator로 타입 안전한 Server Functions
|
|
9
|
+
|
|
10
|
+
`createServerFn`의 `.inputValidator()`로 런타임 입력 검증과 TypeScript 타입 추론을 동시에 확보합니다.
|
|
11
|
+
|
|
12
|
+
**❌ 잘못된 예시 (검증 없음, 타입 안전하지 않음):**
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
const createUser = createServerFn({ method: 'POST' })
|
|
16
|
+
.handler(async (data: any) => {
|
|
17
|
+
// data가 검증되지 않음 - 런타임 에러 위험
|
|
18
|
+
return await db.user.create({ data })
|
|
19
|
+
})
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**✅ 올바른 예시 (Zod로 검증 + 타입 추론):**
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { z } from 'zod'
|
|
26
|
+
import { createServerFn } from '@tanstack/react-start'
|
|
27
|
+
|
|
28
|
+
const UserSchema = z.object({
|
|
29
|
+
name: z.string().min(1),
|
|
30
|
+
email: z.string().email()
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const createUser = createServerFn({ method: 'POST' })
|
|
34
|
+
.inputValidator((d: unknown) => UserSchema.parse(d))
|
|
35
|
+
.handler(async ({ data }) => {
|
|
36
|
+
// data는 자동으로 { name: string; email: string } 타입
|
|
37
|
+
return await db.user.create({ data })
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
// 클라이언트에서 호출
|
|
41
|
+
await createUser({ data: { name: 'Alice', email: 'alice@example.com' } })
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**중요:** `.inputValidator()`는 반드시 **함수** 형태로 전달해야 합니다. Zod schema를 직접 전달하면 안 됩니다.
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
// ❌ 잘못됨: schema 직접 전달
|
|
48
|
+
.inputValidator(UserSchema)
|
|
49
|
+
|
|
50
|
+
// ✅ 올바름: 함수로 감싸서 전달
|
|
51
|
+
.inputValidator((d: unknown) => UserSchema.parse(d))
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**FormData 검증:**
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
const uploadFile = createServerFn({ method: 'POST' })
|
|
58
|
+
.inputValidator((d: unknown) => {
|
|
59
|
+
if (!(d instanceof FormData)) throw new Error('Expected FormData')
|
|
60
|
+
return {
|
|
61
|
+
name: d.get('name')?.toString() || '',
|
|
62
|
+
file: d.get('file') as File
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
.handler(async ({ data }) => {
|
|
66
|
+
// data.name, data.file 모두 타입 안전
|
|
67
|
+
return await saveFile(data.file)
|
|
68
|
+
})
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
참고: [Server Functions Guide](https://tanstack.com/start/latest/docs/framework/react/guide/server-functions)
|