xxf_react 0.7.1 → 0.7.3
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.
|
@@ -4,63 +4,114 @@
|
|
|
4
4
|
* 使用 Builder 模式定义 API,类似 Android Retrofit。
|
|
5
5
|
* 采用泛型累积模式,每次 .get() / .post() 调用都返回带有累积类型的新 Builder。
|
|
6
6
|
*
|
|
7
|
-
* ##
|
|
7
|
+
* ## 类型安全特性
|
|
8
8
|
*
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
11
|
-
* - `
|
|
12
|
-
* -
|
|
9
|
+
* - **端点名称字面量**:每个端点名称保留字面量类型(如 `'getUser'`)
|
|
10
|
+
* - **泛型累积**:链式调用累积所有端点类型 `T & Record<K, ApiEndpoint<...>>`
|
|
11
|
+
* - **路径参数推断**:从 path 字符串自动提取 `{param}` 并约束 `pathParams` 类型
|
|
12
|
+
* - **Body 类型约束**:POST/PUT/PATCH 支持指定请求体类型
|
|
13
|
+
* - **防止重复端点**:添加已存在的端点名称会编译报错
|
|
13
14
|
*
|
|
14
15
|
* @example
|
|
15
16
|
* ```ts
|
|
17
|
+
* interface CreateUserDTO { name: string; email: string }
|
|
18
|
+
*
|
|
16
19
|
* // 定义 API
|
|
17
20
|
* const userApi = ApiBuilder.create({
|
|
18
21
|
* baseUrl: 'https://api.example.com',
|
|
19
22
|
* })
|
|
20
23
|
* .get<User>('getUser', {
|
|
21
|
-
* path: '/users/{id}',
|
|
24
|
+
* path: '/users/{id}', // pathParams 自动约束为 { id: string | number }
|
|
22
25
|
* cache: { mode: CacheMode.IfCache, ttl: 60000 },
|
|
23
26
|
* })
|
|
24
27
|
* .get<User[]>('getUsers', { path: '/users' })
|
|
25
|
-
* .post<User>('createUser', { path: '/users' })
|
|
28
|
+
* .post<User, CreateUserDTO>('createUser', { path: '/users' }) // body 类型为 CreateUserDTO
|
|
26
29
|
* .build()
|
|
27
30
|
*
|
|
28
31
|
* // ✅ 类型正确推断
|
|
29
|
-
* userApi.getUser({ pathParams: { id: '123' } })
|
|
30
|
-
* userApi.getUsers()
|
|
31
|
-
* userApi.createUser({ body: { name: 'John' } })
|
|
32
|
+
* userApi.getUser({ pathParams: { id: '123' } }) // pathParams 必须有 id
|
|
33
|
+
* userApi.getUsers() // 无需 pathParams
|
|
34
|
+
* userApi.createUser({ body: { name: 'John', email: 'x' } }) // body 类型检查
|
|
32
35
|
*
|
|
33
36
|
* // ❌ 类型错误会被捕获
|
|
34
|
-
* userApi.
|
|
35
|
-
*
|
|
36
|
-
* //
|
|
37
|
-
* for await (const { data, fromCache } of userApi.getUser({ pathParams: { id: '123' } })) {
|
|
38
|
-
* console.log(data, fromCache)
|
|
39
|
-
* }
|
|
37
|
+
* userApi.getUser({ pathParams: { wrong: '1' } }) // Error: 缺少 id
|
|
38
|
+
* userApi.createUser({ body: { wrong: 'x' } }) // Error: body 类型不匹配
|
|
39
|
+
* userApi.unknownMethod() // Error: 方法不存在
|
|
40
40
|
* ```
|
|
41
41
|
*/
|
|
42
42
|
import ky, { type Options as KyOptions } from 'ky';
|
|
43
43
|
import { HttpClient } from '../client/HttpClient';
|
|
44
44
|
import { ApiStream } from '../client/ApiStream';
|
|
45
|
-
import type { RequestConfig,
|
|
45
|
+
import type { RequestConfig, CacheConfig, HttpClientConfig } from '../types';
|
|
46
|
+
/**
|
|
47
|
+
* 从路径字符串中提取参数名称
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ExtractPathParams<'/users/{id}'> = 'id'
|
|
51
|
+
* ExtractPathParams<'/users/{userId}/posts/{postId}'> = 'userId' | 'postId'
|
|
52
|
+
* ExtractPathParams<'/users'> = never
|
|
53
|
+
*/
|
|
54
|
+
type ExtractPathParams<Path extends string> = Path extends `${string}{${infer Param}}${infer Rest}` ? Param | ExtractPathParams<Rest> : never;
|
|
55
|
+
/**
|
|
56
|
+
* 根据路径参数生成 pathParams 类型
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* PathParamsType<'/users/{id}'> = { id: string | number }
|
|
60
|
+
* PathParamsType<'/users'> = undefined (无需路径参数)
|
|
61
|
+
*/
|
|
62
|
+
type PathParamsType<Path extends string> = ExtractPathParams<Path> extends never ? undefined : Record<ExtractPathParams<Path>, string | number>;
|
|
63
|
+
/**
|
|
64
|
+
* 判断路径是否有参数
|
|
65
|
+
*/
|
|
66
|
+
type HasPathParams<Path extends string> = ExtractPathParams<Path> extends never ? false : true;
|
|
67
|
+
/**
|
|
68
|
+
* 带类型约束的 API 调用选项
|
|
69
|
+
*
|
|
70
|
+
* @template Path 路径字符串字面量
|
|
71
|
+
* @template TBody 请求体类型(用于 POST/PUT/PATCH)
|
|
72
|
+
* @template HasBody 是否需要 body
|
|
73
|
+
*/
|
|
74
|
+
type TypedApiOptions<Path extends string, TBody = never, HasBody extends boolean = false> = {
|
|
75
|
+
/** 查询参数,会自动过滤 undefined 和 null */
|
|
76
|
+
query?: Record<string, string | number | boolean | undefined>;
|
|
77
|
+
/** 覆盖缓存配置(优先级最高) */
|
|
78
|
+
cache?: Partial<CacheConfig>;
|
|
79
|
+
/** 覆盖请求头 */
|
|
80
|
+
headers?: Record<string, string>;
|
|
81
|
+
} & (HasPathParams<Path> extends true ? {
|
|
82
|
+
pathParams: PathParamsType<Path>;
|
|
83
|
+
} : {
|
|
84
|
+
pathParams?: undefined;
|
|
85
|
+
}) & (HasBody extends true ? {
|
|
86
|
+
body?: TBody;
|
|
87
|
+
} : {
|
|
88
|
+
body?: never;
|
|
89
|
+
});
|
|
46
90
|
/**
|
|
47
|
-
* API
|
|
91
|
+
* API 端点函数类型(带路径参数和 Body 类型约束)
|
|
92
|
+
*
|
|
93
|
+
* @template TResponse 响应数据类型
|
|
94
|
+
* @template Path 路径字符串字面量
|
|
95
|
+
* @template TBody 请求体类型
|
|
96
|
+
* @template HasBody 是否需要 body
|
|
48
97
|
*/
|
|
49
|
-
export type ApiEndpoint<TResponse> = {
|
|
50
|
-
(options?:
|
|
98
|
+
export type ApiEndpoint<TResponse, Path extends string = string, TBody = never, HasBody extends boolean = false> = {
|
|
99
|
+
(options?: TypedApiOptions<Path, TBody, HasBody>): ApiStream<TResponse>;
|
|
51
100
|
/** 请求配置 */
|
|
52
101
|
config: RequestConfig;
|
|
53
102
|
};
|
|
54
103
|
/**
|
|
55
|
-
* API
|
|
104
|
+
* API 定义类型(端点集合)
|
|
56
105
|
*/
|
|
57
|
-
export type ApiDefinition = Record<string, ApiEndpoint<unknown>>;
|
|
106
|
+
export type ApiDefinition = Record<string, ApiEndpoint<unknown, string, unknown, boolean>>;
|
|
58
107
|
/**
|
|
59
|
-
*
|
|
108
|
+
* 端点选项(构建时配置)
|
|
109
|
+
*
|
|
110
|
+
* @template Path 路径字符串字面量,用于类型推断
|
|
60
111
|
*/
|
|
61
|
-
interface EndpointOptions {
|
|
112
|
+
interface EndpointOptions<Path extends string = string> {
|
|
62
113
|
/** 请求路径,支持 {param} 占位符 */
|
|
63
|
-
path:
|
|
114
|
+
path: Path;
|
|
64
115
|
/** 请求方法 */
|
|
65
116
|
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
66
117
|
/** 请求头 */
|
|
@@ -73,7 +124,9 @@ interface EndpointOptions {
|
|
|
73
124
|
cache?: CacheConfig;
|
|
74
125
|
}
|
|
75
126
|
/**
|
|
76
|
-
* API
|
|
127
|
+
* API 构建器类
|
|
128
|
+
*
|
|
129
|
+
* @template T 当前已定义的端点类型集合,通过链式调用累积
|
|
77
130
|
*/
|
|
78
131
|
export declare class ApiBuilder<T extends ApiDefinition = Record<string, never>> {
|
|
79
132
|
private client;
|
|
@@ -81,54 +134,206 @@ export declare class ApiBuilder<T extends ApiDefinition = Record<string, never>>
|
|
|
81
134
|
private constructor();
|
|
82
135
|
/**
|
|
83
136
|
* 创建 API 构建器
|
|
137
|
+
*
|
|
138
|
+
* @param config HTTP 客户端配置
|
|
139
|
+
* @returns 新的 ApiBuilder 实例
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```ts
|
|
143
|
+
* const api = ApiBuilder.create({
|
|
144
|
+
* baseUrl: 'https://api.example.com',
|
|
145
|
+
* timeout: 10000,
|
|
146
|
+
* })
|
|
147
|
+
* ```
|
|
84
148
|
*/
|
|
85
149
|
static create(config: HttpClientConfig): ApiBuilder;
|
|
86
150
|
/**
|
|
87
151
|
* 从现有 ky 实例创建
|
|
152
|
+
*
|
|
153
|
+
* @param kyInstance 已配置的 ky 实例
|
|
154
|
+
* @param config 可选的额外配置
|
|
155
|
+
* @returns 新的 ApiBuilder 实例
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```ts
|
|
159
|
+
* const kyInstance = ky.create({ prefixUrl: 'https://api.example.com' })
|
|
160
|
+
* const api = ApiBuilder.from(kyInstance)
|
|
161
|
+
* ```
|
|
88
162
|
*/
|
|
89
163
|
static from(kyInstance: ReturnType<typeof ky.create>, config?: Partial<HttpClientConfig>): ApiBuilder;
|
|
90
164
|
/**
|
|
91
165
|
* 定义 GET 请求
|
|
92
|
-
*
|
|
166
|
+
*
|
|
167
|
+
* @template TResponse 响应数据类型
|
|
168
|
+
* @template K 端点名称(自动推断,不能与已有端点重复)
|
|
169
|
+
* @template Path 路径字符串(自动推断,用于提取路径参数)
|
|
170
|
+
*
|
|
171
|
+
* @param name 端点名称
|
|
172
|
+
* @param options 端点配置
|
|
173
|
+
* @returns 累积了新端点类型的 ApiBuilder
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```ts
|
|
177
|
+
* .get<User>('getUser', {
|
|
178
|
+
* path: '/users/{id}', // pathParams 自动约束为 { id: string | number }
|
|
179
|
+
* cache: { mode: CacheMode.IfCache },
|
|
180
|
+
* })
|
|
181
|
+
* ```
|
|
93
182
|
*/
|
|
94
|
-
get<TResponse, K extends string>(name: K
|
|
183
|
+
get<TResponse, K extends string = string, Path extends string = string>(name: K extends keyof T ? never : K, // 防止重复端点名称
|
|
184
|
+
options: Omit<EndpointOptions<Path>, 'method'>): ApiBuilder<T & Record<K, ApiEndpoint<TResponse, Path, never, false>>>;
|
|
95
185
|
/**
|
|
96
186
|
* 定义 POST 请求
|
|
97
|
-
*
|
|
187
|
+
*
|
|
188
|
+
* @template TResponse 响应数据类型
|
|
189
|
+
* @template TBody 请求体类型(可选,默认 unknown)
|
|
190
|
+
* @template K 端点名称(自动推断)
|
|
191
|
+
* @template Path 路径字符串(自动推断)
|
|
192
|
+
*
|
|
193
|
+
* @param name 端点名称
|
|
194
|
+
* @param options 端点配置
|
|
195
|
+
* @returns 累积了新端点类型的 ApiBuilder
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```ts
|
|
199
|
+
* interface CreateUserDTO { name: string; email: string }
|
|
200
|
+
*
|
|
201
|
+
* .post<User, CreateUserDTO>('createUser', {
|
|
202
|
+
* path: '/users',
|
|
203
|
+
* })
|
|
204
|
+
* // body 类型约束为 CreateUserDTO
|
|
205
|
+
* ```
|
|
98
206
|
*/
|
|
99
|
-
post<TResponse, K extends string>(name: K, options: Omit<EndpointOptions
|
|
207
|
+
post<TResponse, TBody = unknown, K extends string = string, Path extends string = string>(name: K extends keyof T ? never : K, options: Omit<EndpointOptions<Path>, 'method'>): ApiBuilder<T & Record<K, ApiEndpoint<TResponse, Path, TBody, true>>>;
|
|
100
208
|
/**
|
|
101
209
|
* 定义 PUT 请求
|
|
102
|
-
*
|
|
210
|
+
*
|
|
211
|
+
* @template TResponse 响应数据类型
|
|
212
|
+
* @template TBody 请求体类型(可选,默认 unknown)
|
|
213
|
+
* @template K 端点名称(自动推断)
|
|
214
|
+
* @template Path 路径字符串(自动推断)
|
|
215
|
+
*
|
|
216
|
+
* @param name 端点名称
|
|
217
|
+
* @param options 端点配置
|
|
218
|
+
* @returns 累积了新端点类型的 ApiBuilder
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```ts
|
|
222
|
+
* .put<User, UpdateUserDTO>('updateUser', {
|
|
223
|
+
* path: '/users/{id}',
|
|
224
|
+
* })
|
|
225
|
+
* ```
|
|
103
226
|
*/
|
|
104
|
-
put<TResponse, K extends string>(name: K, options: Omit<EndpointOptions
|
|
227
|
+
put<TResponse, TBody = unknown, K extends string = string, Path extends string = string>(name: K extends keyof T ? never : K, options: Omit<EndpointOptions<Path>, 'method'>): ApiBuilder<T & Record<K, ApiEndpoint<TResponse, Path, TBody, true>>>;
|
|
105
228
|
/**
|
|
106
229
|
* 定义 DELETE 请求
|
|
107
|
-
*
|
|
230
|
+
*
|
|
231
|
+
* @template TResponse 响应数据类型
|
|
232
|
+
* @template K 端点名称(自动推断)
|
|
233
|
+
* @template Path 路径字符串(自动推断)
|
|
234
|
+
*
|
|
235
|
+
* @param name 端点名称
|
|
236
|
+
* @param options 端点配置
|
|
237
|
+
* @returns 累积了新端点类型的 ApiBuilder
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```ts
|
|
241
|
+
* .delete<void>('deleteUser', {
|
|
242
|
+
* path: '/users/{id}',
|
|
243
|
+
* })
|
|
244
|
+
* ```
|
|
108
245
|
*/
|
|
109
|
-
delete<TResponse, K extends string>(name: K, options: Omit<EndpointOptions
|
|
246
|
+
delete<TResponse, K extends string = string, Path extends string = string>(name: K extends keyof T ? never : K, options: Omit<EndpointOptions<Path>, 'method'>): ApiBuilder<T & Record<K, ApiEndpoint<TResponse, Path, never, false>>>;
|
|
110
247
|
/**
|
|
111
248
|
* 定义 PATCH 请求
|
|
112
|
-
*
|
|
249
|
+
*
|
|
250
|
+
* @template TResponse 响应数据类型
|
|
251
|
+
* @template TBody 请求体类型(可选,默认 unknown)
|
|
252
|
+
* @template K 端点名称(自动推断)
|
|
253
|
+
* @template Path 路径字符串(自动推断)
|
|
254
|
+
*
|
|
255
|
+
* @param name 端点名称
|
|
256
|
+
* @param options 端点配置
|
|
257
|
+
* @returns 累积了新端点类型的 ApiBuilder
|
|
258
|
+
*
|
|
259
|
+
* @example
|
|
260
|
+
* ```ts
|
|
261
|
+
* .patch<User, Partial<UpdateUserDTO>>('patchUser', {
|
|
262
|
+
* path: '/users/{id}',
|
|
263
|
+
* })
|
|
264
|
+
* ```
|
|
113
265
|
*/
|
|
114
|
-
patch<TResponse, K extends string>(name: K, options: Omit<EndpointOptions
|
|
266
|
+
patch<TResponse, TBody = unknown, K extends string = string, Path extends string = string>(name: K extends keyof T ? never : K, options: Omit<EndpointOptions<Path>, 'method'>): ApiBuilder<T & Record<K, ApiEndpoint<TResponse, Path, TBody, true>>>;
|
|
115
267
|
/**
|
|
116
|
-
*
|
|
117
|
-
*
|
|
268
|
+
* 通用端点定义(内部方法)
|
|
269
|
+
*
|
|
270
|
+
* @template TResponse 响应数据类型
|
|
271
|
+
* @template K 端点名称
|
|
272
|
+
* @template Path 路径字符串
|
|
273
|
+
* @template TBody 请求体类型
|
|
274
|
+
* @template HasBody 是否有请求体
|
|
118
275
|
*/
|
|
119
276
|
private endpoint;
|
|
120
277
|
/**
|
|
121
278
|
* 扩展 ky 实例(添加 hooks 等)
|
|
279
|
+
*
|
|
280
|
+
* @param options ky 配置选项
|
|
281
|
+
* @returns this(支持链式调用)
|
|
282
|
+
*
|
|
283
|
+
* @example
|
|
284
|
+
* ```ts
|
|
285
|
+
* .extend({
|
|
286
|
+
* hooks: {
|
|
287
|
+
* beforeRequest: [(req) => {
|
|
288
|
+
* req.headers.set('Authorization', `Bearer ${token}`)
|
|
289
|
+
* }],
|
|
290
|
+
* },
|
|
291
|
+
* })
|
|
292
|
+
* ```
|
|
122
293
|
*/
|
|
123
294
|
extend(options: KyOptions): this;
|
|
124
295
|
/**
|
|
125
296
|
* 构建 API 服务
|
|
297
|
+
*
|
|
298
|
+
* 将所有定义的端点转换为可调用的 API 对象。
|
|
299
|
+
* 每个端点都带有完整的类型信息(响应类型、路径参数、请求体类型)。
|
|
300
|
+
*
|
|
301
|
+
* @returns 类型安全的 API 对象
|
|
302
|
+
*
|
|
303
|
+
* @example
|
|
304
|
+
* ```ts
|
|
305
|
+
* const api = ApiBuilder.create({ baseUrl: '...' })
|
|
306
|
+
* .get<User>('getUser', { path: '/users/{id}' })
|
|
307
|
+
* .post<User, CreateUserDTO>('createUser', { path: '/users' })
|
|
308
|
+
* .build()
|
|
309
|
+
*
|
|
310
|
+
* // 类型安全调用
|
|
311
|
+
* await api.getUser({ pathParams: { id: '1' } })
|
|
312
|
+
* await api.createUser({ body: { name: 'John', email: 'x@x.com' } })
|
|
313
|
+
* ```
|
|
126
314
|
*/
|
|
127
315
|
build(): T;
|
|
128
316
|
/**
|
|
129
317
|
* 获取 HTTP 客户端实例(用于高级操作)
|
|
318
|
+
*
|
|
319
|
+
* @returns HttpClient 实例
|
|
320
|
+
*
|
|
321
|
+
* @example
|
|
322
|
+
* ```ts
|
|
323
|
+
* const client = api.getClient()
|
|
324
|
+
* await client.clearCache()
|
|
325
|
+
* ```
|
|
130
326
|
*/
|
|
131
327
|
getClient(): HttpClient;
|
|
132
328
|
}
|
|
133
|
-
|
|
329
|
+
/**
|
|
330
|
+
* 从路径字符串中提取参数名称
|
|
331
|
+
*
|
|
332
|
+
* @example
|
|
333
|
+
* ```ts
|
|
334
|
+
* type Params = ExtractPathParams<'/users/{userId}/posts/{postId}'>
|
|
335
|
+
* // Params = 'userId' | 'postId'
|
|
336
|
+
* ```
|
|
337
|
+
*/
|
|
338
|
+
export type { ExtractPathParams, PathParamsType, HasPathParams };
|
|
134
339
|
//# sourceMappingURL=ApiBuilder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApiBuilder.d.ts","sourceRoot":"","sources":["../../../src/http/api/ApiBuilder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EAAE,EAAE,EAAE,KAAK,OAAO,IAAI,SAAS,EAAE,MAAM,IAAI,CAAA;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"ApiBuilder.d.ts","sourceRoot":"","sources":["../../../src/http/api/ApiBuilder.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,44 +4,49 @@
|
|
|
4
4
|
* 使用 Builder 模式定义 API,类似 Android Retrofit。
|
|
5
5
|
* 采用泛型累积模式,每次 .get() / .post() 调用都返回带有累积类型的新 Builder。
|
|
6
6
|
*
|
|
7
|
-
* ##
|
|
7
|
+
* ## 类型安全特性
|
|
8
8
|
*
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
11
|
-
* - `
|
|
12
|
-
* -
|
|
9
|
+
* - **端点名称字面量**:每个端点名称保留字面量类型(如 `'getUser'`)
|
|
10
|
+
* - **泛型累积**:链式调用累积所有端点类型 `T & Record<K, ApiEndpoint<...>>`
|
|
11
|
+
* - **路径参数推断**:从 path 字符串自动提取 `{param}` 并约束 `pathParams` 类型
|
|
12
|
+
* - **Body 类型约束**:POST/PUT/PATCH 支持指定请求体类型
|
|
13
|
+
* - **防止重复端点**:添加已存在的端点名称会编译报错
|
|
13
14
|
*
|
|
14
15
|
* @example
|
|
15
16
|
* ```ts
|
|
17
|
+
* interface CreateUserDTO { name: string; email: string }
|
|
18
|
+
*
|
|
16
19
|
* // 定义 API
|
|
17
20
|
* const userApi = ApiBuilder.create({
|
|
18
21
|
* baseUrl: 'https://api.example.com',
|
|
19
22
|
* })
|
|
20
23
|
* .get<User>('getUser', {
|
|
21
|
-
* path: '/users/{id}',
|
|
24
|
+
* path: '/users/{id}', // pathParams 自动约束为 { id: string | number }
|
|
22
25
|
* cache: { mode: CacheMode.IfCache, ttl: 60000 },
|
|
23
26
|
* })
|
|
24
27
|
* .get<User[]>('getUsers', { path: '/users' })
|
|
25
|
-
* .post<User>('createUser', { path: '/users' })
|
|
28
|
+
* .post<User, CreateUserDTO>('createUser', { path: '/users' }) // body 类型为 CreateUserDTO
|
|
26
29
|
* .build()
|
|
27
30
|
*
|
|
28
31
|
* // ✅ 类型正确推断
|
|
29
|
-
* userApi.getUser({ pathParams: { id: '123' } })
|
|
30
|
-
* userApi.getUsers()
|
|
31
|
-
* userApi.createUser({ body: { name: 'John' } })
|
|
32
|
+
* userApi.getUser({ pathParams: { id: '123' } }) // pathParams 必须有 id
|
|
33
|
+
* userApi.getUsers() // 无需 pathParams
|
|
34
|
+
* userApi.createUser({ body: { name: 'John', email: 'x' } }) // body 类型检查
|
|
32
35
|
*
|
|
33
36
|
* // ❌ 类型错误会被捕获
|
|
34
|
-
* userApi.
|
|
35
|
-
*
|
|
36
|
-
* //
|
|
37
|
-
* for await (const { data, fromCache } of userApi.getUser({ pathParams: { id: '123' } })) {
|
|
38
|
-
* console.log(data, fromCache)
|
|
39
|
-
* }
|
|
37
|
+
* userApi.getUser({ pathParams: { wrong: '1' } }) // Error: 缺少 id
|
|
38
|
+
* userApi.createUser({ body: { wrong: 'x' } }) // Error: body 类型不匹配
|
|
39
|
+
* userApi.unknownMethod() // Error: 方法不存在
|
|
40
40
|
* ```
|
|
41
41
|
*/
|
|
42
42
|
import { HttpClient } from '../client/HttpClient';
|
|
43
|
+
// ============================================================================
|
|
44
|
+
// API 构建器
|
|
45
|
+
// ============================================================================
|
|
43
46
|
/**
|
|
44
|
-
* API
|
|
47
|
+
* API 构建器类
|
|
48
|
+
*
|
|
49
|
+
* @template T 当前已定义的端点类型集合,通过链式调用累积
|
|
45
50
|
*/
|
|
46
51
|
export class ApiBuilder {
|
|
47
52
|
constructor(config) {
|
|
@@ -50,12 +55,33 @@ export class ApiBuilder {
|
|
|
50
55
|
}
|
|
51
56
|
/**
|
|
52
57
|
* 创建 API 构建器
|
|
58
|
+
*
|
|
59
|
+
* @param config HTTP 客户端配置
|
|
60
|
+
* @returns 新的 ApiBuilder 实例
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```ts
|
|
64
|
+
* const api = ApiBuilder.create({
|
|
65
|
+
* baseUrl: 'https://api.example.com',
|
|
66
|
+
* timeout: 10000,
|
|
67
|
+
* })
|
|
68
|
+
* ```
|
|
53
69
|
*/
|
|
54
70
|
static create(config) {
|
|
55
71
|
return new ApiBuilder(config);
|
|
56
72
|
}
|
|
57
73
|
/**
|
|
58
74
|
* 从现有 ky 实例创建
|
|
75
|
+
*
|
|
76
|
+
* @param kyInstance 已配置的 ky 实例
|
|
77
|
+
* @param config 可选的额外配置
|
|
78
|
+
* @returns 新的 ApiBuilder 实例
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* const kyInstance = ky.create({ prefixUrl: 'https://api.example.com' })
|
|
83
|
+
* const api = ApiBuilder.from(kyInstance)
|
|
84
|
+
* ```
|
|
59
85
|
*/
|
|
60
86
|
static from(kyInstance, config) {
|
|
61
87
|
const builder = new ApiBuilder({
|
|
@@ -67,42 +93,125 @@ export class ApiBuilder {
|
|
|
67
93
|
}
|
|
68
94
|
/**
|
|
69
95
|
* 定义 GET 请求
|
|
70
|
-
*
|
|
96
|
+
*
|
|
97
|
+
* @template TResponse 响应数据类型
|
|
98
|
+
* @template K 端点名称(自动推断,不能与已有端点重复)
|
|
99
|
+
* @template Path 路径字符串(自动推断,用于提取路径参数)
|
|
100
|
+
*
|
|
101
|
+
* @param name 端点名称
|
|
102
|
+
* @param options 端点配置
|
|
103
|
+
* @returns 累积了新端点类型的 ApiBuilder
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```ts
|
|
107
|
+
* .get<User>('getUser', {
|
|
108
|
+
* path: '/users/{id}', // pathParams 自动约束为 { id: string | number }
|
|
109
|
+
* cache: { mode: CacheMode.IfCache },
|
|
110
|
+
* })
|
|
111
|
+
* ```
|
|
71
112
|
*/
|
|
72
|
-
get(name,
|
|
113
|
+
get(name, // 防止重复端点名称
|
|
114
|
+
options) {
|
|
73
115
|
return this.endpoint(name, { ...options, method: 'GET' });
|
|
74
116
|
}
|
|
75
117
|
/**
|
|
76
118
|
* 定义 POST 请求
|
|
77
|
-
*
|
|
119
|
+
*
|
|
120
|
+
* @template TResponse 响应数据类型
|
|
121
|
+
* @template TBody 请求体类型(可选,默认 unknown)
|
|
122
|
+
* @template K 端点名称(自动推断)
|
|
123
|
+
* @template Path 路径字符串(自动推断)
|
|
124
|
+
*
|
|
125
|
+
* @param name 端点名称
|
|
126
|
+
* @param options 端点配置
|
|
127
|
+
* @returns 累积了新端点类型的 ApiBuilder
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```ts
|
|
131
|
+
* interface CreateUserDTO { name: string; email: string }
|
|
132
|
+
*
|
|
133
|
+
* .post<User, CreateUserDTO>('createUser', {
|
|
134
|
+
* path: '/users',
|
|
135
|
+
* })
|
|
136
|
+
* // body 类型约束为 CreateUserDTO
|
|
137
|
+
* ```
|
|
78
138
|
*/
|
|
79
139
|
post(name, options) {
|
|
80
140
|
return this.endpoint(name, { ...options, method: 'POST' });
|
|
81
141
|
}
|
|
82
142
|
/**
|
|
83
143
|
* 定义 PUT 请求
|
|
84
|
-
*
|
|
144
|
+
*
|
|
145
|
+
* @template TResponse 响应数据类型
|
|
146
|
+
* @template TBody 请求体类型(可选,默认 unknown)
|
|
147
|
+
* @template K 端点名称(自动推断)
|
|
148
|
+
* @template Path 路径字符串(自动推断)
|
|
149
|
+
*
|
|
150
|
+
* @param name 端点名称
|
|
151
|
+
* @param options 端点配置
|
|
152
|
+
* @returns 累积了新端点类型的 ApiBuilder
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* ```ts
|
|
156
|
+
* .put<User, UpdateUserDTO>('updateUser', {
|
|
157
|
+
* path: '/users/{id}',
|
|
158
|
+
* })
|
|
159
|
+
* ```
|
|
85
160
|
*/
|
|
86
161
|
put(name, options) {
|
|
87
162
|
return this.endpoint(name, { ...options, method: 'PUT' });
|
|
88
163
|
}
|
|
89
164
|
/**
|
|
90
165
|
* 定义 DELETE 请求
|
|
91
|
-
*
|
|
166
|
+
*
|
|
167
|
+
* @template TResponse 响应数据类型
|
|
168
|
+
* @template K 端点名称(自动推断)
|
|
169
|
+
* @template Path 路径字符串(自动推断)
|
|
170
|
+
*
|
|
171
|
+
* @param name 端点名称
|
|
172
|
+
* @param options 端点配置
|
|
173
|
+
* @returns 累积了新端点类型的 ApiBuilder
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```ts
|
|
177
|
+
* .delete<void>('deleteUser', {
|
|
178
|
+
* path: '/users/{id}',
|
|
179
|
+
* })
|
|
180
|
+
* ```
|
|
92
181
|
*/
|
|
93
182
|
delete(name, options) {
|
|
94
183
|
return this.endpoint(name, { ...options, method: 'DELETE' });
|
|
95
184
|
}
|
|
96
185
|
/**
|
|
97
186
|
* 定义 PATCH 请求
|
|
98
|
-
*
|
|
187
|
+
*
|
|
188
|
+
* @template TResponse 响应数据类型
|
|
189
|
+
* @template TBody 请求体类型(可选,默认 unknown)
|
|
190
|
+
* @template K 端点名称(自动推断)
|
|
191
|
+
* @template Path 路径字符串(自动推断)
|
|
192
|
+
*
|
|
193
|
+
* @param name 端点名称
|
|
194
|
+
* @param options 端点配置
|
|
195
|
+
* @returns 累积了新端点类型的 ApiBuilder
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```ts
|
|
199
|
+
* .patch<User, Partial<UpdateUserDTO>>('patchUser', {
|
|
200
|
+
* path: '/users/{id}',
|
|
201
|
+
* })
|
|
202
|
+
* ```
|
|
99
203
|
*/
|
|
100
204
|
patch(name, options) {
|
|
101
205
|
return this.endpoint(name, { ...options, method: 'PATCH' });
|
|
102
206
|
}
|
|
103
207
|
/**
|
|
104
|
-
*
|
|
105
|
-
*
|
|
208
|
+
* 通用端点定义(内部方法)
|
|
209
|
+
*
|
|
210
|
+
* @template TResponse 响应数据类型
|
|
211
|
+
* @template K 端点名称
|
|
212
|
+
* @template Path 路径字符串
|
|
213
|
+
* @template TBody 请求体类型
|
|
214
|
+
* @template HasBody 是否有请求体
|
|
106
215
|
*/
|
|
107
216
|
endpoint(name, options) {
|
|
108
217
|
var _a;
|
|
@@ -120,6 +229,20 @@ export class ApiBuilder {
|
|
|
120
229
|
}
|
|
121
230
|
/**
|
|
122
231
|
* 扩展 ky 实例(添加 hooks 等)
|
|
232
|
+
*
|
|
233
|
+
* @param options ky 配置选项
|
|
234
|
+
* @returns this(支持链式调用)
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* ```ts
|
|
238
|
+
* .extend({
|
|
239
|
+
* hooks: {
|
|
240
|
+
* beforeRequest: [(req) => {
|
|
241
|
+
* req.headers.set('Authorization', `Bearer ${token}`)
|
|
242
|
+
* }],
|
|
243
|
+
* },
|
|
244
|
+
* })
|
|
245
|
+
* ```
|
|
123
246
|
*/
|
|
124
247
|
extend(options) {
|
|
125
248
|
this.client.extendKy(options);
|
|
@@ -127,10 +250,28 @@ export class ApiBuilder {
|
|
|
127
250
|
}
|
|
128
251
|
/**
|
|
129
252
|
* 构建 API 服务
|
|
253
|
+
*
|
|
254
|
+
* 将所有定义的端点转换为可调用的 API 对象。
|
|
255
|
+
* 每个端点都带有完整的类型信息(响应类型、路径参数、请求体类型)。
|
|
256
|
+
*
|
|
257
|
+
* @returns 类型安全的 API 对象
|
|
258
|
+
*
|
|
259
|
+
* @example
|
|
260
|
+
* ```ts
|
|
261
|
+
* const api = ApiBuilder.create({ baseUrl: '...' })
|
|
262
|
+
* .get<User>('getUser', { path: '/users/{id}' })
|
|
263
|
+
* .post<User, CreateUserDTO>('createUser', { path: '/users' })
|
|
264
|
+
* .build()
|
|
265
|
+
*
|
|
266
|
+
* // 类型安全调用
|
|
267
|
+
* await api.getUser({ pathParams: { id: '1' } })
|
|
268
|
+
* await api.createUser({ body: { name: 'John', email: 'x@x.com' } })
|
|
269
|
+
* ```
|
|
130
270
|
*/
|
|
131
271
|
build() {
|
|
132
272
|
const api = {};
|
|
133
273
|
for (const [name, config] of this.endpoints) {
|
|
274
|
+
// 运行时不需要类型检查,类型安全由编译时保证
|
|
134
275
|
const endpoint = ((options) => {
|
|
135
276
|
return this.client.request(config, options);
|
|
136
277
|
});
|
|
@@ -141,6 +282,14 @@ export class ApiBuilder {
|
|
|
141
282
|
}
|
|
142
283
|
/**
|
|
143
284
|
* 获取 HTTP 客户端实例(用于高级操作)
|
|
285
|
+
*
|
|
286
|
+
* @returns HttpClient 实例
|
|
287
|
+
*
|
|
288
|
+
* @example
|
|
289
|
+
* ```ts
|
|
290
|
+
* const client = api.getClient()
|
|
291
|
+
* await client.clearCache()
|
|
292
|
+
* ```
|
|
144
293
|
*/
|
|
145
294
|
getClient() {
|
|
146
295
|
return this.client;
|
package/dist/http/api/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { ApiBuilder, type ApiEndpoint, type ApiDefinition } from './ApiBuilder';
|
|
1
|
+
export { ApiBuilder, type ApiEndpoint, type ApiDefinition, type ExtractPathParams, type PathParamsType, type HasPathParams, } from './ApiBuilder';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/http/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/http/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,UAAU,EACV,KAAK,WAAW,EAChB,KAAK,aAAa,EAElB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,aAAa,GACrB,MAAM,cAAc,CAAA"}
|
package/dist/http/api/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { ApiBuilder } from './ApiBuilder';
|
|
1
|
+
export { ApiBuilder, } from './ApiBuilder';
|