@kood/claude-code 0.1.6 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +109 -216
- package/package.json +8 -2
- package/templates/hono/CLAUDE.md +59 -328
- package/templates/hono/docs/architecture/architecture.md +93 -747
- package/templates/hono/docs/deployment/cloudflare.md +59 -513
- package/templates/hono/docs/deployment/docker.md +41 -356
- package/templates/hono/docs/deployment/index.md +54 -190
- package/templates/hono/docs/deployment/railway.md +36 -306
- package/templates/hono/docs/deployment/vercel.md +49 -434
- package/templates/hono/docs/library/ai-sdk/index.md +53 -290
- package/templates/hono/docs/library/ai-sdk/openrouter.md +19 -387
- package/templates/hono/docs/library/ai-sdk/providers.md +28 -394
- package/templates/hono/docs/library/ai-sdk/streaming.md +52 -353
- package/templates/hono/docs/library/ai-sdk/structured-output.md +63 -395
- package/templates/hono/docs/library/ai-sdk/tools.md +62 -431
- package/templates/hono/docs/library/hono/env-setup.md +24 -313
- package/templates/hono/docs/library/hono/error-handling.md +34 -295
- package/templates/hono/docs/library/hono/index.md +29 -121
- package/templates/hono/docs/library/hono/middleware.md +21 -188
- package/templates/hono/docs/library/hono/rpc.md +40 -341
- package/templates/hono/docs/library/hono/validation.md +35 -195
- package/templates/hono/docs/library/pino/index.md +42 -333
- package/templates/hono/docs/library/prisma/cloudflare-d1.md +64 -367
- package/templates/hono/docs/library/prisma/config.md +19 -260
- package/templates/hono/docs/library/prisma/index.md +67 -320
- package/templates/hono/docs/library/zod/index.md +53 -257
- package/templates/npx/CLAUDE.md +62 -274
- package/templates/npx/docs/references/patterns.md +160 -0
- package/templates/tanstack-start/CLAUDE.md +100 -256
- package/templates/tanstack-start/docs/architecture/architecture.md +44 -589
- package/templates/tanstack-start/docs/deployment/cloudflare.md +37 -424
- package/templates/tanstack-start/docs/deployment/index.md +57 -286
- package/templates/tanstack-start/docs/deployment/nitro.md +36 -318
- package/templates/tanstack-start/docs/deployment/railway.md +40 -409
- package/templates/tanstack-start/docs/deployment/vercel.md +43 -465
- package/templates/tanstack-start/docs/design/components.md +77 -311
- package/templates/tanstack-start/docs/design/index.md +113 -69
- package/templates/tanstack-start/docs/design/safe-area.md +51 -250
- package/templates/tanstack-start/docs/design/tailwind-setup.md +45 -359
- package/templates/tanstack-start/docs/guides/conventions.md +103 -0
- package/templates/tanstack-start/docs/guides/env-setup.md +34 -340
- package/templates/tanstack-start/docs/guides/getting-started.md +22 -209
- package/templates/tanstack-start/docs/guides/hooks.md +166 -0
- package/templates/tanstack-start/docs/guides/routes.md +166 -0
- package/templates/tanstack-start/docs/guides/services.md +143 -0
- package/templates/tanstack-start/docs/library/better-auth/2fa.md +27 -115
- package/templates/tanstack-start/docs/library/better-auth/advanced.md +22 -105
- package/templates/tanstack-start/docs/library/better-auth/index.md +17 -66
- package/templates/tanstack-start/docs/library/better-auth/plugins.md +11 -88
- package/templates/tanstack-start/docs/library/better-auth/session.md +12 -92
- package/templates/tanstack-start/docs/library/better-auth/setup.md +9 -91
- package/templates/tanstack-start/docs/library/prisma/cloudflare-d1.md +30 -358
- package/templates/tanstack-start/docs/library/prisma/config.md +27 -327
- package/templates/tanstack-start/docs/library/prisma/crud.md +46 -174
- package/templates/tanstack-start/docs/library/prisma/index.md +23 -113
- package/templates/tanstack-start/docs/library/prisma/relations.md +31 -153
- package/templates/tanstack-start/docs/library/prisma/schema.md +40 -217
- package/templates/tanstack-start/docs/library/prisma/setup.md +12 -112
- package/templates/tanstack-start/docs/library/prisma/transactions.md +20 -110
- package/templates/tanstack-start/docs/library/tanstack-query/index.md +26 -97
- package/templates/tanstack-start/docs/library/tanstack-query/invalidation.md +28 -107
- package/templates/tanstack-start/docs/library/tanstack-query/optimistic-updates.md +44 -146
- package/templates/tanstack-start/docs/library/tanstack-query/use-mutation.md +33 -127
- package/templates/tanstack-start/docs/library/tanstack-query/use-query.md +49 -149
- package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +19 -112
- package/templates/tanstack-start/docs/library/tanstack-start/index.md +33 -80
- package/templates/tanstack-start/docs/library/tanstack-start/middleware.md +28 -106
- package/templates/tanstack-start/docs/library/tanstack-start/routing.md +21 -118
- package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +34 -246
- package/templates/tanstack-start/docs/library/tanstack-start/setup.md +6 -39
- package/templates/tanstack-start/docs/library/zod/complex-types.md +32 -156
- package/templates/tanstack-start/docs/library/zod/index.md +31 -144
- package/templates/tanstack-start/docs/library/zod/transforms.md +20 -129
- package/templates/tanstack-start/docs/library/zod/validation.md +39 -155
- package/templates/hono/docs/commands/git.md +0 -145
- package/templates/hono/docs/mcp/context7.md +0 -106
- package/templates/hono/docs/mcp/index.md +0 -176
- package/templates/hono/docs/mcp/sequential-thinking.md +0 -101
- package/templates/hono/docs/mcp/serena.md +0 -269
- package/templates/hono/docs/mcp/sgrep.md +0 -105
- package/templates/hono/docs/skills/gemini-review/SKILL.md +0 -220
- package/templates/hono/docs/skills/gemini-review/references/checklists.md +0 -136
- package/templates/hono/docs/skills/gemini-review/references/prompt-templates.md +0 -303
- package/templates/npx/docs/commands/git.md +0 -145
- package/templates/npx/docs/mcp/index.md +0 -60
- package/templates/npx/docs/skills/gemini-review/SKILL.md +0 -220
- package/templates/npx/docs/skills/gemini-review/references/checklists.md +0 -134
- package/templates/npx/docs/skills/gemini-review/references/prompt-templates.md +0 -301
- package/templates/tanstack-start/docs/commands/git.md +0 -145
- package/templates/tanstack-start/docs/design/accessibility.md +0 -433
- package/templates/tanstack-start/docs/design/color.md +0 -235
- package/templates/tanstack-start/docs/design/spacing.md +0 -341
- package/templates/tanstack-start/docs/design/typography.md +0 -324
- package/templates/tanstack-start/docs/guides/best-practices.md +0 -950
- package/templates/tanstack-start/docs/guides/husky-lint-staged.md +0 -303
- package/templates/tanstack-start/docs/guides/prettier.md +0 -189
- package/templates/tanstack-start/docs/guides/project-templates.md +0 -710
- package/templates/tanstack-start/docs/library/tanstack-query/setup.md +0 -107
- package/templates/tanstack-start/docs/library/zod/basic-types.md +0 -186
- package/templates/tanstack-start/docs/mcp/context7.md +0 -204
- package/templates/tanstack-start/docs/mcp/index.md +0 -177
- package/templates/tanstack-start/docs/mcp/sequential-thinking.md +0 -180
- package/templates/tanstack-start/docs/mcp/serena.md +0 -269
- package/templates/tanstack-start/docs/mcp/sgrep.md +0 -174
- package/templates/tanstack-start/docs/skills/gemini-review/SKILL.md +0 -220
- package/templates/tanstack-start/docs/skills/gemini-review/references/checklists.md +0 -144
- package/templates/tanstack-start/docs/skills/gemini-review/references/prompt-templates.md +0 -292
|
@@ -1,18 +1,10 @@
|
|
|
1
1
|
# Hono RPC Client
|
|
2
2
|
|
|
3
|
-
> Type-safe API
|
|
3
|
+
> Type-safe API 호출
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
##
|
|
8
|
-
|
|
9
|
-
Hono의 RPC 기능은 서버 타입을 클라이언트에서 직접 사용하여 타입 안전한 API 호출을 가능하게 합니다.
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## 기본 사용법
|
|
14
|
-
|
|
15
|
-
### 서버 설정
|
|
7
|
+
## 서버 설정
|
|
16
8
|
|
|
17
9
|
```typescript
|
|
18
10
|
// server.ts
|
|
@@ -21,132 +13,68 @@ import { zValidator } from '@hono/zod-validator'
|
|
|
21
13
|
import { z } from 'zod'
|
|
22
14
|
|
|
23
15
|
const app = new Hono()
|
|
24
|
-
.get('/hello', (c) => {
|
|
25
|
-
return c.json({ message: 'Hello!' })
|
|
26
|
-
})
|
|
16
|
+
.get('/hello', (c) => c.json({ message: 'Hello!' }))
|
|
27
17
|
.get('/users/:id', (c) => {
|
|
28
18
|
const id = c.req.param('id')
|
|
29
19
|
return c.json({ id, name: 'John' })
|
|
30
20
|
})
|
|
31
|
-
.post(
|
|
32
|
-
'
|
|
33
|
-
zValidator(
|
|
34
|
-
'json',
|
|
35
|
-
z.object({
|
|
36
|
-
name: z.string(),
|
|
37
|
-
email: z.email(),
|
|
38
|
-
})
|
|
39
|
-
),
|
|
21
|
+
.post('/users',
|
|
22
|
+
zValidator('json', z.object({ name: z.string(), email: z.email() })),
|
|
40
23
|
(c) => {
|
|
41
24
|
const data = c.req.valid('json')
|
|
42
25
|
return c.json({ id: '1', ...data }, 201)
|
|
43
26
|
}
|
|
44
27
|
)
|
|
45
28
|
|
|
46
|
-
//
|
|
29
|
+
// 타입 export 필수
|
|
47
30
|
export type AppType = typeof app
|
|
48
31
|
export default app
|
|
49
32
|
```
|
|
50
33
|
|
|
51
|
-
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 클라이언트 사용
|
|
52
37
|
|
|
53
38
|
```typescript
|
|
54
39
|
// client.ts
|
|
55
40
|
import { hc } from 'hono/client'
|
|
56
41
|
import type { AppType } from './server'
|
|
57
42
|
|
|
58
|
-
// 클라이언트 생성
|
|
59
43
|
const client = hc<AppType>('http://localhost:8787/')
|
|
60
44
|
|
|
61
|
-
// GET
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (res.ok) {
|
|
65
|
-
const data = await res.json() // { message: string }
|
|
66
|
-
console.log(data.message)
|
|
67
|
-
}
|
|
68
|
-
}
|
|
45
|
+
// GET
|
|
46
|
+
const res = await client.hello.$get()
|
|
47
|
+
const data = await res.json() // { message: string }
|
|
69
48
|
|
|
70
49
|
// Path Parameter
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
param: { id: '123' },
|
|
74
|
-
})
|
|
75
|
-
const data = await res.json() // { id: string, name: string }
|
|
76
|
-
}
|
|
50
|
+
const res = await client.users[':id'].$get({ param: { id: '123' } })
|
|
51
|
+
const data = await res.json() // { id: string, name: string }
|
|
77
52
|
|
|
78
|
-
// POST
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
name: 'John',
|
|
83
|
-
email: 'john@example.com',
|
|
84
|
-
},
|
|
85
|
-
})
|
|
86
|
-
if (res.status === 201) {
|
|
87
|
-
const data = await res.json()
|
|
88
|
-
console.log(data.id)
|
|
89
|
-
}
|
|
90
|
-
}
|
|
53
|
+
// POST
|
|
54
|
+
const res = await client.users.$post({
|
|
55
|
+
json: { name: 'John', email: 'john@example.com' },
|
|
56
|
+
})
|
|
91
57
|
```
|
|
92
58
|
|
|
93
59
|
---
|
|
94
60
|
|
|
95
61
|
## 요청 옵션
|
|
96
62
|
|
|
97
|
-
### Query Parameters
|
|
98
|
-
|
|
99
63
|
```typescript
|
|
100
|
-
//
|
|
101
|
-
const app = new Hono().get(
|
|
102
|
-
'/search',
|
|
103
|
-
zValidator('query', z.object({ q: z.string(), page: z.coerce.number() })),
|
|
104
|
-
(c) => {
|
|
105
|
-
const { q, page } = c.req.valid('query')
|
|
106
|
-
return c.json({ query: q, page, results: [] })
|
|
107
|
-
}
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
// 클라이언트
|
|
64
|
+
// Query
|
|
111
65
|
const res = await client.search.$get({
|
|
112
66
|
query: { q: 'hono', page: '1' },
|
|
113
67
|
})
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
### Form Data
|
|
117
68
|
|
|
118
|
-
|
|
119
|
-
// 서버
|
|
120
|
-
const app = new Hono().post(
|
|
121
|
-
'/posts',
|
|
122
|
-
zValidator('form', z.object({ title: z.string(), body: z.string() })),
|
|
123
|
-
(c) => {
|
|
124
|
-
const data = c.req.valid('form')
|
|
125
|
-
return c.json({ post: data }, 201)
|
|
126
|
-
}
|
|
127
|
-
)
|
|
128
|
-
|
|
129
|
-
// 클라이언트
|
|
69
|
+
// Form
|
|
130
70
|
const res = await client.posts.$post({
|
|
131
|
-
form: {
|
|
132
|
-
title: 'Hello',
|
|
133
|
-
body: 'World',
|
|
134
|
-
},
|
|
71
|
+
form: { title: 'Hello', body: 'World' },
|
|
135
72
|
})
|
|
136
|
-
```
|
|
137
73
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
```typescript
|
|
74
|
+
// Headers
|
|
141
75
|
const res = await client.posts.$post(
|
|
142
|
-
{
|
|
143
|
-
|
|
144
|
-
},
|
|
145
|
-
{
|
|
146
|
-
headers: {
|
|
147
|
-
'X-Custom-Header': 'value',
|
|
148
|
-
},
|
|
149
|
-
}
|
|
76
|
+
{ json: { title: 'Test' } },
|
|
77
|
+
{ headers: { 'X-Custom': 'value' } }
|
|
150
78
|
)
|
|
151
79
|
```
|
|
152
80
|
|
|
@@ -154,38 +82,10 @@ const res = await client.posts.$post(
|
|
|
154
82
|
|
|
155
83
|
## 클라이언트 설정
|
|
156
84
|
|
|
157
|
-
### 공통 헤더
|
|
158
|
-
|
|
159
|
-
```typescript
|
|
160
|
-
const client = hc<AppType>('http://localhost:8787/', {
|
|
161
|
-
headers: {
|
|
162
|
-
Authorization: 'Bearer TOKEN',
|
|
163
|
-
},
|
|
164
|
-
})
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
### Credentials (쿠키 전송)
|
|
168
|
-
|
|
169
|
-
```typescript
|
|
170
|
-
const client = hc<AppType>('http://localhost:8787/', {
|
|
171
|
-
init: {
|
|
172
|
-
credentials: 'include',
|
|
173
|
-
},
|
|
174
|
-
})
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
### 전체 설정
|
|
178
|
-
|
|
179
85
|
```typescript
|
|
180
86
|
const client = hc<AppType>('http://localhost:8787/', {
|
|
181
|
-
headers: {
|
|
182
|
-
|
|
183
|
-
'Content-Type': 'application/json',
|
|
184
|
-
},
|
|
185
|
-
init: {
|
|
186
|
-
credentials: 'include',
|
|
187
|
-
mode: 'cors',
|
|
188
|
-
},
|
|
87
|
+
headers: { Authorization: 'Bearer TOKEN' },
|
|
88
|
+
init: { credentials: 'include' },
|
|
189
89
|
})
|
|
190
90
|
```
|
|
191
91
|
|
|
@@ -193,228 +93,22 @@ const client = hc<AppType>('http://localhost:8787/', {
|
|
|
193
93
|
|
|
194
94
|
## 타입 추론
|
|
195
95
|
|
|
196
|
-
### InferRequestType
|
|
197
|
-
|
|
198
96
|
```typescript
|
|
199
|
-
import type { InferRequestType } from 'hono/client'
|
|
97
|
+
import type { InferRequestType, InferResponseType } from 'hono/client'
|
|
200
98
|
|
|
201
|
-
|
|
202
|
-
type CreateUserRequest = InferRequestType<typeof client.users.$post>['json']
|
|
99
|
+
type CreateUserInput = InferRequestType<typeof client.users.$post>['json']
|
|
203
100
|
// { name: string; email: string }
|
|
204
101
|
|
|
205
|
-
// Form 타입 추론
|
|
206
|
-
type PostFormRequest = InferRequestType<typeof client.posts.$post>['form']
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
### InferResponseType
|
|
210
|
-
|
|
211
|
-
```typescript
|
|
212
|
-
import type { InferResponseType } from 'hono/client'
|
|
213
|
-
|
|
214
|
-
// 응답 타입 추론
|
|
215
102
|
type UserResponse = InferResponseType<typeof client.users[':id'].$get>
|
|
216
103
|
// { id: string; name: string }
|
|
217
|
-
|
|
218
|
-
// 특정 상태 코드의 응답 타입
|
|
219
|
-
type NotFoundResponse = InferResponseType<typeof client.users[':id'].$get, 404>
|
|
220
|
-
// { error: string }
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
---
|
|
224
|
-
|
|
225
|
-
## 상태 코드 처리
|
|
226
|
-
|
|
227
|
-
### 서버에서 명시적 상태 코드
|
|
228
|
-
|
|
229
|
-
```typescript
|
|
230
|
-
// server.ts
|
|
231
|
-
const app = new Hono().get(
|
|
232
|
-
'/posts/:id',
|
|
233
|
-
zValidator('param', z.object({ id: z.string() })),
|
|
234
|
-
async (c) => {
|
|
235
|
-
const { id } = c.req.valid('param')
|
|
236
|
-
const post = await getPost(id)
|
|
237
|
-
|
|
238
|
-
if (!post) {
|
|
239
|
-
return c.json({ error: 'Post not found' }, 404) // 명시적 404
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
return c.json({ post }, 200) // 명시적 200
|
|
243
|
-
}
|
|
244
|
-
)
|
|
245
|
-
|
|
246
|
-
export type AppType = typeof app
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
### 클라이언트에서 상태 코드 처리
|
|
250
|
-
|
|
251
|
-
```typescript
|
|
252
|
-
// client.ts
|
|
253
|
-
async function getPost(id: string) {
|
|
254
|
-
const res = await client.posts[':id'].$get({
|
|
255
|
-
param: { id },
|
|
256
|
-
})
|
|
257
|
-
|
|
258
|
-
if (res.status === 404) {
|
|
259
|
-
const data = await res.json() // { error: string }
|
|
260
|
-
console.log(data.error)
|
|
261
|
-
return null
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
if (res.status === 200) {
|
|
265
|
-
const data = await res.json() // { post: Post }
|
|
266
|
-
return data.post
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
throw new Error('Unexpected status')
|
|
270
|
-
}
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
---
|
|
274
|
-
|
|
275
|
-
## URL 생성
|
|
276
|
-
|
|
277
|
-
```typescript
|
|
278
|
-
// URL 객체 생성 (요청 없이)
|
|
279
|
-
const url = client.posts[':id'].$url({
|
|
280
|
-
param: { id: '123' },
|
|
281
|
-
})
|
|
282
|
-
|
|
283
|
-
console.log(url.pathname) // /posts/123
|
|
284
|
-
console.log(url.toString()) // http://localhost:8787/posts/123
|
|
285
104
|
```
|
|
286
105
|
|
|
287
106
|
---
|
|
288
107
|
|
|
289
|
-
##
|
|
290
|
-
|
|
291
|
-
### 서버
|
|
292
|
-
|
|
293
|
-
```typescript
|
|
294
|
-
// routes/users.ts
|
|
295
|
-
import { Hono } from 'hono'
|
|
296
|
-
|
|
297
|
-
const users = new Hono()
|
|
298
|
-
.get('/', (c) => c.json({ users: [] }))
|
|
299
|
-
.get('/:id', (c) => c.json({ id: c.req.param('id') }))
|
|
300
|
-
.post('/', (c) => c.json({ created: true }, 201))
|
|
301
|
-
|
|
302
|
-
export default users
|
|
303
|
-
export type UsersType = typeof users
|
|
304
|
-
|
|
305
|
-
// index.ts
|
|
306
|
-
import { Hono } from 'hono'
|
|
307
|
-
import users from './routes/users'
|
|
308
|
-
|
|
309
|
-
const app = new Hono().route('/users', users)
|
|
310
|
-
|
|
311
|
-
export type AppType = typeof app
|
|
312
|
-
export default app
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
### 클라이언트
|
|
316
|
-
|
|
317
|
-
```typescript
|
|
318
|
-
import { hc } from 'hono/client'
|
|
319
|
-
import type { AppType } from './server'
|
|
320
|
-
|
|
321
|
-
const client = hc<AppType>('http://localhost:8787/')
|
|
322
|
-
|
|
323
|
-
// /users 엔드포인트 호출
|
|
324
|
-
await client.users.$get()
|
|
325
|
-
await client.users[':id'].$get({ param: { id: '123' } })
|
|
326
|
-
await client.users.$post({ json: { name: 'John' } })
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
---
|
|
330
|
-
|
|
331
|
-
## 에러 처리
|
|
332
|
-
|
|
333
|
-
```typescript
|
|
334
|
-
async function fetchUser(id: string) {
|
|
335
|
-
try {
|
|
336
|
-
const res = await client.users[':id'].$get({
|
|
337
|
-
param: { id },
|
|
338
|
-
})
|
|
339
|
-
|
|
340
|
-
if (!res.ok) {
|
|
341
|
-
const error = await res.json()
|
|
342
|
-
throw new Error(error.message || 'Request failed')
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
return await res.json()
|
|
346
|
-
} catch (err) {
|
|
347
|
-
if (err instanceof TypeError) {
|
|
348
|
-
// 네트워크 에러
|
|
349
|
-
console.error('Network error:', err)
|
|
350
|
-
}
|
|
351
|
-
throw err
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
---
|
|
357
|
-
|
|
358
|
-
## 완전한 예제
|
|
359
|
-
|
|
360
|
-
### 서버
|
|
361
|
-
|
|
362
|
-
```typescript
|
|
363
|
-
// server.ts
|
|
364
|
-
import { Hono } from 'hono'
|
|
365
|
-
import { zValidator } from '@hono/zod-validator'
|
|
366
|
-
import { z } from 'zod'
|
|
367
|
-
|
|
368
|
-
const userSchema = z.object({
|
|
369
|
-
name: z.string().min(1),
|
|
370
|
-
email: z.email(),
|
|
371
|
-
})
|
|
372
|
-
|
|
373
|
-
const app = new Hono()
|
|
374
|
-
.get('/users', (c) => {
|
|
375
|
-
return c.json({ users: [{ id: '1', name: 'John' }] })
|
|
376
|
-
})
|
|
377
|
-
.get('/users/:id', (c) => {
|
|
378
|
-
const id = c.req.param('id')
|
|
379
|
-
return c.json({ user: { id, name: 'John' } })
|
|
380
|
-
})
|
|
381
|
-
.post('/users', zValidator('json', userSchema), (c) => {
|
|
382
|
-
const data = c.req.valid('json')
|
|
383
|
-
return c.json({ user: { id: '1', ...data } }, 201)
|
|
384
|
-
})
|
|
385
|
-
.put('/users/:id', zValidator('json', userSchema.partial()), (c) => {
|
|
386
|
-
const id = c.req.param('id')
|
|
387
|
-
const data = c.req.valid('json')
|
|
388
|
-
return c.json({ user: { id, ...data } })
|
|
389
|
-
})
|
|
390
|
-
.delete('/users/:id', (c) => {
|
|
391
|
-
return c.json({ success: true })
|
|
392
|
-
})
|
|
393
|
-
|
|
394
|
-
export type AppType = typeof app
|
|
395
|
-
export default app
|
|
396
|
-
```
|
|
397
|
-
|
|
398
|
-
### 클라이언트
|
|
108
|
+
## CRUD 예제
|
|
399
109
|
|
|
400
110
|
```typescript
|
|
401
|
-
|
|
402
|
-
import { hc } from 'hono/client'
|
|
403
|
-
import type { InferRequestType, InferResponseType } from 'hono/client'
|
|
404
|
-
import type { AppType } from './server'
|
|
405
|
-
|
|
406
|
-
const client = hc<AppType>('http://localhost:8787/', {
|
|
407
|
-
headers: {
|
|
408
|
-
Authorization: 'Bearer TOKEN',
|
|
409
|
-
},
|
|
410
|
-
})
|
|
411
|
-
|
|
412
|
-
// 타입 추론
|
|
413
|
-
type CreateUserInput = InferRequestType<typeof client.users.$post>['json']
|
|
414
|
-
type User = InferResponseType<typeof client.users[':id'].$get>['user']
|
|
415
|
-
|
|
416
|
-
// CRUD 함수
|
|
417
|
-
export const userApi = {
|
|
111
|
+
const userApi = {
|
|
418
112
|
list: async () => {
|
|
419
113
|
const res = await client.users.$get()
|
|
420
114
|
return res.json()
|
|
@@ -431,10 +125,7 @@ export const userApi = {
|
|
|
431
125
|
},
|
|
432
126
|
|
|
433
127
|
update: async (id: string, data: Partial<CreateUserInput>) => {
|
|
434
|
-
const res = await client.users[':id'].$put({
|
|
435
|
-
param: { id },
|
|
436
|
-
json: data,
|
|
437
|
-
})
|
|
128
|
+
const res = await client.users[':id'].$put({ param: { id }, json: data })
|
|
438
129
|
return res.json()
|
|
439
130
|
},
|
|
440
131
|
|
|
@@ -447,8 +138,16 @@ export const userApi = {
|
|
|
447
138
|
|
|
448
139
|
---
|
|
449
140
|
|
|
141
|
+
## URL 생성
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
const url = client.posts[':id'].$url({ param: { id: '123' } })
|
|
145
|
+
console.log(url.pathname) // /posts/123
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
450
150
|
## 관련 문서
|
|
451
151
|
|
|
452
152
|
- [기본 사용법](./index.md)
|
|
453
153
|
- [Zod 검증](./validation.md)
|
|
454
|
-
- [에러 처리](./error-handling.md)
|