@djvlc/openapi-client-core 1.0.0

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,996 @@
1
+ /**
2
+ * @djvlc/openapi-client-core - 版本信息
3
+ *
4
+ * 版本号在构建时由 tsup 注入,避免手动维护。
5
+ */
6
+ /**
7
+ * SDK 版本号(构建时注入)
8
+ */
9
+ declare const SDK_VERSION: string;
10
+ /**
11
+ * SDK 名称(构建时注入)
12
+ */
13
+ declare const SDK_NAME: string;
14
+ /**
15
+ * 获取 SDK 版本信息
16
+ */
17
+ declare function getSdkInfo(): {
18
+ name: string;
19
+ version: string;
20
+ };
21
+
22
+ /**
23
+ * @djvlc/openapi-client-core - 错误类定义
24
+ *
25
+ * 提供结构化的错误类型,便于调用方区分和处理不同类型的错误。
26
+ *
27
+ * 错误层次:
28
+ * - DjvApiError: 业务层错误(服务器返回的错误响应)
29
+ * - NetworkError: 网络层错误(连接失败、DNS 解析失败等)
30
+ * - TimeoutError: 超时错误(继承自 NetworkError)
31
+ * - AbortError: 请求被取消(继承自 NetworkError)
32
+ */
33
+ /**
34
+ * API 业务错误
35
+ *
36
+ * 当服务器返回非 2xx 响应时抛出,包含完整的错误信息。
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * try {
41
+ * await client.PageApi.resolvePage({ pageUid: 'xxx' });
42
+ * } catch (e) {
43
+ * if (DjvApiError.is(e)) {
44
+ * console.log('业务错误:', e.code, e.message);
45
+ * console.log('追踪ID:', e.traceId);
46
+ *
47
+ * // 使用增强方法
48
+ * if (e.isAuthError()) {
49
+ * redirectToLogin();
50
+ * } else if (e.isRateLimited()) {
51
+ * const retryAfter = e.getRetryAfter();
52
+ * await delay(retryAfter * 1000);
53
+ * }
54
+ * }
55
+ * }
56
+ * ```
57
+ */
58
+ declare class DjvApiError extends Error {
59
+ /** 业务错误码(可能是字符串如 'INVALID_REQUEST' 或数字如 1001) */
60
+ readonly code: string | number;
61
+ /** HTTP 状态码 */
62
+ readonly status: number;
63
+ /** 追踪 ID(用于日志排查) */
64
+ readonly traceId?: string | undefined;
65
+ /** 详细错误信息(字段级错误等) */
66
+ readonly details?: unknown | undefined;
67
+ /** 原始响应对象 */
68
+ readonly response?: Response | undefined;
69
+ /** 标识这是一个 API 错误(用于 instanceof 替代方案) */
70
+ readonly isApiError: true;
71
+ /** 错误名称 */
72
+ readonly name: "DjvApiError";
73
+ constructor(message: string,
74
+ /** 业务错误码(可能是字符串如 'INVALID_REQUEST' 或数字如 1001) */
75
+ code: string | number,
76
+ /** HTTP 状态码 */
77
+ status: number,
78
+ /** 追踪 ID(用于日志排查) */
79
+ traceId?: string | undefined,
80
+ /** 详细错误信息(字段级错误等) */
81
+ details?: unknown | undefined,
82
+ /** 原始响应对象 */
83
+ response?: Response | undefined);
84
+ /**
85
+ * 是否为认证错误 (401 Unauthorized)
86
+ */
87
+ isUnauthorized(): boolean;
88
+ /**
89
+ * 是否为权限错误 (403 Forbidden)
90
+ */
91
+ isForbidden(): boolean;
92
+ /**
93
+ * 是否为认证相关错误 (401 或 403)
94
+ */
95
+ isAuthError(): boolean;
96
+ /**
97
+ * 是否为客户端错误 (4xx)
98
+ */
99
+ isClientError(): boolean;
100
+ /**
101
+ * 是否为服务端错误 (5xx)
102
+ */
103
+ isServerError(): boolean;
104
+ /**
105
+ * 是否为限流错误 (429 Too Many Requests)
106
+ */
107
+ isRateLimited(): boolean;
108
+ /**
109
+ * 是否为资源未找到 (404 Not Found)
110
+ */
111
+ isNotFound(): boolean;
112
+ /**
113
+ * 是否为请求冲突 (409 Conflict)
114
+ */
115
+ isConflict(): boolean;
116
+ /**
117
+ * 是否为请求验证失败 (400 Bad Request 或 422 Unprocessable Entity)
118
+ */
119
+ isValidationError(): boolean;
120
+ /**
121
+ * 获取 Retry-After 头的值(秒)
122
+ *
123
+ * 适用于 429 限流响应和 503 服务不可用响应
124
+ *
125
+ * @returns 重试等待秒数,如果没有 Retry-After 头则返回 null
126
+ */
127
+ getRetryAfter(): number | null;
128
+ /**
129
+ * 获取重试延迟(毫秒)
130
+ *
131
+ * 优先使用 Retry-After 头,否则返回默认值
132
+ *
133
+ * @param defaultMs 默认延迟毫秒数
134
+ */
135
+ getRetryDelayMs(defaultMs?: number): number;
136
+ /**
137
+ * 类型保护:判断是否为 DjvApiError
138
+ */
139
+ static is(error: unknown): error is DjvApiError;
140
+ /**
141
+ * 从响应创建错误
142
+ */
143
+ static fromResponse(response: Response): Promise<DjvApiError>;
144
+ /**
145
+ * 转为 JSON(便于日志记录)
146
+ */
147
+ toJSON(): {
148
+ name: "DjvApiError";
149
+ message: string;
150
+ code: string | number;
151
+ status: number;
152
+ traceId: string | undefined;
153
+ details: unknown;
154
+ };
155
+ }
156
+ /**
157
+ * 网络层错误
158
+ *
159
+ * 当请求无法到达服务器时抛出(连接失败、DNS 解析失败、CORS 等)。
160
+ *
161
+ * @example
162
+ * ```typescript
163
+ * try {
164
+ * await client.PageApi.resolvePage({ pageUid: 'xxx' });
165
+ * } catch (e) {
166
+ * if (NetworkError.is(e)) {
167
+ * console.log('网络错误,请检查网络连接');
168
+ * }
169
+ * }
170
+ * ```
171
+ */
172
+ declare class NetworkError extends Error {
173
+ /** 标识这是一个网络错误 */
174
+ readonly isNetworkError: true;
175
+ /** 错误名称 */
176
+ readonly name: string;
177
+ /** 原始错误 */
178
+ readonly originalCause?: Error;
179
+ constructor(message: string,
180
+ /** 原始错误 */
181
+ cause?: Error);
182
+ /**
183
+ * 获取原始错误
184
+ */
185
+ get cause(): Error | undefined;
186
+ /**
187
+ * 类型保护:判断是否为 NetworkError(包括子类)
188
+ */
189
+ static is(error: unknown): error is NetworkError;
190
+ /**
191
+ * 从原始错误创建
192
+ */
193
+ static fromError(error: unknown): NetworkError | AbortError;
194
+ toJSON(): Record<string, unknown>;
195
+ }
196
+ /**
197
+ * 超时错误
198
+ *
199
+ * 当请求超过指定时间未响应时抛出。
200
+ *
201
+ * @example
202
+ * ```typescript
203
+ * try {
204
+ * await client.PageApi.resolvePage({ pageUid: 'xxx' });
205
+ * } catch (e) {
206
+ * if (TimeoutError.is(e)) {
207
+ * console.log(`请求超时 (${e.timeoutMs}ms),请稍后重试`);
208
+ * }
209
+ * }
210
+ * ```
211
+ */
212
+ declare class TimeoutError extends NetworkError {
213
+ /** 超时时间(毫秒) */
214
+ readonly timeoutMs: number;
215
+ /** 请求 URL */
216
+ readonly url?: string | undefined;
217
+ /** 标识这是一个超时错误 */
218
+ readonly isTimeout: true;
219
+ readonly name: string;
220
+ constructor(
221
+ /** 超时时间(毫秒) */
222
+ timeoutMs: number,
223
+ /** 请求 URL */
224
+ url?: string | undefined);
225
+ /**
226
+ * 类型保护:判断是否为 TimeoutError
227
+ */
228
+ static is(error: unknown): error is TimeoutError;
229
+ toJSON(): Record<string, unknown>;
230
+ }
231
+ /**
232
+ * 请求取消错误
233
+ *
234
+ * 当请求被用户手动取消时抛出。
235
+ *
236
+ * @example
237
+ * ```typescript
238
+ * const controller = new AbortController();
239
+ * setTimeout(() => controller.abort(), 100);
240
+ *
241
+ * try {
242
+ * await client.PageApi.resolvePage({ pageUid: 'xxx' }, { signal: controller.signal });
243
+ * } catch (e) {
244
+ * if (AbortError.is(e)) {
245
+ * console.log('请求已取消');
246
+ * }
247
+ * }
248
+ * ```
249
+ */
250
+ declare class AbortError extends NetworkError {
251
+ /** 标识这是一个取消错误 */
252
+ readonly isAbort: true;
253
+ readonly name: string;
254
+ constructor(message?: string);
255
+ /**
256
+ * 类型保护:判断是否为 AbortError
257
+ */
258
+ static is(error: unknown): error is AbortError;
259
+ }
260
+ /**
261
+ * 判断错误是否可重试
262
+ *
263
+ * 可重试的情况:
264
+ * - 超时错误
265
+ * - 网络错误(非取消)
266
+ * - 特定 HTTP 状态码:408, 429, 500, 502, 503, 504
267
+ */
268
+ declare function isRetryableError(error: unknown): boolean;
269
+ /**
270
+ * 获取错误的推荐重试延迟(毫秒)
271
+ *
272
+ * 优先使用 Retry-After 头,否则返回默认值
273
+ */
274
+ declare function getRetryDelay(error: unknown, defaultMs?: number): number;
275
+
276
+ /**
277
+ * @djvlc/openapi-client-core - 公共类型定义
278
+ */
279
+ /**
280
+ * 请求上下文(Middleware 使用)
281
+ */
282
+ interface RequestContext {
283
+ /** 请求 URL */
284
+ url: string;
285
+ /** 请求初始化配置 */
286
+ init: RequestInit;
287
+ /** 额外元数据 */
288
+ meta?: Record<string, unknown>;
289
+ }
290
+ /**
291
+ * 响应上下文(Middleware 使用)
292
+ */
293
+ interface ResponseContext extends RequestContext {
294
+ /** 响应对象 */
295
+ response: Response;
296
+ /** 请求耗时(毫秒) */
297
+ durationMs: number;
298
+ }
299
+ /**
300
+ * Middleware 定义
301
+ */
302
+ interface Middleware {
303
+ /** 请求前钩子 */
304
+ pre?: (context: RequestContext) => Promise<RequestContext> | RequestContext;
305
+ /** 响应后钩子 */
306
+ post?: (context: ResponseContext) => Promise<void> | void;
307
+ }
308
+ /**
309
+ * 重试配置
310
+ */
311
+ interface RetryOptions {
312
+ /** 最大重试次数(默认 0 不重试) */
313
+ maxRetries?: number;
314
+ /** 重试延迟基数(毫秒,默认 1000) */
315
+ retryDelayMs?: number;
316
+ /** 是否使用指数退避(默认 true) */
317
+ exponentialBackoff?: boolean;
318
+ /** 最大延迟时间(毫秒,默认 30000) */
319
+ maxDelayMs?: number;
320
+ /** 可重试的 HTTP 状态码(默认 [408, 429, 500, 502, 503, 504]) */
321
+ retryableStatuses?: number[];
322
+ /** 自定义重试判断函数 */
323
+ shouldRetry?: (error: unknown, attempt: number) => boolean;
324
+ /** 重试前回调(用于日志等) */
325
+ onRetry?: (error: unknown, attempt: number, delayMs: number) => void;
326
+ /**
327
+ * 是否尊重 Retry-After 响应头
328
+ *
329
+ * 当服务器返回 429 或 503 时,优先使用 Retry-After 头中的延迟时间
330
+ *
331
+ * @default true
332
+ */
333
+ respectRetryAfter?: boolean;
334
+ }
335
+ /**
336
+ * 日志接口
337
+ */
338
+ interface Logger {
339
+ /** 请求日志 */
340
+ request?: (url: string, init: RequestInit) => void;
341
+ /** 响应日志 */
342
+ response?: (url: string, response: Response, durationMs: number) => void;
343
+ /** 错误日志 */
344
+ error?: (url: string, error: unknown) => void;
345
+ /** 重试日志 */
346
+ retry?: (url: string, attempt: number, error: unknown) => void;
347
+ }
348
+ /**
349
+ * 拦截器配置
350
+ */
351
+ interface Interceptors {
352
+ /** 请求拦截器 */
353
+ request?: RequestInterceptor[];
354
+ /** 响应拦截器 */
355
+ response?: ResponseInterceptor[];
356
+ /** 错误拦截器 */
357
+ error?: ErrorInterceptor[];
358
+ }
359
+ /**
360
+ * 请求拦截器
361
+ */
362
+ type RequestInterceptor = (context: RequestContext) => Promise<RequestContext> | RequestContext;
363
+ /**
364
+ * 响应拦截器
365
+ */
366
+ type ResponseInterceptor = (response: Response, context: RequestContext) => Promise<Response> | Response;
367
+ /**
368
+ * 错误拦截器
369
+ */
370
+ type ErrorInterceptor = (error: unknown, context: RequestContext) => Promise<unknown> | unknown;
371
+ /**
372
+ * 基础客户端配置
373
+ */
374
+ interface BaseClientOptions {
375
+ /** 基础 URL */
376
+ baseUrl: string;
377
+ /** 获取认证 Token(Bearer) */
378
+ getAuthToken?: () => string | Promise<string>;
379
+ /** 获取 API Key */
380
+ getApiKey?: () => string | Promise<string>;
381
+ /** 获取追踪头(OpenTelemetry) */
382
+ getTraceHeaders?: () => Record<string, string>;
383
+ /** 默认请求头 */
384
+ defaultHeaders?: Record<string, string>;
385
+ /** 超时时间(毫秒,默认 30000) */
386
+ timeoutMs?: number;
387
+ /** 自定义 fetch 实现 */
388
+ fetchApi?: typeof fetch;
389
+ /** Cookie 策略(默认 'omit') */
390
+ credentials?: RequestCredentials;
391
+ /** 重试配置 */
392
+ retry?: RetryOptions;
393
+ /** 日志配置 */
394
+ logger?: Logger;
395
+ /** 是否开启调试模式 */
396
+ debug?: boolean;
397
+ /** Middleware 列表 */
398
+ middleware?: Middleware[];
399
+ /** 拦截器 */
400
+ interceptors?: Interceptors;
401
+ }
402
+ /**
403
+ * 请求额外配置(每个请求可覆盖)
404
+ */
405
+ interface RequestOptions {
406
+ /** 取消信号 */
407
+ signal?: AbortSignal;
408
+ /** 超时时间(覆盖全局配置) */
409
+ timeoutMs?: number;
410
+ /** 是否跳过重试 */
411
+ skipRetry?: boolean;
412
+ /** 额外请求头 */
413
+ headers?: Record<string, string>;
414
+ }
415
+ /**
416
+ * SDK 版本信息(自动注入)
417
+ */
418
+ interface SdkInfo {
419
+ /** 包名 */
420
+ name: string;
421
+ /** 版本号 */
422
+ version: string;
423
+ /** 平台信息 */
424
+ platform?: string;
425
+ }
426
+ /**
427
+ * Configuration 参数(兼容生成代码)
428
+ */
429
+ interface ConfigurationParameters {
430
+ basePath?: string;
431
+ fetchApi?: typeof fetch;
432
+ middleware?: Middleware[];
433
+ credentials?: RequestCredentials;
434
+ headers?: (() => Promise<Record<string, string>> | Record<string, string>) | Record<string, string>;
435
+ }
436
+
437
+ /**
438
+ * @djvlc/openapi-client-core - 工具函数
439
+ */
440
+ /**
441
+ * 移除 URL 末尾的斜杠
442
+ */
443
+ declare function stripTrailingSlash(url: string): string;
444
+ /**
445
+ * 标准化 Headers
446
+ */
447
+ declare function normalizeHeaders(initHeaders: HeadersInit | undefined): Headers;
448
+ /**
449
+ * 合并多个 Headers
450
+ */
451
+ declare function mergeHeaders(...headersList: (HeadersInit | undefined)[]): Headers;
452
+ /**
453
+ * 延迟指定时间
454
+ */
455
+ declare function delay(ms: number): Promise<void>;
456
+ /**
457
+ * 计算指数退避延迟
458
+ */
459
+ declare function calculateBackoffDelay(attempt: number, baseDelayMs: number, maxDelayMs: number, exponential?: boolean): number;
460
+ /**
461
+ * 获取当前运行平台
462
+ */
463
+ declare function getPlatform(): string;
464
+ /**
465
+ * 生成 SDK User-Agent 字符串
466
+ */
467
+ declare function buildUserAgent(sdkName: string, sdkVersion: string): string;
468
+ /**
469
+ * 判断是否为浏览器环境
470
+ */
471
+ declare function isBrowser(): boolean;
472
+ /**
473
+ * 安全解析 JSON
474
+ */
475
+ declare function safeParseJson<T = unknown>(response: Response): Promise<T | null>;
476
+ /**
477
+ * 克隆响应(用于读取 body 后仍保留原响应)
478
+ */
479
+ declare function cloneResponse(response: Response): Response;
480
+
481
+ /**
482
+ * @djvlc/openapi-client-core - Fetch 增强
483
+ *
484
+ * 提供超时、重试、取消等能力的 fetch 封装。
485
+ */
486
+
487
+ /**
488
+ * 创建带超时的 fetch
489
+ */
490
+ declare function createFetchWithTimeout(fetchImpl: typeof fetch, timeoutMs: number): typeof fetch;
491
+ /**
492
+ * 创建带重试的 fetch
493
+ */
494
+ declare function createFetchWithRetry(fetchImpl: typeof fetch, options?: RetryOptions, logger?: Logger): typeof fetch;
495
+ /**
496
+ * 创建增强版 fetch(组合超时 + 重试 + 日志)
497
+ */
498
+ declare function createEnhancedFetch(options: {
499
+ fetchApi?: typeof fetch;
500
+ timeoutMs?: number;
501
+ retry?: RetryOptions;
502
+ logger?: Logger;
503
+ }): typeof fetch;
504
+ /**
505
+ * 执行请求并处理错误
506
+ *
507
+ * 统一处理响应,非 2xx 响应转换为 DjvApiError
508
+ */
509
+ declare function executeRequest(fetchFn: typeof fetch, url: string, init: RequestInit, options?: RequestOptions): Promise<Response>;
510
+
511
+ /**
512
+ * @djvlc/openapi-client-core - Middleware 系统
513
+ *
514
+ * 提供请求/响应拦截、认证注入、追踪头注入等能力。
515
+ */
516
+
517
+ /**
518
+ * 创建 Headers 注入 Middleware
519
+ *
520
+ * 统一处理:
521
+ * - 默认 Headers
522
+ * - Bearer Token
523
+ * - API Key
524
+ * - Trace Headers
525
+ * - SDK 版本
526
+ */
527
+ declare function createHeadersMiddleware(opts: {
528
+ getAuthToken?: () => string | Promise<string>;
529
+ getApiKey?: () => string | Promise<string>;
530
+ getTraceHeaders?: () => Record<string, string>;
531
+ defaultHeaders?: Record<string, string>;
532
+ sdkInfo?: SdkInfo;
533
+ }): Middleware;
534
+ /**
535
+ * 创建日志 Middleware
536
+ */
537
+ declare function createLoggingMiddleware(opts: {
538
+ onRequest?: (url: string, init: RequestInit) => void;
539
+ onResponse?: (url: string, response: Response, durationMs: number) => void;
540
+ onError?: (url: string, error: unknown) => void;
541
+ }): Middleware;
542
+ /**
543
+ * 应用 Middleware 链
544
+ */
545
+ declare function applyMiddlewareChain(middlewares: Middleware[], context: RequestContext): Promise<RequestContext>;
546
+ /**
547
+ * 应用 post Middleware 链
548
+ */
549
+ declare function applyPostMiddlewareChain(middlewares: Middleware[], context: ResponseContext): Promise<void>;
550
+ /**
551
+ * 从 ClientOptions 创建默认 Middleware 列表
552
+ */
553
+ declare function createDefaultMiddlewares(opts: Pick<BaseClientOptions, 'getAuthToken' | 'getApiKey' | 'getTraceHeaders' | 'defaultHeaders' | 'logger' | 'debug'>, sdkInfo?: SdkInfo): Middleware[];
554
+
555
+ /**
556
+ * @djvlc/openapi-client-core - 拦截器系统
557
+ *
558
+ * 提供更灵活的请求/响应/错误拦截能力。
559
+ */
560
+
561
+ /**
562
+ * 拦截器管理器
563
+ */
564
+ declare class InterceptorManager {
565
+ private requestInterceptors;
566
+ private responseInterceptors;
567
+ private errorInterceptors;
568
+ constructor(interceptors?: Interceptors);
569
+ /**
570
+ * 添加请求拦截器
571
+ * @returns 移除拦截器的函数
572
+ */
573
+ addRequestInterceptor(interceptor: RequestInterceptor): () => void;
574
+ /**
575
+ * 添加响应拦截器
576
+ * @returns 移除拦截器的函数
577
+ */
578
+ addResponseInterceptor(interceptor: ResponseInterceptor): () => void;
579
+ /**
580
+ * 添加错误拦截器
581
+ * @returns 移除拦截器的函数
582
+ */
583
+ addErrorInterceptor(interceptor: ErrorInterceptor): () => void;
584
+ /**
585
+ * 执行请求拦截器链
586
+ */
587
+ runRequestInterceptors(context: RequestContext): Promise<RequestContext>;
588
+ /**
589
+ * 执行响应拦截器链
590
+ */
591
+ runResponseInterceptors(response: Response, context: RequestContext): Promise<Response>;
592
+ /**
593
+ * 执行错误拦截器链
594
+ */
595
+ runErrorInterceptors(error: unknown, context: RequestContext): Promise<unknown>;
596
+ /**
597
+ * 清除所有拦截器
598
+ */
599
+ clear(): void;
600
+ }
601
+ /**
602
+ * 创建 Token 刷新拦截器
603
+ *
604
+ * 当收到 401 错误时自动刷新 token 并重试请求
605
+ */
606
+ declare function createTokenRefreshInterceptor(options: {
607
+ /** 刷新 token 的函数 */
608
+ refreshToken: () => Promise<string>;
609
+ /** 判断是否需要刷新 */
610
+ shouldRefresh?: (response: Response) => boolean;
611
+ /** 最大刷新重试次数 */
612
+ maxRetries?: number;
613
+ }): ResponseInterceptor;
614
+ /**
615
+ * 创建请求去重拦截器
616
+ *
617
+ * 相同请求(URL + Method)在进行中时,复用同一个 Promise
618
+ */
619
+ declare function createDedupeInterceptor(): {
620
+ interceptor: RequestInterceptor;
621
+ clear: () => void;
622
+ };
623
+ /**
624
+ * 创建请求缓存拦截器
625
+ *
626
+ * 缓存 GET 请求的响应
627
+ */
628
+ declare function createCacheInterceptor(options: {
629
+ /** 缓存 TTL(毫秒) */
630
+ ttlMs?: number;
631
+ /** 判断是否应该缓存 */
632
+ shouldCache?: (context: RequestContext) => boolean;
633
+ /** 最大缓存条目数 */
634
+ maxSize?: number;
635
+ }): {
636
+ requestInterceptor: RequestInterceptor;
637
+ responseInterceptor: ResponseInterceptor;
638
+ clear: () => void;
639
+ };
640
+
641
+ /**
642
+ * @djvlc/openapi-client-core - 请求去重
643
+ *
644
+ * 避免相同的 GET 请求并发执行多次,复用进行中的请求。
645
+ */
646
+ /**
647
+ * 请求去重器选项
648
+ */
649
+ interface DedupeOptions {
650
+ /**
651
+ * 生成请求唯一标识的函数
652
+ *
653
+ * 默认使用 `${method}:${url}`
654
+ */
655
+ keyGenerator?: (url: string, init?: RequestInit) => string;
656
+ /**
657
+ * 是否只对 GET 请求去重
658
+ *
659
+ * @default true
660
+ */
661
+ getOnly?: boolean;
662
+ /**
663
+ * 调试日志
664
+ */
665
+ onDedupe?: (key: string, pending: number) => void;
666
+ }
667
+ /**
668
+ * 请求去重器
669
+ *
670
+ * @example
671
+ * ```typescript
672
+ * const deduper = createRequestDeduper();
673
+ *
674
+ * // 包装 fetch
675
+ * const dedupedFetch = deduper.wrap(fetch);
676
+ *
677
+ * // 相同的请求只会执行一次
678
+ * const [r1, r2] = await Promise.all([
679
+ * dedupedFetch('/api/user'),
680
+ * dedupedFetch('/api/user'),
681
+ * ]);
682
+ * ```
683
+ */
684
+ declare function createRequestDeduper(options?: DedupeOptions): {
685
+ /**
686
+ * 包装 fetch 函数,添加请求去重能力
687
+ */
688
+ wrap: (fetchFn: typeof fetch) => typeof fetch;
689
+ /**
690
+ * 获取当前进行中的请求数量
691
+ */
692
+ getPendingCount(): number;
693
+ /**
694
+ * 获取所有进行中的请求 key
695
+ */
696
+ getPendingKeys(): string[];
697
+ /**
698
+ * 清除所有进行中的请求记录
699
+ *
700
+ * 注意:这不会取消请求,只是清除去重映射
701
+ */
702
+ clear(): void;
703
+ };
704
+ /**
705
+ * 请求去重器类型
706
+ */
707
+ type RequestDeduper = ReturnType<typeof createRequestDeduper>;
708
+
709
+ /**
710
+ * @djvlc/openapi-client-core - 指标收集
711
+ *
712
+ * 提供请求级别的指标收集能力,用于可观测性和性能监控。
713
+ */
714
+
715
+ /**
716
+ * 请求指标
717
+ */
718
+ interface RequestMetrics {
719
+ /** 请求 ID(唯一标识) */
720
+ requestId: string;
721
+ /** 请求 URL */
722
+ url: string;
723
+ /** 请求路径(不含 base URL 和 query) */
724
+ path: string;
725
+ /** HTTP 方法 */
726
+ method: string;
727
+ /** 请求开始时间戳(毫秒) */
728
+ startTime: number;
729
+ /** 请求结束时间戳(毫秒) */
730
+ endTime: number;
731
+ /** 请求耗时(毫秒) */
732
+ durationMs: number;
733
+ /** HTTP 状态码 */
734
+ status: number;
735
+ /** 是否成功(2xx) */
736
+ success: boolean;
737
+ /** 是否来自缓存 */
738
+ fromCache?: boolean;
739
+ /** 重试次数 */
740
+ retryCount?: number;
741
+ /** 请求体大小(字节) */
742
+ requestSize?: number;
743
+ /** 响应体大小(字节,如果可获取) */
744
+ responseSize?: number;
745
+ /** 错误信息(如果失败) */
746
+ error?: string;
747
+ /** 追踪 ID */
748
+ traceId?: string;
749
+ }
750
+ /**
751
+ * 指标摘要
752
+ */
753
+ interface MetricsSummary {
754
+ /** 总请求数 */
755
+ totalRequests: number;
756
+ /** 成功请求数 */
757
+ successCount: number;
758
+ /** 失败请求数 */
759
+ failureCount: number;
760
+ /** 成功率 */
761
+ successRate: number;
762
+ /** 平均耗时(毫秒) */
763
+ avgDurationMs: number;
764
+ /** P50 耗时(毫秒) */
765
+ p50Ms: number;
766
+ /** P90 耗时(毫秒) */
767
+ p90Ms: number;
768
+ /** P95 耗时(毫秒) */
769
+ p95Ms: number;
770
+ /** P99 耗时(毫秒) */
771
+ p99Ms: number;
772
+ /** 最小耗时(毫秒) */
773
+ minMs: number;
774
+ /** 最大耗时(毫秒) */
775
+ maxMs: number;
776
+ /** 按状态码分组的计数 */
777
+ statusCodeCounts: Record<number, number>;
778
+ /** 按路径分组的计数 */
779
+ pathCounts: Record<string, number>;
780
+ /** 统计时间范围 */
781
+ timeRange: {
782
+ start: number;
783
+ end: number;
784
+ };
785
+ }
786
+ /**
787
+ * 指标收集器选项
788
+ */
789
+ interface MetricsCollectorOptions {
790
+ /** 最大保留的指标数量(避免内存泄漏) */
791
+ maxMetrics?: number;
792
+ /** 指标 TTL(毫秒,超过此时间的指标会被清理) */
793
+ ttlMs?: number;
794
+ /** 是否自动清理过期指标 */
795
+ autoCleanup?: boolean;
796
+ /** 清理间隔(毫秒) */
797
+ cleanupIntervalMs?: number;
798
+ /** 指标收集回调(每次请求完成时调用) */
799
+ onMetrics?: (metrics: RequestMetrics) => void;
800
+ }
801
+ /**
802
+ * 指标收集器
803
+ */
804
+ interface MetricsCollector {
805
+ /** 收集指标 */
806
+ collect(metrics: RequestMetrics): void;
807
+ /** 获取所有指标 */
808
+ getMetrics(): RequestMetrics[];
809
+ /** 获取并清空所有指标 */
810
+ flush(): RequestMetrics[];
811
+ /** 获取指标摘要 */
812
+ summary(): MetricsSummary;
813
+ /** 按路径获取指标 */
814
+ getByPath(path: string): RequestMetrics[];
815
+ /** 按时间范围获取指标 */
816
+ getByTimeRange(startTime: number, endTime: number): RequestMetrics[];
817
+ /** 清除所有指标 */
818
+ clear(): void;
819
+ /** 销毁收集器(清理定时器等) */
820
+ destroy(): void;
821
+ }
822
+ /**
823
+ * 创建指标收集器
824
+ *
825
+ * @example
826
+ * ```typescript
827
+ * const metrics = createMetricsCollector({
828
+ * maxMetrics: 1000,
829
+ * onMetrics: (m) => console.log(`${m.method} ${m.path} - ${m.durationMs}ms`),
830
+ * });
831
+ *
832
+ * // 使用 middleware 收集指标
833
+ * const client = createClient({
834
+ * middleware: [createMetricsMiddleware(metrics)],
835
+ * });
836
+ *
837
+ * // 获取摘要
838
+ * const summary = metrics.summary();
839
+ * console.log(`成功率: ${(summary.successRate * 100).toFixed(1)}%`);
840
+ * console.log(`P95: ${summary.p95Ms}ms`);
841
+ * ```
842
+ */
843
+ declare function createMetricsCollector(options?: MetricsCollectorOptions): MetricsCollector;
844
+ /**
845
+ * 创建指标收集 Middleware
846
+ *
847
+ * @example
848
+ * ```typescript
849
+ * const metrics = createMetricsCollector();
850
+ * const middleware = createMetricsMiddleware(metrics);
851
+ *
852
+ * const client = createClient({
853
+ * middleware: [middleware],
854
+ * });
855
+ * ```
856
+ */
857
+ declare function createMetricsMiddleware(collector: MetricsCollector): Middleware;
858
+
859
+ /**
860
+ * @djvlc/openapi-client-core - 日志系统
861
+ */
862
+
863
+ /**
864
+ * 创建控制台日志器
865
+ */
866
+ declare function createConsoleLogger(options?: {
867
+ /** 日志前缀 */
868
+ prefix?: string;
869
+ /** 是否启用 */
870
+ enabled?: boolean;
871
+ /** 日志级别:'debug' | 'info' | 'warn' | 'error' */
872
+ level?: 'debug' | 'info' | 'warn' | 'error';
873
+ /** 是否包含时间戳 */
874
+ timestamp?: boolean;
875
+ /** 是否包含请求体 */
876
+ includeBody?: boolean;
877
+ }): Logger;
878
+ /**
879
+ * 创建静默日志器(不输出任何日志)
880
+ */
881
+ declare function createSilentLogger(): Logger;
882
+ /**
883
+ * 创建自定义日志器
884
+ *
885
+ * 将日志发送到自定义目标(如监控系统)
886
+ */
887
+ declare function createCustomLogger(handlers: {
888
+ onRequest?: (data: {
889
+ url: string;
890
+ method: string;
891
+ headers?: Record<string, string>;
892
+ timestamp: number;
893
+ }) => void;
894
+ onResponse?: (data: {
895
+ url: string;
896
+ status: number;
897
+ durationMs: number;
898
+ timestamp: number;
899
+ }) => void;
900
+ onError?: (data: {
901
+ url: string;
902
+ error: unknown;
903
+ timestamp: number;
904
+ }) => void;
905
+ onRetry?: (data: {
906
+ url: string;
907
+ attempt: number;
908
+ error: unknown;
909
+ timestamp: number;
910
+ }) => void;
911
+ }): Logger;
912
+ /**
913
+ * 组合多个日志器
914
+ */
915
+ declare function combineLoggers(...loggers: Logger[]): Logger;
916
+
917
+ /**
918
+ * @djvlc/openapi-client-core - Configuration 类
919
+ *
920
+ * 兼容 openapi-generator 生成的代码,同时提供增强能力。
921
+ */
922
+
923
+ /**
924
+ * API 配置类
925
+ *
926
+ * 兼容 openapi-generator 的 Configuration,同时提供增强能力。
927
+ */
928
+ declare class Configuration {
929
+ /** 基础路径 */
930
+ basePath: string;
931
+ /** fetch 实现 */
932
+ fetchApi: typeof fetch;
933
+ /** Middleware 列表 */
934
+ middleware: Middleware[];
935
+ /** Cookie 策略 */
936
+ credentials?: RequestCredentials;
937
+ /** 拦截器管理器 */
938
+ interceptors: InterceptorManager;
939
+ /** SDK 信息 */
940
+ sdkInfo?: SdkInfo;
941
+ constructor(params?: ConfigurationParameters);
942
+ /**
943
+ * 从 ClientOptions 创建 Configuration
944
+ */
945
+ static fromClientOptions(opts: BaseClientOptions, sdkInfo?: SdkInfo): Configuration;
946
+ }
947
+ /**
948
+ * 创建兼容 openapi-generator 的 Configuration
949
+ *
950
+ * 这个函数用于快速创建一个简单的配置,兼容生成的 API 类。
951
+ */
952
+ declare function createConfiguration(opts: BaseClientOptions, sdkInfo?: SdkInfo): Configuration;
953
+
954
+ /**
955
+ * @djvlc/openapi-client-core - 客户端工厂
956
+ *
957
+ * 提供通用的客户端创建逻辑。
958
+ */
959
+
960
+ /**
961
+ * API 类构造函数类型
962
+ */
963
+ type ApiConstructor<T> = new (configuration: Configuration) => T;
964
+ /**
965
+ * API 类映射
966
+ */
967
+ type ApiMap = Record<string, ApiConstructor<unknown>>;
968
+ /**
969
+ * 从 API 类映射提取实例类型
970
+ */
971
+ type ApiInstances<T extends ApiMap> = {
972
+ [K in keyof T]: InstanceType<T[K]>;
973
+ };
974
+ /**
975
+ * 创建客户端的通用工厂函数
976
+ *
977
+ * @example
978
+ * ```typescript
979
+ * import * as apis from './gen/apis';
980
+ *
981
+ * const client = createClient(apis, {
982
+ * baseUrl: 'https://api.example.com',
983
+ * getAuthToken: () => token,
984
+ * }, { name: '@djvlc/openapi-user-client', version: '1.0.0' });
985
+ * ```
986
+ */
987
+ declare function createClient<T extends ApiMap>(apiClasses: T, opts: BaseClientOptions, sdkInfo?: SdkInfo): {
988
+ config: Configuration;
989
+ apis: ApiInstances<T>;
990
+ } & ApiInstances<T>;
991
+ /**
992
+ * 过滤出 API 类(以 'Api' 结尾的构造函数)
993
+ */
994
+ declare function filterApiClasses<T extends Record<string, unknown>>(exports: T): Record<string, ApiConstructor<unknown>>;
995
+
996
+ export { AbortError, type ApiConstructor, type ApiInstances, type ApiMap, type BaseClientOptions, Configuration, type ConfigurationParameters, type DedupeOptions, DjvApiError, type ErrorInterceptor, InterceptorManager, type Interceptors, type Logger, type MetricsCollector, type MetricsCollectorOptions, type MetricsSummary, type Middleware, NetworkError, type RequestContext, type RequestDeduper, type RequestInterceptor, type RequestMetrics, type RequestOptions, type ResponseContext, type ResponseInterceptor, type RetryOptions, SDK_NAME, SDK_VERSION, type SdkInfo, TimeoutError, applyMiddlewareChain, applyPostMiddlewareChain, buildUserAgent, calculateBackoffDelay, cloneResponse, combineLoggers, createCacheInterceptor, createClient, createConfiguration, createConsoleLogger, createCustomLogger, createDedupeInterceptor, createDefaultMiddlewares, createEnhancedFetch, createFetchWithRetry, createFetchWithTimeout, createHeadersMiddleware, createLoggingMiddleware, createMetricsCollector, createMetricsMiddleware, createRequestDeduper, createSilentLogger, createTokenRefreshInterceptor, delay, executeRequest, filterApiClasses, getPlatform, getRetryDelay, getSdkInfo, isBrowser, isRetryableError, mergeHeaders, normalizeHeaders, safeParseJson, stripTrailingSlash };