@h-ai/api-client 0.1.0-alpha5

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.
@@ -0,0 +1,348 @@
1
+ import * as _h_ai_core from '@h-ai/core';
2
+ import { HaiResult } from '@h-ai/core';
3
+ import { z } from 'zod';
4
+
5
+ declare const HaiApiClientError: {
6
+ readonly NETWORK_ERROR: _h_ai_core.HaiErrorDef;
7
+ readonly TIMEOUT: _h_ai_core.HaiErrorDef;
8
+ readonly SERVER_ERROR: _h_ai_core.HaiErrorDef;
9
+ readonly UNAUTHORIZED: _h_ai_core.HaiErrorDef;
10
+ readonly FORBIDDEN: _h_ai_core.HaiErrorDef;
11
+ readonly NOT_FOUND: _h_ai_core.HaiErrorDef;
12
+ readonly VALIDATION_FAILED: _h_ai_core.HaiErrorDef;
13
+ readonly TOKEN_REFRESH_FAILED: _h_ai_core.HaiErrorDef;
14
+ readonly NOT_INITIALIZED: _h_ai_core.HaiErrorDef;
15
+ readonly CONFIG_ERROR: _h_ai_core.HaiErrorDef;
16
+ readonly UNKNOWN: _h_ai_core.HaiErrorDef;
17
+ };
18
+ /**
19
+ * API 端点契约定义
20
+ *
21
+ * 描述单个 API 端点的 HTTP 方法、路径、入参/出参 Schema 与元数据。
22
+ * 客户端通过 `api.call(endpoint, input)` 调用,服务端通过
23
+ * `kit.fromContract(endpoint, handler)` 响应,两端共享同一份契约。
24
+ *
25
+ * @typeParam TInput - 入参类型(由 Zod Schema 推导)
26
+ * @typeParam TOutput - 出参类型(由 Zod Schema 推导)
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * const loginEndpoint: EndpointDef<LoginInput, LoginOutput> = {
31
+ * method: 'POST',
32
+ * path: '/auth/login',
33
+ * input: LoginInputSchema,
34
+ * output: LoginOutputSchema,
35
+ * requireAuth: false,
36
+ * }
37
+ * ```
38
+ */
39
+ interface EndpointDef<TInput = unknown, TOutput = unknown> {
40
+ /** HTTP 方法 */
41
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
42
+ /** 相对路径(相对于 API 前缀,如 '/auth/login') */
43
+ path: string;
44
+ /** 入参 Zod Schema(GET 请求为 query params,其他为 body) */
45
+ input: z.ZodType<TInput>;
46
+ /** 出参 Zod Schema */
47
+ output: z.ZodType<TOutput>;
48
+ /** 是否需要认证(默认 true) */
49
+ requireAuth?: boolean;
50
+ /** OpenAPI 描述元数据 */
51
+ meta?: {
52
+ summary?: string;
53
+ tags?: string[];
54
+ };
55
+ }
56
+ /**
57
+ * Token 对(与 @h-ai/iam 的 TokenPair 对齐)
58
+ */
59
+ interface TokenPair {
60
+ /** Access Token */
61
+ accessToken: string;
62
+ /** Refresh Token */
63
+ refreshToken: string;
64
+ /** 过期时间(秒) */
65
+ expiresIn: number;
66
+ /** Token 类型 */
67
+ tokenType: 'Bearer';
68
+ }
69
+ /**
70
+ * Token 存储适配器
71
+ *
72
+ * 可插拔存储后端(localStorage / memory / Capacitor Preferences / 自定义)。
73
+ */
74
+ interface TokenStorage {
75
+ /** 获取 Access Token */
76
+ getAccessToken: () => Promise<string | null>;
77
+ /** 设置 Access Token */
78
+ setAccessToken: (token: string) => Promise<void>;
79
+ /** 获取 Refresh Token */
80
+ getRefreshToken: () => Promise<string | null>;
81
+ /** 设置 Refresh Token */
82
+ setRefreshToken: (token: string) => Promise<void>;
83
+ /** 清空所有 Token */
84
+ clear: () => Promise<void>;
85
+ }
86
+ /**
87
+ * 请求配置(传递给拦截器)
88
+ */
89
+ interface RequestConfig {
90
+ /** 完整 URL */
91
+ url: string;
92
+ /** HTTP 方法 */
93
+ method: string;
94
+ /** 请求头 */
95
+ headers: Record<string, string>;
96
+ /** 请求体(已序列化) */
97
+ body?: string | FormData;
98
+ /** 信号(abort) */
99
+ signal?: AbortSignal;
100
+ }
101
+ /** 请求拦截器 */
102
+ type RequestInterceptor = (config: RequestConfig) => RequestConfig | Promise<RequestConfig>;
103
+ /** 响应拦截器 */
104
+ type ResponseInterceptor = (response: Response) => Response | Promise<Response>;
105
+ /**
106
+ * Token 刷新配置
107
+ */
108
+ interface AuthConfig {
109
+ /** Token 存储适配器(默认 createLocalStorageTokenStorage) */
110
+ storage?: TokenStorage;
111
+ /** Refresh Token 接口路径(相对于 baseUrl) */
112
+ refreshUrl: string;
113
+ /** Token 刷新回调 */
114
+ onTokenRefreshed?: (tokens: TokenPair) => void;
115
+ /** Token 刷新失败回调(通常用于跳转登录页) */
116
+ onRefreshFailed?: () => void;
117
+ }
118
+ /**
119
+ * ApiClient 配置
120
+ */
121
+ interface ApiClientConfig {
122
+ /** API 基础 URL(如 https://api.example.com/api/v1) */
123
+ baseUrl: string;
124
+ /** Token 认证配置(省略则不启用自动 Token 管理) */
125
+ auth?: AuthConfig;
126
+ /** 请求超时(毫秒,默认 30000) */
127
+ timeout?: number;
128
+ /** 拦截器 */
129
+ interceptors?: {
130
+ request?: RequestInterceptor[];
131
+ response?: ResponseInterceptor[];
132
+ };
133
+ /** 自定义 fetch 实现(用于测试或特殊环境) */
134
+ fetch?: typeof globalThis.fetch;
135
+ }
136
+ /**
137
+ * 文件上传选项
138
+ */
139
+ interface UploadOptions {
140
+ /** 文件字段名(默认 'file') */
141
+ fieldName?: string;
142
+ /** 附加表单字段 */
143
+ extraFields?: Record<string, string>;
144
+ }
145
+ /**
146
+ * 流式请求选项
147
+ */
148
+ interface StreamOptions {
149
+ /** 外部取消信号(例如 AbortController.signal) */
150
+ signal?: AbortSignal;
151
+ }
152
+ /**
153
+ * Api Client 实例接口
154
+ *
155
+ * 提供通用 HTTP 方法和契约调用能力。
156
+ */
157
+ interface ApiClient {
158
+ /** GET 请求 */
159
+ get: <T>(path: string, params?: Record<string, unknown>) => Promise<HaiResult<T>>;
160
+ /** POST 请求 */
161
+ post: <T>(path: string, body?: unknown) => Promise<HaiResult<T>>;
162
+ /** PUT 请求 */
163
+ put: <T>(path: string, body?: unknown) => Promise<HaiResult<T>>;
164
+ /** PATCH 请求 */
165
+ patch: <T>(path: string, body?: unknown) => Promise<HaiResult<T>>;
166
+ /** DELETE 请求 */
167
+ delete: <T>(path: string, params?: Record<string, unknown>) => Promise<HaiResult<T>>;
168
+ /** 文件上传 */
169
+ upload: (path: string, file: File | Blob, options?: UploadOptions) => Promise<HaiResult<unknown>>;
170
+ /** 流式请求(返回 AsyncIterable) */
171
+ stream: (path: string, body?: unknown, options?: StreamOptions) => AsyncIterable<string>;
172
+ /**
173
+ * 契约调用(推荐)
174
+ *
175
+ * 基于 EndpointDef 发起请求,路径、方法、入参、出参类型全由契约保证。
176
+ */
177
+ call: <TInput, TOutput>(endpoint: EndpointDef<TInput, TOutput>, input: TInput) => Promise<HaiResult<TOutput>>;
178
+ /** Token 管理 */
179
+ auth: {
180
+ /** 设置 Token */
181
+ setTokens: (tokens: TokenPair) => Promise<void>;
182
+ /** 清空 Token */
183
+ clear: () => Promise<void>;
184
+ /** Token 刷新回调,返回取消订阅函数 */
185
+ onTokenRefreshed: (callback: (tokens: TokenPair) => void) => () => void;
186
+ };
187
+ }
188
+ /**
189
+ * 辅助函数:创建端点定义(获得类型推导)
190
+ *
191
+ * @example
192
+ * ```ts
193
+ * const login = defineEndpoint({
194
+ * method: 'POST',
195
+ * path: '/auth/login',
196
+ * input: LoginInputSchema,
197
+ * output: LoginOutputSchema,
198
+ * requireAuth: false,
199
+ * })
200
+ * ```
201
+ */
202
+ declare function defineEndpoint<TInput, TOutput>(def: EndpointDef<TInput, TOutput>): EndpointDef<TInput, TOutput>;
203
+ /**
204
+ * API 客户端函数接口(单例模式)
205
+ *
206
+ * 统一的 API 客户端访问入口:
207
+ * - `api.init(config)` — 初始化客户端
208
+ * - `api.close()` — 关闭客户端并释放资源
209
+ * - `api.get / post / put / patch / delete` — 通用 HTTP 方法
210
+ * - `api.call(endpoint, input)` — 契约调用
211
+ * - `api.upload(path, file)` — 文件上传
212
+ * - `api.stream(path, body)` — 流式请求
213
+ * - `api.auth` — Token 管理
214
+ * - `api.config` — 当前配置(未初始化时为 null)
215
+ * - `api.isInitialized` — 初始化状态
216
+ */
217
+ interface ApiClientFunctions {
218
+ /**
219
+ * 初始化 API 客户端
220
+ *
221
+ * 已有实例时会先 close 再重新初始化。
222
+ *
223
+ * @param config - 客户端配置
224
+ * @returns 成功 ok(undefined);失败返回 err(含 ApiClientError)
225
+ */
226
+ init: (config: ApiClientConfig) => Promise<HaiResult<void>>;
227
+ /**
228
+ * 关闭 API 客户端并释放资源
229
+ *
230
+ * 重复调用不会报错。
231
+ */
232
+ close: () => Promise<void>;
233
+ /** 当前客户端配置;未初始化或已关闭时为 null */
234
+ readonly config: ApiClientConfig | null;
235
+ /** 是否已完成初始化 */
236
+ readonly isInitialized: boolean;
237
+ /** GET 请求 */
238
+ readonly get: ApiClient['get'];
239
+ /** POST 请求 */
240
+ readonly post: ApiClient['post'];
241
+ /** PUT 请求 */
242
+ readonly put: ApiClient['put'];
243
+ /** PATCH 请求 */
244
+ readonly patch: ApiClient['patch'];
245
+ /** DELETE 请求 */
246
+ readonly delete: ApiClient['delete'];
247
+ /** 文件上传 */
248
+ readonly upload: ApiClient['upload'];
249
+ /**
250
+ * 流式请求(返回 AsyncIterable)
251
+ *
252
+ * @throws 未初始化时抛出异常(async generator 无法返回 HaiResult)
253
+ */
254
+ readonly stream: ApiClient['stream'];
255
+ /** 契约调用(推荐) */
256
+ readonly call: ApiClient['call'];
257
+ /** Token 管理 */
258
+ readonly auth: ApiClient['auth'];
259
+ }
260
+
261
+ /**
262
+ * @h-ai/api-client — Token 存储适配器
263
+ *
264
+ * 提供 localStorage 和内存两种内置 Token 存储实现。
265
+ * @module api-client-auth
266
+ */
267
+
268
+ /**
269
+ * 创建基于 localStorage 的 Token 存储
270
+ *
271
+ * 适用于浏览器端 SPA / PWA。Capacitor 环境建议使用
272
+ * `@h-ai/capacitor` 提供的 `CapacitorTokenStorage`。
273
+ *
274
+ * @returns TokenStorage 实例
275
+ *
276
+ * @example
277
+ * ```ts
278
+ * import { api, createLocalStorageTokenStorage } from '@h-ai/api-client'
279
+ *
280
+ * await api.init({
281
+ * baseUrl: 'https://api.example.com',
282
+ * auth: {
283
+ * storage: createLocalStorageTokenStorage(),
284
+ * refreshUrl: '/auth/refresh',
285
+ * },
286
+ * })
287
+ * ```
288
+ */
289
+ declare function createLocalStorageTokenStorage(): TokenStorage;
290
+ /**
291
+ * 创建内存 Token 存储
292
+ *
293
+ * 适用于 Node.js 测试、SSR 或短生命周期场景。
294
+ * 页面刷新后 Token 丢失。
295
+ *
296
+ * @returns TokenStorage 实例
297
+ *
298
+ * @example
299
+ * ```ts
300
+ * import { api, createMemoryTokenStorage } from '@h-ai/api-client'
301
+ *
302
+ * await api.init({
303
+ * baseUrl: 'https://api.example.com',
304
+ * auth: {
305
+ * storage: createMemoryTokenStorage(),
306
+ * refreshUrl: '/auth/refresh',
307
+ * },
308
+ * })
309
+ * ```
310
+ */
311
+ declare function createMemoryTokenStorage(): TokenStorage;
312
+
313
+ /**
314
+ * @h-ai/api-client — 模块入口
315
+ *
316
+ * 提供统一的 `api` 对象,管理 HTTP 客户端运行时状态与生命周期。
317
+ * @module api-client-main
318
+ */
319
+
320
+ /**
321
+ * API 客户端单例
322
+ *
323
+ * 使用前必须先调用 `api.init()` 初始化,传入 baseUrl 等配置信息。
324
+ * 初始化后通过 `api.get`、`api.post`、`api.call` 等方法发起请求。
325
+ *
326
+ * @example
327
+ * ```ts
328
+ * import { api } from '@h-ai/api-client'
329
+ *
330
+ * // 初始化
331
+ * await api.init({
332
+ * baseUrl: 'https://api.example.com/api/v1',
333
+ * auth: { refreshUrl: '/auth/refresh' },
334
+ * })
335
+ *
336
+ * // 契约调用
337
+ * const result = await api.call(loginEndpoint, { identifier: 'alice', password: 'xxx' })
338
+ *
339
+ * // 通用 HTTP
340
+ * const users = await api.get<User[]>('/users', { page: 1 })
341
+ *
342
+ * // 关闭
343
+ * await api.close()
344
+ * ```
345
+ */
346
+ declare const api: ApiClientFunctions;
347
+
348
+ export { type ApiClient, type ApiClientConfig, type ApiClientFunctions, type AuthConfig, type EndpointDef, HaiApiClientError, type RequestConfig, type RequestInterceptor, type ResponseInterceptor, type StreamOptions, type TokenPair, type TokenStorage, type UploadOptions, api, createLocalStorageTokenStorage, createMemoryTokenStorage, defineEndpoint };