@djvlc/openapi-client-core 1.0.0 → 1.1.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.
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/version.ts","../src/errors.ts","../src/utils.ts","../src/fetch.ts","../src/middleware.ts","../src/interceptors.ts","../src/dedupe.ts","../src/metrics.ts","../src/logger.ts","../src/configuration.ts","../src/client-factory.ts"],"sourcesContent":["/**\n * @djvlc/openapi-client-core\n *\n * OpenAPI Client 公共运行时库\n *\n * 提供:\n * - 结构化错误类(DjvApiError, NetworkError, TimeoutError, AbortError)\n * - 增强版 fetch(超时、重试、取消)\n * - Middleware 系统\n * - 拦截器系统\n * - 日志系统\n * - 请求去重\n * - 指标收集\n * - 客户端工厂\n *\n * @example\n * ```typescript\n * import {\n * createClient,\n * DjvApiError,\n * createConsoleLogger,\n * createMetricsCollector,\n * createMetricsMiddleware,\n * } from '@djvlc/openapi-client-core';\n *\n * const metrics = createMetricsCollector();\n *\n * const client = createClient(apis, {\n * baseUrl: 'https://api.example.com',\n * retry: { maxRetries: 2, respectRetryAfter: true },\n * logger: createConsoleLogger(),\n * middleware: [createMetricsMiddleware(metrics)],\n * });\n *\n * try {\n * await client.PageApi.resolvePage({ pageUid: 'xxx' });\n * } catch (e) {\n * if (DjvApiError.is(e)) {\n * console.log('业务错误:', e.code);\n * if (e.isRateLimited()) {\n * console.log('限流,等待:', e.getRetryAfter(), '秒');\n * }\n * }\n * }\n *\n * // 查看指标\n * console.log(metrics.summary());\n * ```\n */\n\n// ============================================================\n// 版本信息\n// ============================================================\nexport { SDK_VERSION, SDK_NAME, getSdkInfo } from './version';\n\n// ============================================================\n// 错误类\n// ============================================================\nexport {\n DjvApiError,\n NetworkError,\n TimeoutError,\n AbortError,\n isRetryableError,\n getRetryDelay,\n} from './errors';\n\n// ============================================================\n// 类型定义\n// ============================================================\nexport type {\n // 核心类型\n BaseClientOptions,\n RequestOptions,\n SdkInfo,\n\n // Middleware\n Middleware,\n RequestContext,\n ResponseContext,\n ConfigurationParameters,\n\n // 拦截器\n Interceptors,\n RequestInterceptor,\n ResponseInterceptor,\n ErrorInterceptor,\n\n // 重试\n RetryOptions,\n\n // 日志\n Logger,\n} from './types';\n\n// ============================================================\n// 工具函数\n// ============================================================\nexport {\n stripTrailingSlash,\n normalizeHeaders,\n mergeHeaders,\n delay,\n calculateBackoffDelay,\n getPlatform,\n buildUserAgent,\n isBrowser,\n safeParseJson,\n cloneResponse,\n} from './utils';\n\n// ============================================================\n// Fetch 增强\n// ============================================================\nexport {\n createFetchWithTimeout,\n createFetchWithRetry,\n createEnhancedFetch,\n executeRequest,\n} from './fetch';\n\n// ============================================================\n// Middleware\n// ============================================================\nexport {\n createHeadersMiddleware,\n createLoggingMiddleware,\n createDefaultMiddlewares,\n applyMiddlewareChain,\n applyPostMiddlewareChain,\n} from './middleware';\n\n// ============================================================\n// 拦截器\n// ============================================================\nexport {\n InterceptorManager,\n createTokenRefreshInterceptor,\n createDedupeInterceptor,\n createCacheInterceptor,\n} from './interceptors';\n\n// ============================================================\n// 请求去重\n// ============================================================\nexport {\n createRequestDeduper,\n type DedupeOptions,\n type RequestDeduper,\n} from './dedupe';\n\n// ============================================================\n// 指标收集\n// ============================================================\nexport {\n createMetricsCollector,\n createMetricsMiddleware,\n type RequestMetrics,\n type MetricsSummary,\n type MetricsCollector,\n type MetricsCollectorOptions,\n} from './metrics';\n\n// ============================================================\n// 日志\n// ============================================================\nexport {\n createConsoleLogger,\n createSilentLogger,\n createCustomLogger,\n combineLoggers,\n} from './logger';\n\n// ============================================================\n// Configuration\n// ============================================================\nexport { Configuration, createConfiguration } from './configuration';\n\n// ============================================================\n// 客户端工厂\n// ============================================================\nexport {\n createClient,\n filterApiClasses,\n type ApiConstructor,\n type ApiMap,\n type ApiInstances,\n} from './client-factory';\n","/**\n * @djvlc/openapi-client-core - 版本信息\n *\n * 版本号在构建时由 tsup 注入,避免手动维护。\n */\n\n// 这些常量在构建时由 tsup define 注入\ndeclare const __SDK_VERSION__: string;\ndeclare const __SDK_NAME__: string;\n\n/**\n * SDK 版本号(构建时注入)\n */\nexport const SDK_VERSION: string =\n typeof __SDK_VERSION__ !== 'undefined' ? __SDK_VERSION__ : '0.0.0-dev';\n\n/**\n * SDK 名称(构建时注入)\n */\nexport const SDK_NAME: string =\n typeof __SDK_NAME__ !== 'undefined' ? __SDK_NAME__ : '@djvlc/openapi-client-core';\n\n/**\n * 获取 SDK 版本信息\n */\nexport function getSdkInfo(): { name: string; version: string } {\n return {\n name: SDK_NAME,\n version: SDK_VERSION,\n };\n}\n","/**\n * @djvlc/openapi-client-core - 错误类定义\n *\n * 提供结构化的错误类型,便于调用方区分和处理不同类型的错误。\n *\n * 错误层次:\n * - DjvApiError: 业务层错误(服务器返回的错误响应)\n * - NetworkError: 网络层错误(连接失败、DNS 解析失败等)\n * - TimeoutError: 超时错误(继承自 NetworkError)\n * - AbortError: 请求被取消(继承自 NetworkError)\n */\n\n/**\n * API 业务错误\n *\n * 当服务器返回非 2xx 响应时抛出,包含完整的错误信息。\n *\n * @example\n * ```typescript\n * try {\n * await client.PageApi.resolvePage({ pageUid: 'xxx' });\n * } catch (e) {\n * if (DjvApiError.is(e)) {\n * console.log('业务错误:', e.code, e.message);\n * console.log('追踪ID:', e.traceId);\n *\n * // 使用增强方法\n * if (e.isAuthError()) {\n * redirectToLogin();\n * } else if (e.isRateLimited()) {\n * const retryAfter = e.getRetryAfter();\n * await delay(retryAfter * 1000);\n * }\n * }\n * }\n * ```\n */\nexport class DjvApiError extends Error {\n /** 标识这是一个 API 错误(用于 instanceof 替代方案) */\n readonly isApiError = true as const;\n\n /** 错误名称 */\n readonly name = 'DjvApiError' as const;\n\n constructor(\n message: string,\n /** 业务错误码(可能是字符串如 'INVALID_REQUEST' 或数字如 1001) */\n public readonly code: string | number,\n /** HTTP 状态码 */\n public readonly status: number,\n /** 追踪 ID(用于日志排查) */\n public readonly traceId?: string,\n /** 详细错误信息(字段级错误等) */\n public readonly details?: unknown,\n /** 原始响应对象 */\n public readonly response?: Response,\n ) {\n super(message);\n // 确保原型链正确(TypeScript 继承 Error 的问题)\n Object.setPrototypeOf(this, DjvApiError.prototype);\n }\n\n // ============================================================\n // 增强方法 - P1 优化\n // ============================================================\n\n /**\n * 是否为认证错误 (401 Unauthorized)\n */\n isUnauthorized(): boolean {\n return this.status === 401;\n }\n\n /**\n * 是否为权限错误 (403 Forbidden)\n */\n isForbidden(): boolean {\n return this.status === 403;\n }\n\n /**\n * 是否为认证相关错误 (401 或 403)\n */\n isAuthError(): boolean {\n return this.status === 401 || this.status === 403;\n }\n\n /**\n * 是否为客户端错误 (4xx)\n */\n isClientError(): boolean {\n return this.status >= 400 && this.status < 500;\n }\n\n /**\n * 是否为服务端错误 (5xx)\n */\n isServerError(): boolean {\n return this.status >= 500;\n }\n\n /**\n * 是否为限流错误 (429 Too Many Requests)\n */\n isRateLimited(): boolean {\n return this.status === 429;\n }\n\n /**\n * 是否为资源未找到 (404 Not Found)\n */\n isNotFound(): boolean {\n return this.status === 404;\n }\n\n /**\n * 是否为请求冲突 (409 Conflict)\n */\n isConflict(): boolean {\n return this.status === 409;\n }\n\n /**\n * 是否为请求验证失败 (400 Bad Request 或 422 Unprocessable Entity)\n */\n isValidationError(): boolean {\n return this.status === 400 || this.status === 422;\n }\n\n /**\n * 获取 Retry-After 头的值(秒)\n *\n * 适用于 429 限流响应和 503 服务不可用响应\n *\n * @returns 重试等待秒数,如果没有 Retry-After 头则返回 null\n */\n getRetryAfter(): number | null {\n const header = this.response?.headers.get('Retry-After');\n if (!header) return null;\n\n // Retry-After 可以是秒数或 HTTP 日期\n const seconds = parseInt(header, 10);\n if (!isNaN(seconds)) {\n return seconds;\n }\n\n // 尝试解析为日期\n const date = Date.parse(header);\n if (!isNaN(date)) {\n return Math.max(0, Math.ceil((date - Date.now()) / 1000));\n }\n\n return null;\n }\n\n /**\n * 获取重试延迟(毫秒)\n *\n * 优先使用 Retry-After 头,否则返回默认值\n *\n * @param defaultMs 默认延迟毫秒数\n */\n getRetryDelayMs(defaultMs = 1000): number {\n const retryAfter = this.getRetryAfter();\n return retryAfter !== null ? retryAfter * 1000 : defaultMs;\n }\n\n // ============================================================\n // 静态方法\n // ============================================================\n\n /**\n * 类型保护:判断是否为 DjvApiError\n */\n static is(error: unknown): error is DjvApiError {\n if (error instanceof DjvApiError) return true;\n if (error == null || typeof error !== 'object') return false;\n return 'isApiError' in error && (error as DjvApiError).isApiError === true;\n }\n\n /**\n * 从响应创建错误\n */\n static async fromResponse(response: Response): Promise<DjvApiError> {\n let body: {\n code?: string | number;\n message?: string;\n traceId?: string;\n requestId?: string;\n details?: unknown;\n } = {};\n\n try {\n body = await response.json();\n } catch {\n // 响应体不是 JSON,忽略\n }\n\n const message = body.message || response.statusText || `HTTP ${response.status}`;\n const code = body.code || response.status;\n const traceId = body.traceId || body.requestId || response.headers.get('x-request-id') || undefined;\n\n return new DjvApiError(message, code, response.status, traceId, body.details, response);\n }\n\n /**\n * 转为 JSON(便于日志记录)\n */\n toJSON() {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n status: this.status,\n traceId: this.traceId,\n details: this.details,\n };\n }\n}\n\n/**\n * 网络层错误\n *\n * 当请求无法到达服务器时抛出(连接失败、DNS 解析失败、CORS 等)。\n *\n * @example\n * ```typescript\n * try {\n * await client.PageApi.resolvePage({ pageUid: 'xxx' });\n * } catch (e) {\n * if (NetworkError.is(e)) {\n * console.log('网络错误,请检查网络连接');\n * }\n * }\n * ```\n */\nexport class NetworkError extends Error {\n /** 标识这是一个网络错误 */\n readonly isNetworkError = true as const;\n\n /** 错误名称 */\n override readonly name: string = 'NetworkError';\n\n /** 原始错误 */\n readonly originalCause?: Error;\n\n constructor(\n message: string,\n /** 原始错误 */\n cause?: Error,\n ) {\n super(message);\n this.originalCause = cause;\n // 尝试设置 cause(ES2022+)\n if (cause && 'cause' in Error.prototype) {\n (this as unknown as { cause?: Error }).cause = cause;\n }\n Object.setPrototypeOf(this, NetworkError.prototype);\n }\n\n /**\n * 获取原始错误\n */\n get cause(): Error | undefined {\n return this.originalCause;\n }\n\n /**\n * 类型保护:判断是否为 NetworkError(包括子类)\n */\n static is(error: unknown): error is NetworkError {\n if (error instanceof NetworkError) return true;\n if (error == null || typeof error !== 'object') return false;\n return 'isNetworkError' in error && (error as NetworkError).isNetworkError === true;\n }\n\n /**\n * 从原始错误创建\n */\n static fromError(error: unknown): NetworkError | AbortError {\n if (error instanceof NetworkError) return error;\n\n const cause = error instanceof Error ? error : undefined;\n const message = error instanceof Error ? error.message : String(error);\n\n // 检查是否为 AbortError\n if (cause?.name === 'AbortError') {\n return new AbortError('Request was aborted');\n }\n\n return new NetworkError(message, cause);\n }\n\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n cause: this.cause?.message,\n };\n }\n}\n\n/**\n * 超时错误\n *\n * 当请求超过指定时间未响应时抛出。\n *\n * @example\n * ```typescript\n * try {\n * await client.PageApi.resolvePage({ pageUid: 'xxx' });\n * } catch (e) {\n * if (TimeoutError.is(e)) {\n * console.log(`请求超时 (${e.timeoutMs}ms),请稍后重试`);\n * }\n * }\n * ```\n */\nexport class TimeoutError extends NetworkError {\n /** 标识这是一个超时错误 */\n readonly isTimeout = true as const;\n\n override readonly name: string = 'TimeoutError';\n\n constructor(\n /** 超时时间(毫秒) */\n public readonly timeoutMs: number,\n /** 请求 URL */\n public readonly url?: string,\n ) {\n super(`Request timeout after ${timeoutMs}ms${url ? `: ${url}` : ''}`);\n Object.setPrototypeOf(this, TimeoutError.prototype);\n }\n\n /**\n * 类型保护:判断是否为 TimeoutError\n */\n static override is(error: unknown): error is TimeoutError {\n if (error instanceof TimeoutError) return true;\n if (error == null || typeof error !== 'object') return false;\n return 'isTimeout' in error && (error as TimeoutError).isTimeout === true;\n }\n\n override toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n timeoutMs: this.timeoutMs,\n url: this.url,\n };\n }\n}\n\n/**\n * 请求取消错误\n *\n * 当请求被用户手动取消时抛出。\n *\n * @example\n * ```typescript\n * const controller = new AbortController();\n * setTimeout(() => controller.abort(), 100);\n *\n * try {\n * await client.PageApi.resolvePage({ pageUid: 'xxx' }, { signal: controller.signal });\n * } catch (e) {\n * if (AbortError.is(e)) {\n * console.log('请求已取消');\n * }\n * }\n * ```\n */\nexport class AbortError extends NetworkError {\n /** 标识这是一个取消错误 */\n readonly isAbort = true as const;\n\n override readonly name: string = 'AbortError';\n\n constructor(message = 'Request was aborted') {\n super(message);\n Object.setPrototypeOf(this, AbortError.prototype);\n }\n\n /**\n * 类型保护:判断是否为 AbortError\n */\n static override is(error: unknown): error is AbortError {\n if (error instanceof AbortError) return true;\n if (error == null || typeof error !== 'object') return false;\n return 'isAbort' in error && (error as AbortError).isAbort === true;\n }\n}\n\n/**\n * 判断错误是否可重试\n *\n * 可重试的情况:\n * - 超时错误\n * - 网络错误(非取消)\n * - 特定 HTTP 状态码:408, 429, 500, 502, 503, 504\n */\nexport function isRetryableError(error: unknown): boolean {\n // 取消请求不应重试\n if (AbortError.is(error)) return false;\n\n // 超时和网络错误可重试\n if (TimeoutError.is(error) || NetworkError.is(error)) return true;\n\n // API 错误根据状态码判断\n if (DjvApiError.is(error)) {\n const retryableStatuses = [408, 429, 500, 502, 503, 504];\n return retryableStatuses.includes(error.status);\n }\n\n return false;\n}\n\n/**\n * 获取错误的推荐重试延迟(毫秒)\n *\n * 优先使用 Retry-After 头,否则返回默认值\n */\nexport function getRetryDelay(error: unknown, defaultMs = 1000): number {\n if (DjvApiError.is(error)) {\n return error.getRetryDelayMs(defaultMs);\n }\n return defaultMs;\n}\n","/**\n * @djvlc/openapi-client-core - 工具函数\n */\n\n/**\n * 移除 URL 末尾的斜杠\n */\nexport function stripTrailingSlash(url: string): string {\n return url.replace(/\\/$/, '');\n}\n\n/**\n * 标准化 Headers\n */\nexport function normalizeHeaders(initHeaders: HeadersInit | undefined): Headers {\n return new Headers(initHeaders ?? {});\n}\n\n/**\n * 合并多个 Headers\n */\nexport function mergeHeaders(...headersList: (HeadersInit | undefined)[]): Headers {\n const result = new Headers();\n\n for (const headers of headersList) {\n if (!headers) continue;\n\n const normalized = new Headers(headers);\n normalized.forEach((value, key) => {\n result.set(key, value);\n });\n }\n\n return result;\n}\n\n/**\n * 延迟指定时间\n */\nexport function delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * 计算指数退避延迟\n */\nexport function calculateBackoffDelay(\n attempt: number,\n baseDelayMs: number,\n maxDelayMs: number,\n exponential = true\n): number {\n if (!exponential) return baseDelayMs;\n\n // 指数退避 + 随机抖动\n const exponentialDelay = baseDelayMs * Math.pow(2, attempt - 1);\n const jitter = Math.random() * 0.3 * exponentialDelay; // 30% 抖动\n const delayWithJitter = exponentialDelay + jitter;\n\n return Math.min(delayWithJitter, maxDelayMs);\n}\n\n/**\n * 获取当前运行平台\n */\nexport function getPlatform(): string {\n // Node.js\n if (typeof process !== 'undefined' && process.versions?.node) {\n return `node/${process.versions.node}`;\n }\n\n // Deno\n if (typeof Deno !== 'undefined') {\n return `deno/${Deno.version?.deno ?? 'unknown'}`;\n }\n\n // Browser\n if (typeof navigator !== 'undefined') {\n const ua = navigator.userAgent;\n if (ua.includes('Chrome')) return 'chrome';\n if (ua.includes('Firefox')) return 'firefox';\n if (ua.includes('Safari')) return 'safari';\n if (ua.includes('Edge')) return 'edge';\n return 'browser';\n }\n\n return 'unknown';\n}\n\n/**\n * 生成 SDK User-Agent 字符串\n */\nexport function buildUserAgent(sdkName: string, sdkVersion: string): string {\n const platform = getPlatform();\n return `${sdkName}/${sdkVersion} (${platform})`;\n}\n\n/**\n * 判断是否为浏览器环境\n */\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * 安全解析 JSON\n */\nexport async function safeParseJson<T = unknown>(response: Response): Promise<T | null> {\n try {\n return await response.json() as T;\n } catch {\n return null;\n }\n}\n\n/**\n * 克隆响应(用于读取 body 后仍保留原响应)\n */\nexport function cloneResponse(response: Response): Response {\n return response.clone();\n}\n\n// Deno 类型声明(避免 TypeScript 报错)\ndeclare const Deno: {\n version?: {\n deno?: string;\n };\n} | undefined;\n","/**\n * @djvlc/openapi-client-core - Fetch 增强\n *\n * 提供超时、重试、取消等能力的 fetch 封装。\n */\n\nimport { DjvApiError, NetworkError, TimeoutError, AbortError, isRetryableError } from './errors';\nimport type { RetryOptions, Logger, RequestOptions } from './types';\nimport { delay, calculateBackoffDelay } from './utils';\n\n/**\n * 默认重试配置\n */\nconst DEFAULT_RETRY_OPTIONS: Required<RetryOptions> = {\n maxRetries: 0,\n retryDelayMs: 1000,\n exponentialBackoff: true,\n maxDelayMs: 30000,\n retryableStatuses: [408, 429, 500, 502, 503, 504],\n shouldRetry: () => true,\n onRetry: () => {},\n respectRetryAfter: true, // P1: 默认尊重 Retry-After 头\n};\n\n/**\n * 创建带超时的 fetch\n */\nexport function createFetchWithTimeout(\n fetchImpl: typeof fetch,\n timeoutMs: number\n): typeof fetch {\n return (async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n // 合并外部 signal\n const externalSignal = init?.signal;\n if (externalSignal) {\n if (externalSignal.aborted) {\n clearTimeout(timeoutId);\n throw new AbortError('Request was aborted');\n }\n externalSignal.addEventListener('abort', () => {\n clearTimeout(timeoutId);\n controller.abort();\n });\n }\n\n try {\n const response = await fetchImpl(input, {\n ...init,\n signal: controller.signal,\n });\n return response;\n } catch (error) {\n // 区分超时和手动取消\n if (error instanceof Error && error.name === 'AbortError') {\n const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;\n if (externalSignal?.aborted) {\n throw new AbortError('Request was aborted');\n }\n throw new TimeoutError(timeoutMs, url);\n }\n throw NetworkError.fromError(error);\n } finally {\n clearTimeout(timeoutId);\n }\n }) as typeof fetch;\n}\n\n/**\n * 从响应或错误中获取重试延迟\n *\n * P1: 支持 Retry-After 头\n */\nfunction getRetryDelayFromResponse(\n response: Response | null,\n error: unknown,\n attempt: number,\n opts: Required<RetryOptions>\n): number {\n // 1. 优先使用 Retry-After 头(如果启用)\n if (opts.respectRetryAfter && response) {\n const retryAfter = response.headers.get('Retry-After');\n if (retryAfter) {\n // Retry-After 可以是秒数\n const seconds = parseInt(retryAfter, 10);\n if (!isNaN(seconds)) {\n return Math.min(seconds * 1000, opts.maxDelayMs);\n }\n \n // 或者是 HTTP 日期\n const date = Date.parse(retryAfter);\n if (!isNaN(date)) {\n const delayMs = Math.max(0, date - Date.now());\n return Math.min(delayMs, opts.maxDelayMs);\n }\n }\n }\n\n // 2. 使用错误类中的 getRetryDelayMs 方法\n if (DjvApiError.is(error)) {\n const errorDelay = error.getRetryDelayMs(0);\n if (errorDelay > 0) {\n return Math.min(errorDelay, opts.maxDelayMs);\n }\n }\n\n // 3. 使用计算的退避延迟\n return calculateBackoffDelay(\n attempt,\n opts.retryDelayMs,\n opts.maxDelayMs,\n opts.exponentialBackoff\n );\n}\n\n/**\n * 创建带重试的 fetch\n */\nexport function createFetchWithRetry(\n fetchImpl: typeof fetch,\n options: RetryOptions = {},\n logger?: Logger\n): typeof fetch {\n const opts = { ...DEFAULT_RETRY_OPTIONS, ...options };\n\n return (async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;\n let lastError: unknown;\n let lastResponse: Response | null = null;\n\n for (let attempt = 0; attempt <= opts.maxRetries; attempt++) {\n try {\n const response = await fetchImpl(input, init);\n lastResponse = response;\n\n // 检查是否需要重试(基于状态码)\n if (!response.ok && attempt < opts.maxRetries) {\n if (opts.retryableStatuses.includes(response.status)) {\n const error = await DjvApiError.fromResponse(response.clone());\n\n if (opts.shouldRetry(error, attempt + 1)) {\n // P1: 使用增强的重试延迟计算\n const delayMs = getRetryDelayFromResponse(\n response,\n error,\n attempt + 1,\n opts\n );\n\n opts.onRetry(error, attempt + 1, delayMs);\n logger?.retry?.(url, attempt + 1, error);\n\n await delay(delayMs);\n continue;\n }\n }\n }\n\n return response;\n } catch (error) {\n lastError = error;\n\n // 取消请求不重试\n if (AbortError.is(error)) {\n throw error;\n }\n\n // 最后一次尝试直接抛出\n if (attempt >= opts.maxRetries) {\n throw error;\n }\n\n // 判断是否可重试\n if (!isRetryableError(error) || !opts.shouldRetry(error, attempt + 1)) {\n throw error;\n }\n\n // P1: 使用增强的重试延迟计算\n const delayMs = getRetryDelayFromResponse(\n lastResponse,\n error,\n attempt + 1,\n opts\n );\n\n opts.onRetry(error, attempt + 1, delayMs);\n logger?.retry?.(url, attempt + 1, error);\n\n await delay(delayMs);\n }\n }\n\n // 不应该到达这里,但为了类型安全\n throw lastError;\n }) as typeof fetch;\n}\n\n/**\n * 创建增强版 fetch(组合超时 + 重试 + 日志)\n */\nexport function createEnhancedFetch(options: {\n fetchApi?: typeof fetch;\n timeoutMs?: number;\n retry?: RetryOptions;\n logger?: Logger;\n}): typeof fetch {\n const {\n fetchApi = fetch,\n timeoutMs = 30000,\n retry,\n logger,\n } = options;\n\n // 层层包装\n let enhancedFetch = fetchApi;\n\n // 1. 超时\n enhancedFetch = createFetchWithTimeout(enhancedFetch, timeoutMs);\n\n // 2. 重试\n if (retry && retry.maxRetries && retry.maxRetries > 0) {\n enhancedFetch = createFetchWithRetry(enhancedFetch, retry, logger);\n }\n\n // 3. 日志包装\n if (logger) {\n const wrappedFetch = enhancedFetch;\n enhancedFetch = (async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;\n const startTime = Date.now();\n\n logger.request?.(url, init ?? {});\n\n try {\n const response = await wrappedFetch(input, init);\n const durationMs = Date.now() - startTime;\n logger.response?.(url, response, durationMs);\n return response;\n } catch (error) {\n logger.error?.(url, error);\n throw error;\n }\n }) as typeof fetch;\n }\n\n return enhancedFetch;\n}\n\n/**\n * 执行请求并处理错误\n *\n * 统一处理响应,非 2xx 响应转换为 DjvApiError\n */\nexport async function executeRequest(\n fetchFn: typeof fetch,\n url: string,\n init: RequestInit,\n options?: RequestOptions\n): Promise<Response> {\n // 处理请求级别的 signal 和 timeout\n const finalInit = { ...init };\n let timeoutController: AbortController | undefined;\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n if (options?.timeoutMs) {\n timeoutController = new AbortController();\n timeoutId = setTimeout(() => timeoutController!.abort(), options.timeoutMs);\n\n // 合并 signal\n if (options.signal) {\n options.signal.addEventListener('abort', () => {\n clearTimeout(timeoutId);\n timeoutController!.abort();\n });\n }\n\n finalInit.signal = timeoutController.signal;\n } else if (options?.signal) {\n finalInit.signal = options.signal;\n }\n\n try {\n const response = await fetchFn(url, finalInit);\n\n // 非 2xx 响应转为错误\n if (!response.ok) {\n throw await DjvApiError.fromResponse(response);\n }\n\n return response;\n } catch (error) {\n // 已经是我们的错误类型,直接抛出\n if (DjvApiError.is(error) || NetworkError.is(error)) {\n throw error;\n }\n\n // AbortError 特殊处理\n if (error instanceof Error && error.name === 'AbortError') {\n if (options?.signal?.aborted) {\n throw new AbortError('Request was aborted');\n }\n if (options?.timeoutMs) {\n throw new TimeoutError(options.timeoutMs, url);\n }\n throw new AbortError();\n }\n\n // 其他错误包装为 NetworkError\n throw NetworkError.fromError(error);\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n}\n","/**\n * @djvlc/openapi-client-core - Middleware 系统\n *\n * 提供请求/响应拦截、认证注入、追踪头注入等能力。\n */\n\nimport type {\n Middleware,\n RequestContext,\n ResponseContext,\n SdkInfo,\n BaseClientOptions,\n} from './types';\nimport { normalizeHeaders, buildUserAgent } from './utils';\n\n/**\n * 创建 Headers 注入 Middleware\n *\n * 统一处理:\n * - 默认 Headers\n * - Bearer Token\n * - API Key\n * - Trace Headers\n * - SDK 版本\n */\nexport function createHeadersMiddleware(opts: {\n getAuthToken?: () => string | Promise<string>;\n getApiKey?: () => string | Promise<string>;\n getTraceHeaders?: () => Record<string, string>;\n defaultHeaders?: Record<string, string>;\n sdkInfo?: SdkInfo;\n}): Middleware {\n return {\n async pre(context: RequestContext): Promise<RequestContext> {\n const headers = normalizeHeaders(context.init.headers);\n\n // 1. 默认 Headers\n if (opts.defaultHeaders) {\n for (const [key, value] of Object.entries(opts.defaultHeaders)) {\n headers.set(key, value);\n }\n }\n\n // 2. API Key(如果提供)\n if (opts.getApiKey) {\n const apiKey = await opts.getApiKey();\n if (apiKey) {\n headers.set('X-Api-Key', apiKey);\n }\n }\n\n // 3. Bearer Token(如果提供)\n if (opts.getAuthToken) {\n const token = await opts.getAuthToken();\n if (token) {\n headers.set('Authorization', `Bearer ${token}`);\n }\n }\n\n // 4. Trace Headers(OpenTelemetry)\n if (opts.getTraceHeaders) {\n const traceHeaders = opts.getTraceHeaders();\n for (const [key, value] of Object.entries(traceHeaders)) {\n headers.set(key, value);\n }\n }\n\n // 5. SDK 版本信息\n if (opts.sdkInfo) {\n headers.set('X-SDK-Version', `${opts.sdkInfo.name}@${opts.sdkInfo.version}`);\n headers.set('User-Agent', buildUserAgent(opts.sdkInfo.name, opts.sdkInfo.version));\n }\n\n return {\n ...context,\n init: {\n ...context.init,\n headers,\n },\n };\n },\n };\n}\n\n/**\n * 创建日志 Middleware\n */\nexport function createLoggingMiddleware(opts: {\n onRequest?: (url: string, init: RequestInit) => void;\n onResponse?: (url: string, response: Response, durationMs: number) => void;\n onError?: (url: string, error: unknown) => void;\n}): Middleware {\n const requestStartTimes = new Map<string, number>();\n\n return {\n pre(context: RequestContext): RequestContext {\n const requestId = `${context.url}-${Date.now()}`;\n requestStartTimes.set(requestId, Date.now());\n context.meta = { ...context.meta, requestId };\n\n opts.onRequest?.(context.url, context.init);\n return context;\n },\n post(context: ResponseContext): void {\n const requestId = context.meta?.requestId as string;\n const startTime = requestStartTimes.get(requestId);\n const durationMs = startTime ? Date.now() - startTime : 0;\n\n requestStartTimes.delete(requestId);\n opts.onResponse?.(context.url, context.response, durationMs);\n },\n };\n}\n\n/**\n * 应用 Middleware 链\n */\nexport async function applyMiddlewareChain(\n middlewares: Middleware[],\n context: RequestContext\n): Promise<RequestContext> {\n let currentContext = context;\n\n for (const middleware of middlewares) {\n if (middleware.pre) {\n currentContext = await middleware.pre(currentContext);\n }\n }\n\n return currentContext;\n}\n\n/**\n * 应用 post Middleware 链\n */\nexport async function applyPostMiddlewareChain(\n middlewares: Middleware[],\n context: ResponseContext\n): Promise<void> {\n // 倒序执行 post hooks\n for (let i = middlewares.length - 1; i >= 0; i--) {\n const middleware = middlewares[i];\n if (middleware.post) {\n await middleware.post(context);\n }\n }\n}\n\n/**\n * 从 ClientOptions 创建默认 Middleware 列表\n */\nexport function createDefaultMiddlewares(\n opts: Pick<\n BaseClientOptions,\n 'getAuthToken' | 'getApiKey' | 'getTraceHeaders' | 'defaultHeaders' | 'logger' | 'debug'\n >,\n sdkInfo?: SdkInfo\n): Middleware[] {\n const middlewares: Middleware[] = [];\n\n // Headers 注入\n middlewares.push(\n createHeadersMiddleware({\n getAuthToken: opts.getAuthToken,\n getApiKey: opts.getApiKey,\n getTraceHeaders: opts.getTraceHeaders,\n defaultHeaders: opts.defaultHeaders,\n sdkInfo,\n })\n );\n\n // 日志(调试模式或有 logger)\n if (opts.debug || opts.logger) {\n middlewares.push(\n createLoggingMiddleware({\n onRequest: (url, init) => {\n if (opts.debug) {\n console.log(`[API] -> ${init.method ?? 'GET'} ${url}`);\n }\n opts.logger?.request?.(url, init);\n },\n onResponse: (url, response, durationMs) => {\n if (opts.debug) {\n console.log(`[API] <- ${response.status} ${url} (${durationMs}ms)`);\n }\n opts.logger?.response?.(url, response, durationMs);\n },\n onError: (url, error) => {\n if (opts.debug) {\n console.error(`[API] !! ${url}`, error);\n }\n opts.logger?.error?.(url, error);\n },\n })\n );\n }\n\n // 合并用户自定义 Middleware\n // 注意:用户 middleware 在最后执行,可以覆盖默认行为\n\n return middlewares;\n}\n","/**\n * @djvlc/openapi-client-core - 拦截器系统\n *\n * 提供更灵活的请求/响应/错误拦截能力。\n */\n\nimport type {\n Interceptors,\n RequestInterceptor,\n ResponseInterceptor,\n ErrorInterceptor,\n RequestContext,\n} from './types';\n\n/**\n * 拦截器管理器\n */\nexport class InterceptorManager {\n private requestInterceptors: RequestInterceptor[] = [];\n private responseInterceptors: ResponseInterceptor[] = [];\n private errorInterceptors: ErrorInterceptor[] = [];\n\n constructor(interceptors?: Interceptors) {\n if (interceptors?.request) {\n this.requestInterceptors.push(...interceptors.request);\n }\n if (interceptors?.response) {\n this.responseInterceptors.push(...interceptors.response);\n }\n if (interceptors?.error) {\n this.errorInterceptors.push(...interceptors.error);\n }\n }\n\n /**\n * 添加请求拦截器\n * @returns 移除拦截器的函数\n */\n addRequestInterceptor(interceptor: RequestInterceptor): () => void {\n this.requestInterceptors.push(interceptor);\n return () => {\n const index = this.requestInterceptors.indexOf(interceptor);\n if (index >= 0) {\n this.requestInterceptors.splice(index, 1);\n }\n };\n }\n\n /**\n * 添加响应拦截器\n * @returns 移除拦截器的函数\n */\n addResponseInterceptor(interceptor: ResponseInterceptor): () => void {\n this.responseInterceptors.push(interceptor);\n return () => {\n const index = this.responseInterceptors.indexOf(interceptor);\n if (index >= 0) {\n this.responseInterceptors.splice(index, 1);\n }\n };\n }\n\n /**\n * 添加错误拦截器\n * @returns 移除拦截器的函数\n */\n addErrorInterceptor(interceptor: ErrorInterceptor): () => void {\n this.errorInterceptors.push(interceptor);\n return () => {\n const index = this.errorInterceptors.indexOf(interceptor);\n if (index >= 0) {\n this.errorInterceptors.splice(index, 1);\n }\n };\n }\n\n /**\n * 执行请求拦截器链\n */\n async runRequestInterceptors(context: RequestContext): Promise<RequestContext> {\n let currentContext = context;\n\n for (const interceptor of this.requestInterceptors) {\n currentContext = await interceptor(currentContext);\n }\n\n return currentContext;\n }\n\n /**\n * 执行响应拦截器链\n */\n async runResponseInterceptors(response: Response, context: RequestContext): Promise<Response> {\n let currentResponse = response;\n\n for (const interceptor of this.responseInterceptors) {\n currentResponse = await interceptor(currentResponse, context);\n }\n\n return currentResponse;\n }\n\n /**\n * 执行错误拦截器链\n */\n async runErrorInterceptors(error: unknown, context: RequestContext): Promise<unknown> {\n let currentError = error;\n\n for (const interceptor of this.errorInterceptors) {\n try {\n // 错误拦截器可以:\n // 1. 抛出新错误\n // 2. 返回原错误(继续传递)\n // 3. 返回 Response(恢复请求)\n currentError = await interceptor(currentError, context);\n } catch (e) {\n currentError = e;\n }\n }\n\n return currentError;\n }\n\n /**\n * 清除所有拦截器\n */\n clear(): void {\n this.requestInterceptors = [];\n this.responseInterceptors = [];\n this.errorInterceptors = [];\n }\n}\n\n/**\n * 创建 Token 刷新拦截器\n *\n * 当收到 401 错误时自动刷新 token 并重试请求\n */\nexport function createTokenRefreshInterceptor(options: {\n /** 刷新 token 的函数 */\n refreshToken: () => Promise<string>;\n /** 判断是否需要刷新 */\n shouldRefresh?: (response: Response) => boolean;\n /** 最大刷新重试次数 */\n maxRetries?: number;\n}): ResponseInterceptor {\n const {\n refreshToken,\n shouldRefresh = (response) => response.status === 401,\n maxRetries = 1,\n } = options;\n\n let refreshPromise: Promise<string> | null = null;\n let retryCount = 0;\n\n return async (response, context) => {\n if (!shouldRefresh(response) || retryCount >= maxRetries) {\n retryCount = 0;\n return response;\n }\n\n retryCount++;\n\n // 避免并发刷新\n if (!refreshPromise) {\n refreshPromise = refreshToken().finally(() => {\n refreshPromise = null;\n });\n }\n\n try {\n const newToken = await refreshPromise;\n\n // 用新 token 重试请求\n const headers = new Headers(context.init.headers);\n headers.set('Authorization', `Bearer ${newToken}`);\n\n const newResponse = await fetch(context.url, {\n ...context.init,\n headers,\n });\n\n retryCount = 0;\n return newResponse;\n } catch {\n retryCount = 0;\n return response;\n }\n };\n}\n\n/**\n * 创建请求去重拦截器\n *\n * 相同请求(URL + Method)在进行中时,复用同一个 Promise\n */\nexport function createDedupeInterceptor(): {\n interceptor: RequestInterceptor;\n clear: () => void;\n} {\n const pendingRequests = new Map<string, Promise<RequestContext>>();\n\n const getKey = (context: RequestContext): string => {\n return `${context.init.method ?? 'GET'}:${context.url}`;\n };\n\n return {\n interceptor: (context) => {\n const key = getKey(context);\n const pending = pendingRequests.get(key);\n\n if (pending) {\n // 复用进行中的请求\n return pending;\n }\n\n // 标记请求进行中(实际不做去重,只是示例)\n // 真正的去重需要在 fetch 层面实现\n return context;\n },\n clear: () => {\n pendingRequests.clear();\n },\n };\n}\n\n/**\n * 创建请求缓存拦截器\n *\n * 缓存 GET 请求的响应\n */\nexport function createCacheInterceptor(options: {\n /** 缓存 TTL(毫秒) */\n ttlMs?: number;\n /** 判断是否应该缓存 */\n shouldCache?: (context: RequestContext) => boolean;\n /** 最大缓存条目数 */\n maxSize?: number;\n}): {\n requestInterceptor: RequestInterceptor;\n responseInterceptor: ResponseInterceptor;\n clear: () => void;\n} {\n const {\n ttlMs = 60000,\n shouldCache = (context) => context.init.method === 'GET' || !context.init.method,\n maxSize = 100,\n } = options;\n\n interface CacheEntry {\n response: Response;\n timestamp: number;\n }\n\n const cache = new Map<string, CacheEntry>();\n\n const getKey = (context: RequestContext): string => {\n return `${context.init.method ?? 'GET'}:${context.url}`;\n };\n\n const isExpired = (entry: CacheEntry): boolean => {\n return Date.now() - entry.timestamp > ttlMs;\n };\n\n const evictOldest = (): void => {\n if (cache.size >= maxSize) {\n const oldestKey = cache.keys().next().value;\n if (oldestKey) {\n cache.delete(oldestKey);\n }\n }\n };\n\n return {\n requestInterceptor: (context) => {\n if (!shouldCache(context)) {\n return context;\n }\n\n const key = getKey(context);\n const entry = cache.get(key);\n\n if (entry && !isExpired(entry)) {\n // 标记使用缓存(实际需要特殊处理)\n context.meta = { ...context.meta, fromCache: true, cachedResponse: entry.response.clone() };\n }\n\n return context;\n },\n responseInterceptor: (response, context) => {\n if (!shouldCache(context) || !response.ok) {\n return response;\n }\n\n const key = getKey(context);\n evictOldest();\n cache.set(key, {\n response: response.clone(),\n timestamp: Date.now(),\n });\n\n return response;\n },\n clear: () => {\n cache.clear();\n },\n };\n}\n","/**\n * @djvlc/openapi-client-core - 请求去重\n *\n * 避免相同的 GET 请求并发执行多次,复用进行中的请求。\n */\n\n/**\n * 请求去重器选项\n */\nexport interface DedupeOptions {\n /**\n * 生成请求唯一标识的函数\n *\n * 默认使用 `${method}:${url}`\n */\n keyGenerator?: (url: string, init?: RequestInit) => string;\n\n /**\n * 是否只对 GET 请求去重\n *\n * @default true\n */\n getOnly?: boolean;\n\n /**\n * 调试日志\n */\n onDedupe?: (key: string, pending: number) => void;\n}\n\n/**\n * 请求去重器\n *\n * @example\n * ```typescript\n * const deduper = createRequestDeduper();\n *\n * // 包装 fetch\n * const dedupedFetch = deduper.wrap(fetch);\n *\n * // 相同的请求只会执行一次\n * const [r1, r2] = await Promise.all([\n * dedupedFetch('/api/user'),\n * dedupedFetch('/api/user'),\n * ]);\n * ```\n */\nexport function createRequestDeduper(options: DedupeOptions = {}) {\n const {\n keyGenerator = defaultKeyGenerator,\n getOnly = true,\n onDedupe,\n } = options;\n\n // 进行中的请求映射\n const inflightRequests = new Map<string, Promise<Response>>();\n\n // 每个请求的等待者数量\n const pendingCounts = new Map<string, number>();\n\n function defaultKeyGenerator(url: string, init?: RequestInit): string {\n const method = (init?.method ?? 'GET').toUpperCase();\n\n // 非幂等请求不去重\n if (getOnly && method !== 'GET') {\n return `${method}:${url}:${Date.now()}:${Math.random()}`;\n }\n\n return `${method}:${url}`;\n }\n\n return {\n /**\n * 包装 fetch 函数,添加请求去重能力\n */\n wrap: (fetchFn: typeof fetch): typeof fetch => {\n return (async (\n input: RequestInfo | URL,\n init?: RequestInit\n ): Promise<Response> => {\n const url = typeof input === 'string'\n ? input\n : input instanceof URL\n ? input.href\n : input.url;\n\n const key = keyGenerator(url, init);\n\n // 检查是否有相同请求在进行中\n const inflight = inflightRequests.get(key);\n if (inflight) {\n // 增加等待者计数\n pendingCounts.set(key, (pendingCounts.get(key) ?? 1) + 1);\n onDedupe?.(key, pendingCounts.get(key)!);\n\n // 复用进行中的请求,返回克隆的响应\n return inflight.then((response) => response.clone());\n }\n\n // 发起新请求\n const promise = fetchFn(input, init)\n .then((response) => {\n // 保存响应供后续克隆\n return response;\n })\n .finally(() => {\n // 请求完成后清理\n inflightRequests.delete(key);\n pendingCounts.delete(key);\n });\n\n // 记录进行中的请求\n inflightRequests.set(key, promise);\n pendingCounts.set(key, 1);\n\n return promise;\n }) as typeof fetch;\n },\n\n /**\n * 获取当前进行中的请求数量\n */\n getPendingCount(): number {\n return inflightRequests.size;\n },\n\n /**\n * 获取所有进行中的请求 key\n */\n getPendingKeys(): string[] {\n return Array.from(inflightRequests.keys());\n },\n\n /**\n * 清除所有进行中的请求记录\n *\n * 注意:这不会取消请求,只是清除去重映射\n */\n clear(): void {\n inflightRequests.clear();\n pendingCounts.clear();\n },\n };\n}\n\n/**\n * 请求去重器类型\n */\nexport type RequestDeduper = ReturnType<typeof createRequestDeduper>;\n","/**\n * @djvlc/openapi-client-core - 指标收集\n *\n * 提供请求级别的指标收集能力,用于可观测性和性能监控。\n */\n\nimport type { Middleware, RequestContext, ResponseContext } from './types';\n\n/**\n * 请求指标\n */\nexport interface RequestMetrics {\n /** 请求 ID(唯一标识) */\n requestId: string;\n /** 请求 URL */\n url: string;\n /** 请求路径(不含 base URL 和 query) */\n path: string;\n /** HTTP 方法 */\n method: string;\n /** 请求开始时间戳(毫秒) */\n startTime: number;\n /** 请求结束时间戳(毫秒) */\n endTime: number;\n /** 请求耗时(毫秒) */\n durationMs: number;\n /** HTTP 状态码 */\n status: number;\n /** 是否成功(2xx) */\n success: boolean;\n /** 是否来自缓存 */\n fromCache?: boolean;\n /** 重试次数 */\n retryCount?: number;\n /** 请求体大小(字节) */\n requestSize?: number;\n /** 响应体大小(字节,如果可获取) */\n responseSize?: number;\n /** 错误信息(如果失败) */\n error?: string;\n /** 追踪 ID */\n traceId?: string;\n}\n\n/**\n * 指标摘要\n */\nexport interface MetricsSummary {\n /** 总请求数 */\n totalRequests: number;\n /** 成功请求数 */\n successCount: number;\n /** 失败请求数 */\n failureCount: number;\n /** 成功率 */\n successRate: number;\n /** 平均耗时(毫秒) */\n avgDurationMs: number;\n /** P50 耗时(毫秒) */\n p50Ms: number;\n /** P90 耗时(毫秒) */\n p90Ms: number;\n /** P95 耗时(毫秒) */\n p95Ms: number;\n /** P99 耗时(毫秒) */\n p99Ms: number;\n /** 最小耗时(毫秒) */\n minMs: number;\n /** 最大耗时(毫秒) */\n maxMs: number;\n /** 按状态码分组的计数 */\n statusCodeCounts: Record<number, number>;\n /** 按路径分组的计数 */\n pathCounts: Record<string, number>;\n /** 统计时间范围 */\n timeRange: {\n start: number;\n end: number;\n };\n}\n\n/**\n * 指标收集器选项\n */\nexport interface MetricsCollectorOptions {\n /** 最大保留的指标数量(避免内存泄漏) */\n maxMetrics?: number;\n /** 指标 TTL(毫秒,超过此时间的指标会被清理) */\n ttlMs?: number;\n /** 是否自动清理过期指标 */\n autoCleanup?: boolean;\n /** 清理间隔(毫秒) */\n cleanupIntervalMs?: number;\n /** 指标收集回调(每次请求完成时调用) */\n onMetrics?: (metrics: RequestMetrics) => void;\n}\n\n/**\n * 指标收集器\n */\nexport interface MetricsCollector {\n /** 收集指标 */\n collect(metrics: RequestMetrics): void;\n /** 获取所有指标 */\n getMetrics(): RequestMetrics[];\n /** 获取并清空所有指标 */\n flush(): RequestMetrics[];\n /** 获取指标摘要 */\n summary(): MetricsSummary;\n /** 按路径获取指标 */\n getByPath(path: string): RequestMetrics[];\n /** 按时间范围获取指标 */\n getByTimeRange(startTime: number, endTime: number): RequestMetrics[];\n /** 清除所有指标 */\n clear(): void;\n /** 销毁收集器(清理定时器等) */\n destroy(): void;\n}\n\n/**\n * 创建指标收集器\n *\n * @example\n * ```typescript\n * const metrics = createMetricsCollector({\n * maxMetrics: 1000,\n * onMetrics: (m) => console.log(`${m.method} ${m.path} - ${m.durationMs}ms`),\n * });\n *\n * // 使用 middleware 收集指标\n * const client = createClient({\n * middleware: [createMetricsMiddleware(metrics)],\n * });\n *\n * // 获取摘要\n * const summary = metrics.summary();\n * console.log(`成功率: ${(summary.successRate * 100).toFixed(1)}%`);\n * console.log(`P95: ${summary.p95Ms}ms`);\n * ```\n */\nexport function createMetricsCollector(\n options: MetricsCollectorOptions = {}\n): MetricsCollector {\n const {\n maxMetrics = 10000,\n ttlMs = 3600000, // 1 小时\n autoCleanup = true,\n cleanupIntervalMs = 60000, // 1 分钟\n onMetrics,\n } = options;\n\n const metricsStore: RequestMetrics[] = [];\n let cleanupTimer: ReturnType<typeof setInterval> | null = null;\n\n // 自动清理过期指标\n if (autoCleanup) {\n cleanupTimer = setInterval(() => {\n const now = Date.now();\n const cutoff = now - ttlMs;\n \n // 清理过期指标\n let i = 0;\n while (i < metricsStore.length && metricsStore[i].endTime < cutoff) {\n i++;\n }\n if (i > 0) {\n metricsStore.splice(0, i);\n }\n }, cleanupIntervalMs);\n }\n\n function collect(metrics: RequestMetrics): void {\n // 限制最大数量\n if (metricsStore.length >= maxMetrics) {\n metricsStore.shift();\n }\n \n metricsStore.push(metrics);\n onMetrics?.(metrics);\n }\n\n function getMetrics(): RequestMetrics[] {\n return [...metricsStore];\n }\n\n function flush(): RequestMetrics[] {\n const result = [...metricsStore];\n metricsStore.length = 0;\n return result;\n }\n\n function summary(): MetricsSummary {\n if (metricsStore.length === 0) {\n return {\n totalRequests: 0,\n successCount: 0,\n failureCount: 0,\n successRate: 0,\n avgDurationMs: 0,\n p50Ms: 0,\n p90Ms: 0,\n p95Ms: 0,\n p99Ms: 0,\n minMs: 0,\n maxMs: 0,\n statusCodeCounts: {},\n pathCounts: {},\n timeRange: { start: 0, end: 0 },\n };\n }\n\n const durations = metricsStore.map((m) => m.durationMs).sort((a, b) => a - b);\n const successCount = metricsStore.filter((m) => m.success).length;\n const failureCount = metricsStore.length - successCount;\n\n const statusCodeCounts: Record<number, number> = {};\n const pathCounts: Record<string, number> = {};\n\n for (const m of metricsStore) {\n statusCodeCounts[m.status] = (statusCodeCounts[m.status] ?? 0) + 1;\n pathCounts[m.path] = (pathCounts[m.path] ?? 0) + 1;\n }\n\n const getPercentile = (arr: number[], p: number): number => {\n const index = Math.floor(arr.length * p);\n return arr[Math.min(index, arr.length - 1)] ?? 0;\n };\n\n return {\n totalRequests: metricsStore.length,\n successCount,\n failureCount,\n successRate: successCount / metricsStore.length,\n avgDurationMs:\n durations.reduce((a, b) => a + b, 0) / durations.length,\n p50Ms: getPercentile(durations, 0.5),\n p90Ms: getPercentile(durations, 0.9),\n p95Ms: getPercentile(durations, 0.95),\n p99Ms: getPercentile(durations, 0.99),\n minMs: durations[0] ?? 0,\n maxMs: durations[durations.length - 1] ?? 0,\n statusCodeCounts,\n pathCounts,\n timeRange: {\n start: metricsStore[0]?.startTime ?? 0,\n end: metricsStore[metricsStore.length - 1]?.endTime ?? 0,\n },\n };\n }\n\n function getByPath(path: string): RequestMetrics[] {\n return metricsStore.filter((m) => m.path === path);\n }\n\n function getByTimeRange(startTime: number, endTime: number): RequestMetrics[] {\n return metricsStore.filter(\n (m) => m.startTime >= startTime && m.endTime <= endTime\n );\n }\n\n function clear(): void {\n metricsStore.length = 0;\n }\n\n function destroy(): void {\n if (cleanupTimer) {\n clearInterval(cleanupTimer);\n cleanupTimer = null;\n }\n clear();\n }\n\n return {\n collect,\n getMetrics,\n flush,\n summary,\n getByPath,\n getByTimeRange,\n clear,\n destroy,\n };\n}\n\n/**\n * 生成请求 ID\n */\nfunction generateRequestId(): string {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\n}\n\n/**\n * 从 URL 提取路径\n */\nfunction extractPath(url: string): string {\n try {\n const parsed = new URL(url);\n return parsed.pathname;\n } catch {\n // URL 可能是相对路径\n const match = url.match(/^[^?#]*/);\n return match?.[0] ?? url;\n }\n}\n\n/**\n * 创建指标收集 Middleware\n *\n * @example\n * ```typescript\n * const metrics = createMetricsCollector();\n * const middleware = createMetricsMiddleware(metrics);\n *\n * const client = createClient({\n * middleware: [middleware],\n * });\n * ```\n */\nexport function createMetricsMiddleware(collector: MetricsCollector): Middleware {\n const requestStarts = new Map<string, number>();\n\n return {\n pre(context: RequestContext): RequestContext {\n const requestId = generateRequestId();\n requestStarts.set(requestId, Date.now());\n \n return {\n ...context,\n meta: {\n ...context.meta,\n metricsRequestId: requestId,\n },\n };\n },\n\n post(context: ResponseContext): void {\n const requestId = context.meta?.metricsRequestId as string | undefined;\n if (!requestId) return;\n\n const startTime = requestStarts.get(requestId);\n if (!startTime) return;\n\n requestStarts.delete(requestId);\n const endTime = Date.now();\n\n const metrics: RequestMetrics = {\n requestId,\n url: context.url,\n path: extractPath(context.url),\n method: (context.init.method ?? 'GET').toUpperCase(),\n startTime,\n endTime,\n durationMs: endTime - startTime,\n status: context.response.status,\n success: context.response.ok,\n fromCache: context.meta?.fromCache as boolean | undefined,\n retryCount: context.meta?.retryCount as number | undefined,\n traceId: context.response.headers.get('x-request-id') ?? undefined,\n };\n\n // 尝试获取响应大小\n const contentLength = context.response.headers.get('content-length');\n if (contentLength) {\n metrics.responseSize = parseInt(contentLength, 10);\n }\n\n // 获取请求体大小\n if (context.init.body) {\n if (typeof context.init.body === 'string') {\n metrics.requestSize = new TextEncoder().encode(context.init.body).length;\n }\n }\n\n collector.collect(metrics);\n },\n };\n}\n","/**\n * @djvlc/openapi-client-core - 日志系统\n */\n\nimport type { Logger } from './types';\n\n/**\n * 创建控制台日志器\n */\nexport function createConsoleLogger(options: {\n /** 日志前缀 */\n prefix?: string;\n /** 是否启用 */\n enabled?: boolean;\n /** 日志级别:'debug' | 'info' | 'warn' | 'error' */\n level?: 'debug' | 'info' | 'warn' | 'error';\n /** 是否包含时间戳 */\n timestamp?: boolean;\n /** 是否包含请求体 */\n includeBody?: boolean;\n} = {}): Logger {\n const {\n prefix = '[DJV-API]',\n enabled = true,\n level = 'info',\n timestamp = true,\n includeBody = false,\n } = options;\n\n const levels = ['debug', 'info', 'warn', 'error'];\n const currentLevelIndex = levels.indexOf(level);\n\n const shouldLog = (logLevel: string): boolean => {\n return enabled && levels.indexOf(logLevel) >= currentLevelIndex;\n };\n\n const formatTime = (): string => {\n if (!timestamp) return '';\n return `[${new Date().toISOString()}] `;\n };\n\n const formatMethod = (init: RequestInit): string => {\n return init.method ?? 'GET';\n };\n\n return {\n request: (url, init) => {\n if (!shouldLog('debug')) return;\n\n const method = formatMethod(init);\n console.log(`${formatTime()}${prefix} -> ${method} ${url}`);\n\n if (includeBody && init.body) {\n try {\n const body = typeof init.body === 'string' ? JSON.parse(init.body) : init.body;\n console.log(`${prefix} Body:`, body);\n } catch {\n console.log(`${prefix} Body: [non-JSON]`);\n }\n }\n },\n\n response: (url, response, durationMs) => {\n if (!shouldLog('info')) return;\n\n const status = response.status;\n const statusEmoji = status >= 200 && status < 300 ? '✓' : '✗';\n\n console.log(\n `${formatTime()}${prefix} <- ${statusEmoji} ${status} ${url} (${durationMs}ms)`\n );\n },\n\n error: (url, error) => {\n if (!shouldLog('error')) return;\n\n console.error(`${formatTime()}${prefix} !! ${url}`, error);\n },\n\n retry: (url, attempt, error) => {\n if (!shouldLog('warn')) return;\n\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.warn(\n `${formatTime()}${prefix} ↻ Retry #${attempt} ${url} (${errorMessage})`\n );\n },\n };\n}\n\n/**\n * 创建静默日志器(不输出任何日志)\n */\nexport function createSilentLogger(): Logger {\n return {\n request: () => {},\n response: () => {},\n error: () => {},\n retry: () => {},\n };\n}\n\n/**\n * 创建自定义日志器\n *\n * 将日志发送到自定义目标(如监控系统)\n */\nexport function createCustomLogger(handlers: {\n onRequest?: (data: {\n url: string;\n method: string;\n headers?: Record<string, string>;\n timestamp: number;\n }) => void;\n onResponse?: (data: {\n url: string;\n status: number;\n durationMs: number;\n timestamp: number;\n }) => void;\n onError?: (data: {\n url: string;\n error: unknown;\n timestamp: number;\n }) => void;\n onRetry?: (data: {\n url: string;\n attempt: number;\n error: unknown;\n timestamp: number;\n }) => void;\n}): Logger {\n return {\n request: (url, init) => {\n handlers.onRequest?.({\n url,\n method: init.method ?? 'GET',\n timestamp: Date.now(),\n });\n },\n response: (url, response, durationMs) => {\n handlers.onResponse?.({\n url,\n status: response.status,\n durationMs,\n timestamp: Date.now(),\n });\n },\n error: (url, error) => {\n handlers.onError?.({\n url,\n error,\n timestamp: Date.now(),\n });\n },\n retry: (url, attempt, error) => {\n handlers.onRetry?.({\n url,\n attempt,\n error,\n timestamp: Date.now(),\n });\n },\n };\n}\n\n/**\n * 组合多个日志器\n */\nexport function combineLoggers(...loggers: Logger[]): Logger {\n return {\n request: (url, init) => {\n for (const logger of loggers) {\n logger.request?.(url, init);\n }\n },\n response: (url, response, durationMs) => {\n for (const logger of loggers) {\n logger.response?.(url, response, durationMs);\n }\n },\n error: (url, error) => {\n for (const logger of loggers) {\n logger.error?.(url, error);\n }\n },\n retry: (url, attempt, error) => {\n for (const logger of loggers) {\n logger.retry?.(url, attempt, error);\n }\n },\n };\n}\n","/**\n * @djvlc/openapi-client-core - Configuration 类\n *\n * 兼容 openapi-generator 生成的代码,同时提供增强能力。\n */\n\nimport type {\n Middleware,\n ConfigurationParameters,\n BaseClientOptions,\n SdkInfo,\n} from './types';\nimport { createEnhancedFetch } from './fetch';\nimport { createDefaultMiddlewares } from './middleware';\nimport { InterceptorManager } from './interceptors';\nimport { stripTrailingSlash } from './utils';\n\n/**\n * API 配置类\n *\n * 兼容 openapi-generator 的 Configuration,同时提供增强能力。\n */\nexport class Configuration {\n /** 基础路径 */\n basePath: string;\n\n /** fetch 实现 */\n fetchApi: typeof fetch;\n\n /** Middleware 列表 */\n middleware: Middleware[];\n\n /** Cookie 策略 */\n credentials?: RequestCredentials;\n\n /** 拦截器管理器 */\n interceptors: InterceptorManager;\n\n /** SDK 信息 */\n sdkInfo?: SdkInfo;\n\n constructor(params: ConfigurationParameters = {}) {\n this.basePath = params.basePath ?? '';\n this.fetchApi = params.fetchApi ?? fetch;\n this.middleware = params.middleware ?? [];\n this.credentials = params.credentials;\n this.interceptors = new InterceptorManager();\n }\n\n /**\n * 从 ClientOptions 创建 Configuration\n */\n static fromClientOptions(opts: BaseClientOptions, sdkInfo?: SdkInfo): Configuration {\n const config = new Configuration();\n\n config.basePath = stripTrailingSlash(opts.baseUrl);\n config.credentials = opts.credentials ?? 'omit';\n config.sdkInfo = sdkInfo;\n\n // 创建增强版 fetch\n config.fetchApi = createEnhancedFetch({\n fetchApi: opts.fetchApi,\n timeoutMs: opts.timeoutMs ?? 30000,\n retry: opts.retry,\n logger: opts.logger,\n });\n\n // 创建默认 Middleware\n config.middleware = [\n ...createDefaultMiddlewares(opts, sdkInfo),\n ...(opts.middleware ?? []),\n ];\n\n // 设置拦截器\n if (opts.interceptors) {\n config.interceptors = new InterceptorManager(opts.interceptors);\n }\n\n return config;\n }\n}\n\n/**\n * 创建兼容 openapi-generator 的 Configuration\n *\n * 这个函数用于快速创建一个简单的配置,兼容生成的 API 类。\n */\nexport function createConfiguration(\n opts: BaseClientOptions,\n sdkInfo?: SdkInfo\n): Configuration {\n return Configuration.fromClientOptions(opts, sdkInfo);\n}\n","/**\n * @djvlc/openapi-client-core - 客户端工厂\n *\n * 提供通用的客户端创建逻辑。\n */\n\nimport type { BaseClientOptions, SdkInfo } from './types';\nimport { Configuration } from './configuration';\n\n/**\n * API 类构造函数类型\n */\nexport type ApiConstructor<T> = new (configuration: Configuration) => T;\n\n/**\n * API 类映射\n */\nexport type ApiMap = Record<string, ApiConstructor<unknown>>;\n\n/**\n * 从 API 类映射提取实例类型\n */\nexport type ApiInstances<T extends ApiMap> = {\n [K in keyof T]: InstanceType<T[K]>;\n};\n\n/**\n * 创建客户端的通用工厂函数\n *\n * @example\n * ```typescript\n * import * as apis from './gen/apis';\n *\n * const client = createClient(apis, {\n * baseUrl: 'https://api.example.com',\n * getAuthToken: () => token,\n * }, { name: '@djvlc/openapi-user-client', version: '1.0.0' });\n * ```\n */\nexport function createClient<T extends ApiMap>(\n apiClasses: T,\n opts: BaseClientOptions,\n sdkInfo?: SdkInfo\n): {\n config: Configuration;\n apis: ApiInstances<T>;\n} & ApiInstances<T> {\n // 创建配置\n const config = Configuration.fromClientOptions(opts, sdkInfo);\n\n // 实例化所有 API 类\n const apiInstances = {} as ApiInstances<T>;\n\n for (const [name, ApiClass] of Object.entries(apiClasses)) {\n if (typeof ApiClass === 'function' && name.endsWith('Api')) {\n (apiInstances as Record<string, unknown>)[name] = new ApiClass(config);\n }\n }\n\n return {\n config,\n apis: apiInstances,\n ...apiInstances,\n };\n}\n\n/**\n * 过滤出 API 类(以 'Api' 结尾的构造函数)\n */\nexport function filterApiClasses<T extends Record<string, unknown>>(\n exports: T\n): Record<string, ApiConstructor<unknown>> {\n const result: Record<string, ApiConstructor<unknown>> = {};\n\n for (const [name, value] of Object.entries(exports)) {\n if (typeof value === 'function' && name.endsWith('Api')) {\n result[name] = value as ApiConstructor<unknown>;\n }\n }\n\n return result;\n}\n"],"mappings":"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","names":["exports"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/version.ts","../src/errors.ts","../src/utils.ts","../src/fetch.ts","../src/middleware.ts","../src/interceptors.ts","../src/dedupe.ts","../src/metrics.ts","../src/logger.ts","../src/configuration.ts","../src/client-factory.ts"],"sourcesContent":["/**\n * @djvlc/openapi-client-core\n *\n * OpenAPI Client 公共运行时库\n *\n * 提供:\n * - 结构化错误类(DjvApiError, NetworkError, TimeoutError, AbortError)\n * - 增强版 fetch(超时、重试、取消)\n * - Middleware 系统\n * - 拦截器系统\n * - 日志系统\n * - 请求去重\n * - 指标收集\n * - 客户端工厂\n *\n * @example\n * ```typescript\n * import {\n * createClient,\n * DjvApiError,\n * createConsoleLogger,\n * createMetricsCollector,\n * createMetricsMiddleware,\n * } from '@djvlc/openapi-client-core';\n *\n * const metrics = createMetricsCollector();\n *\n * const client = createClient(apis, {\n * baseUrl: 'https://api.example.com',\n * retry: { maxRetries: 2, respectRetryAfter: true },\n * logger: createConsoleLogger(),\n * middleware: [createMetricsMiddleware(metrics)],\n * });\n *\n * try {\n * await client.PageApi.resolvePage({ pageUid: 'xxx' });\n * } catch (e) {\n * if (DjvApiError.is(e)) {\n * console.log('业务错误:', e.code);\n * if (e.isRateLimited()) {\n * console.log('限流,等待:', e.getRetryAfter(), '秒');\n * }\n * }\n * }\n *\n * // 查看指标\n * console.log(metrics.summary());\n * ```\n */\n\n// ============================================================\n// 版本信息\n// ============================================================\nexport { SDK_VERSION, SDK_NAME, getSdkInfo } from './version';\n\n\n// ============================================================\n// 错误类\n// ============================================================\nexport {\n DjvApiError,\n NetworkError,\n TimeoutError,\n AbortError,\n isRetryableError,\n getRetryDelay,\n} from './errors';\n\n// ============================================================\n// 类型定义\n// ============================================================\nexport type {\n // 核心类型\n BaseClientOptions,\n RequestOptions,\n SdkInfo,\n\n // Middleware\n Middleware,\n RequestContext,\n ResponseContext,\n ConfigurationParameters,\n\n // 拦截器\n Interceptors,\n RequestInterceptor,\n ResponseInterceptor,\n ErrorInterceptor,\n\n // 重试\n RetryOptions,\n\n // 日志\n Logger,\n} from './types';\n\n// ============================================================\n// 工具函数\n// ============================================================\nexport {\n stripTrailingSlash,\n normalizeHeaders,\n mergeHeaders,\n delay,\n calculateBackoffDelay,\n getPlatform,\n buildUserAgent,\n isBrowser,\n safeParseJson,\n cloneResponse,\n} from './utils';\n\n// ============================================================\n// Fetch 增强\n// ============================================================\nexport {\n createFetchWithTimeout,\n createFetchWithRetry,\n createEnhancedFetch,\n executeRequest,\n} from './fetch';\n\n// ============================================================\n// Middleware\n// ============================================================\nexport {\n createHeadersMiddleware,\n createLoggingMiddleware,\n createDefaultMiddlewares,\n applyMiddlewareChain,\n applyPostMiddlewareChain,\n} from './middleware';\n\n// ============================================================\n// 拦截器\n// ============================================================\nexport {\n InterceptorManager,\n createTokenRefreshInterceptor,\n createDedupeInterceptor,\n createCacheInterceptor,\n} from './interceptors';\n\n// ============================================================\n// 请求去重\n// ============================================================\nexport {\n createRequestDeduper,\n type DedupeOptions,\n type RequestDeduper,\n} from './dedupe';\n\n// ============================================================\n// 指标收集\n// ============================================================\nexport {\n createMetricsCollector,\n createMetricsMiddleware,\n type RequestMetrics,\n type MetricsSummary,\n type MetricsCollector,\n type MetricsCollectorOptions,\n} from './metrics';\n\n// ============================================================\n// 日志\n// ============================================================\nexport {\n createConsoleLogger,\n createSilentLogger,\n createCustomLogger,\n combineLoggers,\n} from './logger';\n\n// ============================================================\n// Configuration\n// ============================================================\nexport { Configuration, createConfiguration } from './configuration';\n\n// ============================================================\n// 客户端工厂\n// ============================================================\nexport {\n createClient,\n filterApiClasses,\n type ApiConstructor,\n type ApiMap,\n type ApiInstances,\n} from './client-factory';\n","/**\n * @djvlc/openapi-client-core - 版本信息\n *\n * 版本号在构建时由 tsup 注入,避免手动维护。\n */\n\n// 这些常量在构建时由 tsup define 注入\ndeclare const __SDK_VERSION__: string;\ndeclare const __SDK_NAME__: string;\n\n/**\n * SDK 版本号(构建时注入)\n */\nexport const SDK_VERSION: string =\n typeof __SDK_VERSION__ !== 'undefined' ? __SDK_VERSION__ : '0.0.0-dev';\n\n/**\n * SDK 名称(构建时注入)\n */\nexport const SDK_NAME: string =\n typeof __SDK_NAME__ !== 'undefined' ? __SDK_NAME__ : '@djvlc/openapi-client-core';\n\n/**\n * 获取 SDK 版本信息\n */\nexport function getSdkInfo(): { name: string; version: string } {\n return {\n name: SDK_NAME,\n version: SDK_VERSION,\n };\n}\n","/**\n * @djvlc/openapi-client-core - 错误类定义\n *\n * 提供结构化的错误类型,便于调用方区分和处理不同类型的错误。\n *\n * 错误层次:\n * - DjvApiError: 业务层错误(服务器返回的错误响应)\n * - NetworkError: 网络层错误(连接失败、DNS 解析失败等)\n * - TimeoutError: 超时错误(继承自 NetworkError)\n * - AbortError: 请求被取消(继承自 NetworkError)\n */\n\n/**\n * API 业务错误\n *\n * 当服务器返回非 2xx 响应时抛出,包含完整的错误信息。\n *\n * @example\n * ```typescript\n * try {\n * await client.PageApi.resolvePage({ pageUid: 'xxx' });\n * } catch (e) {\n * if (DjvApiError.is(e)) {\n * console.log('业务错误:', e.code, e.message);\n * console.log('追踪ID:', e.traceId);\n *\n * // 使用增强方法\n * if (e.isAuthError()) {\n * redirectToLogin();\n * } else if (e.isRateLimited()) {\n * const retryAfter = e.getRetryAfter();\n * await delay(retryAfter * 1000);\n * }\n * }\n * }\n * ```\n */\nexport class DjvApiError extends Error {\n /** 标识这是一个 API 错误(用于 instanceof 替代方案) */\n readonly isApiError = true as const;\n\n /** 错误名称 */\n readonly name = 'DjvApiError' as const;\n\n constructor(\n message: string,\n /** 业务错误码(可能是字符串如 'INVALID_REQUEST' 或数字如 1001) */\n public readonly code: string | number,\n /** HTTP 状态码 */\n public readonly status: number,\n /** 追踪 ID(用于日志排查) */\n public readonly traceId?: string,\n /** 详细错误信息(字段级错误等) */\n public readonly details?: unknown,\n /** 原始响应对象 */\n public readonly response?: Response,\n ) {\n super(message);\n // 确保原型链正确(TypeScript 继承 Error 的问题)\n Object.setPrototypeOf(this, DjvApiError.prototype);\n }\n\n // ============================================================\n // 增强方法 - P1 优化\n // ============================================================\n\n /**\n * 是否为认证错误 (401 Unauthorized)\n */\n isUnauthorized(): boolean {\n return this.status === 401;\n }\n\n /**\n * 是否为权限错误 (403 Forbidden)\n */\n isForbidden(): boolean {\n return this.status === 403;\n }\n\n /**\n * 是否为认证相关错误 (401 或 403)\n */\n isAuthError(): boolean {\n return this.status === 401 || this.status === 403;\n }\n\n /**\n * 是否为客户端错误 (4xx)\n */\n isClientError(): boolean {\n return this.status >= 400 && this.status < 500;\n }\n\n /**\n * 是否为服务端错误 (5xx)\n */\n isServerError(): boolean {\n return this.status >= 500;\n }\n\n /**\n * 是否为限流错误 (429 Too Many Requests)\n */\n isRateLimited(): boolean {\n return this.status === 429;\n }\n\n /**\n * 是否为资源未找到 (404 Not Found)\n */\n isNotFound(): boolean {\n return this.status === 404;\n }\n\n /**\n * 是否为请求冲突 (409 Conflict)\n */\n isConflict(): boolean {\n return this.status === 409;\n }\n\n /**\n * 是否为请求验证失败 (400 Bad Request 或 422 Unprocessable Entity)\n */\n isValidationError(): boolean {\n return this.status === 400 || this.status === 422;\n }\n\n /**\n * 获取 Retry-After 头的值(秒)\n *\n * 适用于 429 限流响应和 503 服务不可用响应\n *\n * @returns 重试等待秒数,如果没有 Retry-After 头则返回 null\n */\n getRetryAfter(): number | null {\n const header = this.response?.headers.get('Retry-After');\n if (!header) return null;\n\n // Retry-After 可以是秒数或 HTTP 日期\n const seconds = parseInt(header, 10);\n if (!isNaN(seconds)) {\n return seconds;\n }\n\n // 尝试解析为日期\n const date = Date.parse(header);\n if (!isNaN(date)) {\n return Math.max(0, Math.ceil((date - Date.now()) / 1000));\n }\n\n return null;\n }\n\n /**\n * 获取重试延迟(毫秒)\n *\n * 优先使用 Retry-After 头,否则返回默认值\n *\n * @param defaultMs 默认延迟毫秒数\n */\n getRetryDelayMs(defaultMs = 1000): number {\n const retryAfter = this.getRetryAfter();\n return retryAfter !== null ? retryAfter * 1000 : defaultMs;\n }\n\n // ============================================================\n // 静态方法\n // ============================================================\n\n /**\n * 类型保护:判断是否为 DjvApiError\n */\n static is(error: unknown): error is DjvApiError {\n if (error instanceof DjvApiError) return true;\n if (error == null || typeof error !== 'object') return false;\n return 'isApiError' in error && (error as DjvApiError).isApiError === true;\n }\n\n /**\n * 从响应创建错误\n */\n static async fromResponse(response: Response): Promise<DjvApiError> {\n let body: {\n code?: string | number;\n message?: string;\n traceId?: string;\n requestId?: string;\n details?: unknown;\n } = {};\n\n try {\n body = await response.json();\n } catch {\n // 响应体不是 JSON,忽略\n }\n\n const message = body.message || response.statusText || `HTTP ${response.status}`;\n const code = body.code || response.status;\n const traceId = body.traceId || body.requestId || response.headers.get('x-request-id') || undefined;\n\n return new DjvApiError(message, code, response.status, traceId, body.details, response);\n }\n\n /**\n * 转为 JSON(便于日志记录)\n */\n toJSON() {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n status: this.status,\n traceId: this.traceId,\n details: this.details,\n };\n }\n}\n\n/**\n * 网络层错误\n *\n * 当请求无法到达服务器时抛出(连接失败、DNS 解析失败、CORS 等)。\n *\n * @example\n * ```typescript\n * try {\n * await client.PageApi.resolvePage({ pageUid: 'xxx' });\n * } catch (e) {\n * if (NetworkError.is(e)) {\n * console.log('网络错误,请检查网络连接');\n * }\n * }\n * ```\n */\nexport class NetworkError extends Error {\n /** 标识这是一个网络错误 */\n readonly isNetworkError = true as const;\n\n /** 错误名称 */\n override readonly name: string = 'NetworkError';\n\n /** 原始错误 */\n readonly originalCause?: Error;\n\n constructor(\n message: string,\n /** 原始错误 */\n cause?: Error,\n ) {\n super(message);\n this.originalCause = cause;\n // 尝试设置 cause(ES2022+)\n if (cause && 'cause' in Error.prototype) {\n (this as unknown as { cause?: Error }).cause = cause;\n }\n Object.setPrototypeOf(this, NetworkError.prototype);\n }\n\n /**\n * 获取原始错误\n */\n get cause(): Error | undefined {\n return this.originalCause;\n }\n\n /**\n * 类型保护:判断是否为 NetworkError(包括子类)\n */\n static is(error: unknown): error is NetworkError {\n if (error instanceof NetworkError) return true;\n if (error == null || typeof error !== 'object') return false;\n return 'isNetworkError' in error && (error as NetworkError).isNetworkError === true;\n }\n\n /**\n * 从原始错误创建\n */\n static fromError(error: unknown): NetworkError | AbortError {\n if (error instanceof NetworkError) return error;\n\n const cause = error instanceof Error ? error : undefined;\n const message = error instanceof Error ? error.message : String(error);\n\n // 检查是否为 AbortError\n if (cause?.name === 'AbortError') {\n return new AbortError('Request was aborted');\n }\n\n return new NetworkError(message, cause);\n }\n\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n cause: this.cause?.message,\n };\n }\n}\n\n/**\n * 超时错误\n *\n * 当请求超过指定时间未响应时抛出。\n *\n * @example\n * ```typescript\n * try {\n * await client.PageApi.resolvePage({ pageUid: 'xxx' });\n * } catch (e) {\n * if (TimeoutError.is(e)) {\n * console.log(`请求超时 (${e.timeoutMs}ms),请稍后重试`);\n * }\n * }\n * ```\n */\nexport class TimeoutError extends NetworkError {\n /** 标识这是一个超时错误 */\n readonly isTimeout = true as const;\n\n override readonly name: string = 'TimeoutError';\n\n constructor(\n /** 超时时间(毫秒) */\n public readonly timeoutMs: number,\n /** 请求 URL */\n public readonly url?: string,\n ) {\n super(`Request timeout after ${timeoutMs}ms${url ? `: ${url}` : ''}`);\n Object.setPrototypeOf(this, TimeoutError.prototype);\n }\n\n /**\n * 类型保护:判断是否为 TimeoutError\n */\n static override is(error: unknown): error is TimeoutError {\n if (error instanceof TimeoutError) return true;\n if (error == null || typeof error !== 'object') return false;\n return 'isTimeout' in error && (error as TimeoutError).isTimeout === true;\n }\n\n override toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n timeoutMs: this.timeoutMs,\n url: this.url,\n };\n }\n}\n\n/**\n * 请求取消错误\n *\n * 当请求被用户手动取消时抛出。\n *\n * @example\n * ```typescript\n * const controller = new AbortController();\n * setTimeout(() => controller.abort(), 100);\n *\n * try {\n * await client.PageApi.resolvePage({ pageUid: 'xxx' }, { signal: controller.signal });\n * } catch (e) {\n * if (AbortError.is(e)) {\n * console.log('请求已取消');\n * }\n * }\n * ```\n */\nexport class AbortError extends NetworkError {\n /** 标识这是一个取消错误 */\n readonly isAbort = true as const;\n\n override readonly name: string = 'AbortError';\n\n constructor(message = 'Request was aborted') {\n super(message);\n Object.setPrototypeOf(this, AbortError.prototype);\n }\n\n /**\n * 类型保护:判断是否为 AbortError\n */\n static override is(error: unknown): error is AbortError {\n if (error instanceof AbortError) return true;\n if (error == null || typeof error !== 'object') return false;\n return 'isAbort' in error && (error as AbortError).isAbort === true;\n }\n}\n\n/**\n * 判断错误是否可重试\n *\n * 可重试的情况:\n * - 超时错误\n * - 网络错误(非取消)\n * - 特定 HTTP 状态码:408, 429, 500, 502, 503, 504\n */\nexport function isRetryableError(error: unknown): boolean {\n // 取消请求不应重试\n if (AbortError.is(error)) return false;\n\n // 超时和网络错误可重试\n if (TimeoutError.is(error) || NetworkError.is(error)) return true;\n\n // API 错误根据状态码判断\n if (DjvApiError.is(error)) {\n const retryableStatuses = [408, 429, 500, 502, 503, 504];\n return retryableStatuses.includes(error.status);\n }\n\n return false;\n}\n\n/**\n * 获取错误的推荐重试延迟(毫秒)\n *\n * 优先使用 Retry-After 头,否则返回默认值\n */\nexport function getRetryDelay(error: unknown, defaultMs = 1000): number {\n if (DjvApiError.is(error)) {\n return error.getRetryDelayMs(defaultMs);\n }\n return defaultMs;\n}\n","/**\n * @djvlc/openapi-client-core - 工具函数\n */\n\n/**\n * 移除 URL 末尾的斜杠\n */\nexport function stripTrailingSlash(url: string): string {\n return url.replace(/\\/$/, '');\n}\n\n/**\n * 标准化 Headers\n */\nexport function normalizeHeaders(initHeaders: HeadersInit | undefined): Headers {\n return new Headers(initHeaders ?? {});\n}\n\n/**\n * 合并多个 Headers\n */\nexport function mergeHeaders(...headersList: (HeadersInit | undefined)[]): Headers {\n const result = new Headers();\n\n for (const headers of headersList) {\n if (!headers) continue;\n\n const normalized = new Headers(headers);\n normalized.forEach((value, key) => {\n result.set(key, value);\n });\n }\n\n return result;\n}\n\n/**\n * 延迟指定时间\n */\nexport function delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * 计算指数退避延迟\n */\nexport function calculateBackoffDelay(\n attempt: number,\n baseDelayMs: number,\n maxDelayMs: number,\n exponential = true\n): number {\n if (!exponential) return baseDelayMs;\n\n // 指数退避 + 随机抖动\n const exponentialDelay = baseDelayMs * Math.pow(2, attempt - 1);\n const jitter = Math.random() * 0.3 * exponentialDelay; // 30% 抖动\n const delayWithJitter = exponentialDelay + jitter;\n\n return Math.min(delayWithJitter, maxDelayMs);\n}\n\n/**\n * 获取当前运行平台\n */\nexport function getPlatform(): string {\n // Node.js\n if (typeof process !== 'undefined' && process.versions?.node) {\n return `node/${process.versions.node}`;\n }\n\n // Deno\n if (typeof Deno !== 'undefined') {\n return `deno/${Deno.version?.deno ?? 'unknown'}`;\n }\n\n // Browser\n if (typeof navigator !== 'undefined') {\n const ua = navigator.userAgent;\n if (ua.includes('Chrome')) return 'chrome';\n if (ua.includes('Firefox')) return 'firefox';\n if (ua.includes('Safari')) return 'safari';\n if (ua.includes('Edge')) return 'edge';\n return 'browser';\n }\n\n return 'unknown';\n}\n\n/**\n * 生成 SDK User-Agent 字符串\n */\nexport function buildUserAgent(sdkName: string, sdkVersion: string): string {\n const platform = getPlatform();\n return `${sdkName}/${sdkVersion} (${platform})`;\n}\n\n/**\n * 判断是否为浏览器环境\n */\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * 安全解析 JSON\n */\nexport async function safeParseJson<T = unknown>(response: Response): Promise<T | null> {\n try {\n return await response.json() as T;\n } catch {\n return null;\n }\n}\n\n/**\n * 克隆响应(用于读取 body 后仍保留原响应)\n */\nexport function cloneResponse(response: Response): Response {\n return response.clone();\n}\n\n// Deno 类型声明(避免 TypeScript 报错)\ndeclare const Deno: {\n version?: {\n deno?: string;\n };\n} | undefined;\n","/**\n * @djvlc/openapi-client-core - Fetch 增强\n *\n * 提供超时、重试、取消等能力的 fetch 封装。\n */\n\nimport { DjvApiError, NetworkError, TimeoutError, AbortError, isRetryableError } from './errors';\nimport type { RetryOptions, Logger, RequestOptions } from './types';\nimport { delay, calculateBackoffDelay } from './utils';\n\n/**\n * 默认重试配置\n */\nconst DEFAULT_RETRY_OPTIONS: Required<RetryOptions> = {\n maxRetries: 0,\n retryDelayMs: 1000,\n exponentialBackoff: true,\n maxDelayMs: 30000,\n retryableStatuses: [408, 429, 500, 502, 503, 504],\n shouldRetry: () => true,\n onRetry: () => {},\n respectRetryAfter: true, // P1: 默认尊重 Retry-After 头\n};\n\n/**\n * 创建带超时的 fetch\n */\nexport function createFetchWithTimeout(\n fetchImpl: typeof fetch,\n timeoutMs: number\n): typeof fetch {\n return (async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n // 合并外部 signal\n const externalSignal = init?.signal;\n if (externalSignal) {\n if (externalSignal.aborted) {\n clearTimeout(timeoutId);\n throw new AbortError('Request was aborted');\n }\n externalSignal.addEventListener('abort', () => {\n clearTimeout(timeoutId);\n controller.abort();\n });\n }\n\n try {\n const response = await fetchImpl(input, {\n ...init,\n signal: controller.signal,\n });\n return response;\n } catch (error) {\n // 区分超时和手动取消\n if (error instanceof Error && error.name === 'AbortError') {\n const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;\n if (externalSignal?.aborted) {\n throw new AbortError('Request was aborted');\n }\n throw new TimeoutError(timeoutMs, url);\n }\n throw NetworkError.fromError(error);\n } finally {\n clearTimeout(timeoutId);\n }\n }) as typeof fetch;\n}\n\n/**\n * 从响应或错误中获取重试延迟\n *\n * P1: 支持 Retry-After 头\n */\nfunction getRetryDelayFromResponse(\n response: Response | null,\n error: unknown,\n attempt: number,\n opts: Required<RetryOptions>\n): number {\n // 1. 优先使用 Retry-After 头(如果启用)\n if (opts.respectRetryAfter && response) {\n const retryAfter = response.headers.get('Retry-After');\n if (retryAfter) {\n // Retry-After 可以是秒数\n const seconds = parseInt(retryAfter, 10);\n if (!isNaN(seconds)) {\n return Math.min(seconds * 1000, opts.maxDelayMs);\n }\n \n // 或者是 HTTP 日期\n const date = Date.parse(retryAfter);\n if (!isNaN(date)) {\n const delayMs = Math.max(0, date - Date.now());\n return Math.min(delayMs, opts.maxDelayMs);\n }\n }\n }\n\n // 2. 使用错误类中的 getRetryDelayMs 方法\n if (DjvApiError.is(error)) {\n const errorDelay = error.getRetryDelayMs(0);\n if (errorDelay > 0) {\n return Math.min(errorDelay, opts.maxDelayMs);\n }\n }\n\n // 3. 使用计算的退避延迟\n return calculateBackoffDelay(\n attempt,\n opts.retryDelayMs,\n opts.maxDelayMs,\n opts.exponentialBackoff\n );\n}\n\n/**\n * 创建带重试的 fetch\n */\nexport function createFetchWithRetry(\n fetchImpl: typeof fetch,\n options: RetryOptions = {},\n logger?: Logger\n): typeof fetch {\n const opts = { ...DEFAULT_RETRY_OPTIONS, ...options };\n\n return (async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;\n let lastError: unknown;\n let lastResponse: Response | null = null;\n\n for (let attempt = 0; attempt <= opts.maxRetries; attempt++) {\n try {\n const response = await fetchImpl(input, init);\n lastResponse = response;\n\n // 检查是否需要重试(基于状态码)\n if (!response.ok && attempt < opts.maxRetries) {\n if (opts.retryableStatuses.includes(response.status)) {\n const error = await DjvApiError.fromResponse(response.clone());\n\n if (opts.shouldRetry(error, attempt + 1)) {\n // P1: 使用增强的重试延迟计算\n const delayMs = getRetryDelayFromResponse(\n response,\n error,\n attempt + 1,\n opts\n );\n\n opts.onRetry(error, attempt + 1, delayMs);\n logger?.retry?.(url, attempt + 1, error);\n\n await delay(delayMs);\n continue;\n }\n }\n }\n\n return response;\n } catch (error) {\n lastError = error;\n\n // 取消请求不重试\n if (AbortError.is(error)) {\n throw error;\n }\n\n // 最后一次尝试直接抛出\n if (attempt >= opts.maxRetries) {\n throw error;\n }\n\n // 判断是否可重试\n if (!isRetryableError(error) || !opts.shouldRetry(error, attempt + 1)) {\n throw error;\n }\n\n // P1: 使用增强的重试延迟计算\n const delayMs = getRetryDelayFromResponse(\n lastResponse,\n error,\n attempt + 1,\n opts\n );\n\n opts.onRetry(error, attempt + 1, delayMs);\n logger?.retry?.(url, attempt + 1, error);\n\n await delay(delayMs);\n }\n }\n\n // 不应该到达这里,但为了类型安全\n throw lastError;\n }) as typeof fetch;\n}\n\n/**\n * 创建增强版 fetch(组合超时 + 重试 + 日志)\n */\nexport function createEnhancedFetch(options: {\n fetchApi?: typeof fetch;\n timeoutMs?: number;\n retry?: RetryOptions;\n logger?: Logger;\n}): typeof fetch {\n const {\n fetchApi = fetch,\n timeoutMs = 30000,\n retry,\n logger,\n } = options;\n\n // 层层包装\n let enhancedFetch = fetchApi;\n\n // 1. 超时\n enhancedFetch = createFetchWithTimeout(enhancedFetch, timeoutMs);\n\n // 2. 重试\n if (retry && retry.maxRetries && retry.maxRetries > 0) {\n enhancedFetch = createFetchWithRetry(enhancedFetch, retry, logger);\n }\n\n // 3. 日志包装\n if (logger) {\n const wrappedFetch = enhancedFetch;\n enhancedFetch = (async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;\n const startTime = Date.now();\n\n logger.request?.(url, init ?? {});\n\n try {\n const response = await wrappedFetch(input, init);\n const durationMs = Date.now() - startTime;\n logger.response?.(url, response, durationMs);\n return response;\n } catch (error) {\n logger.error?.(url, error);\n throw error;\n }\n }) as typeof fetch;\n }\n\n return enhancedFetch;\n}\n\n/**\n * 执行请求并处理错误\n *\n * 统一处理响应,非 2xx 响应转换为 DjvApiError\n */\nexport async function executeRequest(\n fetchFn: typeof fetch,\n url: string,\n init: RequestInit,\n options?: RequestOptions\n): Promise<Response> {\n // 处理请求级别的 signal 和 timeout\n const finalInit = { ...init };\n let timeoutController: AbortController | undefined;\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n if (options?.timeoutMs) {\n timeoutController = new AbortController();\n timeoutId = setTimeout(() => timeoutController!.abort(), options.timeoutMs);\n\n // 合并 signal\n if (options.signal) {\n options.signal.addEventListener('abort', () => {\n clearTimeout(timeoutId);\n timeoutController!.abort();\n });\n }\n\n finalInit.signal = timeoutController.signal;\n } else if (options?.signal) {\n finalInit.signal = options.signal;\n }\n\n try {\n const response = await fetchFn(url, finalInit);\n\n // 非 2xx 响应转为错误\n if (!response.ok) {\n throw await DjvApiError.fromResponse(response);\n }\n\n return response;\n } catch (error) {\n // 已经是我们的错误类型,直接抛出\n if (DjvApiError.is(error) || NetworkError.is(error)) {\n throw error;\n }\n\n // AbortError 特殊处理\n if (error instanceof Error && error.name === 'AbortError') {\n if (options?.signal?.aborted) {\n throw new AbortError('Request was aborted');\n }\n if (options?.timeoutMs) {\n throw new TimeoutError(options.timeoutMs, url);\n }\n throw new AbortError();\n }\n\n // 其他错误包装为 NetworkError\n throw NetworkError.fromError(error);\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n}\n","/**\n * @djvlc/openapi-client-core - Middleware 系统\n *\n * 提供请求/响应拦截、认证注入、追踪头注入等能力。\n */\n\nimport type {\n Middleware,\n RequestContext,\n ResponseContext,\n SdkInfo,\n BaseClientOptions,\n} from './types';\nimport { normalizeHeaders, buildUserAgent } from './utils';\n\n/**\n * 创建 Headers 注入 Middleware\n *\n * 统一处理:\n * - 默认 Headers\n * - Bearer Token\n * - API Key\n * - Trace Headers\n * - SDK 版本\n */\nexport function createHeadersMiddleware(opts: {\n getAuthToken?: () => string | Promise<string>;\n getApiKey?: () => string | Promise<string>;\n getTraceHeaders?: () => Record<string, string>;\n defaultHeaders?: Record<string, string>;\n sdkInfo?: SdkInfo;\n}): Middleware {\n return {\n async pre(context: RequestContext): Promise<RequestContext> {\n const headers = normalizeHeaders(context.init.headers);\n\n // 1. 默认 Headers\n if (opts.defaultHeaders) {\n for (const [key, value] of Object.entries(opts.defaultHeaders)) {\n headers.set(key, value);\n }\n }\n\n // 2. API Key(如果提供)\n if (opts.getApiKey) {\n const apiKey = await opts.getApiKey();\n if (apiKey) {\n headers.set('X-Api-Key', apiKey);\n }\n }\n\n // 3. Bearer Token(如果提供)\n if (opts.getAuthToken) {\n const token = await opts.getAuthToken();\n if (token) {\n headers.set('Authorization', `Bearer ${token}`);\n }\n }\n\n // 4. Trace Headers(OpenTelemetry)\n if (opts.getTraceHeaders) {\n const traceHeaders = opts.getTraceHeaders();\n for (const [key, value] of Object.entries(traceHeaders)) {\n headers.set(key, value);\n }\n }\n\n // 5. SDK 版本信息\n if (opts.sdkInfo) {\n headers.set('X-SDK-Version', `${opts.sdkInfo.name}@${opts.sdkInfo.version}`);\n headers.set('User-Agent', buildUserAgent(opts.sdkInfo.name, opts.sdkInfo.version));\n }\n\n return {\n ...context,\n init: {\n ...context.init,\n headers,\n },\n };\n },\n };\n}\n\n/**\n * 创建日志 Middleware\n */\nexport function createLoggingMiddleware(opts: {\n onRequest?: (url: string, init: RequestInit) => void;\n onResponse?: (url: string, response: Response, durationMs: number) => void;\n onError?: (url: string, error: unknown) => void;\n}): Middleware {\n const requestStartTimes = new Map<string, number>();\n\n return {\n pre(context: RequestContext): RequestContext {\n const requestId = `${context.url}-${Date.now()}`;\n requestStartTimes.set(requestId, Date.now());\n context.meta = { ...context.meta, requestId };\n\n opts.onRequest?.(context.url, context.init);\n return context;\n },\n post(context: ResponseContext): void {\n const requestId = context.meta?.requestId as string;\n const startTime = requestStartTimes.get(requestId);\n const durationMs = startTime ? Date.now() - startTime : 0;\n\n requestStartTimes.delete(requestId);\n opts.onResponse?.(context.url, context.response, durationMs);\n },\n };\n}\n\n/**\n * 应用 Middleware 链\n */\nexport async function applyMiddlewareChain(\n middlewares: Middleware[],\n context: RequestContext\n): Promise<RequestContext> {\n let currentContext = context;\n\n for (const middleware of middlewares) {\n if (middleware.pre) {\n currentContext = await middleware.pre(currentContext);\n }\n }\n\n return currentContext;\n}\n\n/**\n * 应用 post Middleware 链\n */\nexport async function applyPostMiddlewareChain(\n middlewares: Middleware[],\n context: ResponseContext\n): Promise<void> {\n // 倒序执行 post hooks\n for (let i = middlewares.length - 1; i >= 0; i--) {\n const middleware = middlewares[i];\n if (middleware.post) {\n await middleware.post(context);\n }\n }\n}\n\n/**\n * 从 ClientOptions 创建默认 Middleware 列表\n */\nexport function createDefaultMiddlewares(\n opts: Pick<\n BaseClientOptions,\n 'getAuthToken' | 'getApiKey' | 'getTraceHeaders' | 'defaultHeaders' | 'logger' | 'debug'\n >,\n sdkInfo?: SdkInfo\n): Middleware[] {\n const middlewares: Middleware[] = [];\n\n // Headers 注入\n middlewares.push(\n createHeadersMiddleware({\n getAuthToken: opts.getAuthToken,\n getApiKey: opts.getApiKey,\n getTraceHeaders: opts.getTraceHeaders,\n defaultHeaders: opts.defaultHeaders,\n sdkInfo,\n })\n );\n\n // 日志(调试模式或有 logger)\n if (opts.debug || opts.logger) {\n middlewares.push(\n createLoggingMiddleware({\n onRequest: (url, init) => {\n if (opts.debug) {\n console.log(`[API] -> ${init.method ?? 'GET'} ${url}`);\n }\n opts.logger?.request?.(url, init);\n },\n onResponse: (url, response, durationMs) => {\n if (opts.debug) {\n console.log(`[API] <- ${response.status} ${url} (${durationMs}ms)`);\n }\n opts.logger?.response?.(url, response, durationMs);\n },\n onError: (url, error) => {\n if (opts.debug) {\n console.error(`[API] !! ${url}`, error);\n }\n opts.logger?.error?.(url, error);\n },\n })\n );\n }\n\n // 合并用户自定义 Middleware\n // 注意:用户 middleware 在最后执行,可以覆盖默认行为\n\n return middlewares;\n}\n","/**\n * @djvlc/openapi-client-core - 拦截器系统\n *\n * 提供更灵活的请求/响应/错误拦截能力。\n */\n\nimport type {\n Interceptors,\n RequestInterceptor,\n ResponseInterceptor,\n ErrorInterceptor,\n RequestContext,\n} from './types';\n\n/**\n * 拦截器管理器\n */\nexport class InterceptorManager {\n private requestInterceptors: RequestInterceptor[] = [];\n private responseInterceptors: ResponseInterceptor[] = [];\n private errorInterceptors: ErrorInterceptor[] = [];\n\n constructor(interceptors?: Interceptors) {\n if (interceptors?.request) {\n this.requestInterceptors.push(...interceptors.request);\n }\n if (interceptors?.response) {\n this.responseInterceptors.push(...interceptors.response);\n }\n if (interceptors?.error) {\n this.errorInterceptors.push(...interceptors.error);\n }\n }\n\n /**\n * 添加请求拦截器\n * @returns 移除拦截器的函数\n */\n addRequestInterceptor(interceptor: RequestInterceptor): () => void {\n this.requestInterceptors.push(interceptor);\n return () => {\n const index = this.requestInterceptors.indexOf(interceptor);\n if (index >= 0) {\n this.requestInterceptors.splice(index, 1);\n }\n };\n }\n\n /**\n * 添加响应拦截器\n * @returns 移除拦截器的函数\n */\n addResponseInterceptor(interceptor: ResponseInterceptor): () => void {\n this.responseInterceptors.push(interceptor);\n return () => {\n const index = this.responseInterceptors.indexOf(interceptor);\n if (index >= 0) {\n this.responseInterceptors.splice(index, 1);\n }\n };\n }\n\n /**\n * 添加错误拦截器\n * @returns 移除拦截器的函数\n */\n addErrorInterceptor(interceptor: ErrorInterceptor): () => void {\n this.errorInterceptors.push(interceptor);\n return () => {\n const index = this.errorInterceptors.indexOf(interceptor);\n if (index >= 0) {\n this.errorInterceptors.splice(index, 1);\n }\n };\n }\n\n /**\n * 执行请求拦截器链\n */\n async runRequestInterceptors(context: RequestContext): Promise<RequestContext> {\n let currentContext = context;\n\n for (const interceptor of this.requestInterceptors) {\n currentContext = await interceptor(currentContext);\n }\n\n return currentContext;\n }\n\n /**\n * 执行响应拦截器链\n */\n async runResponseInterceptors(response: Response, context: RequestContext): Promise<Response> {\n let currentResponse = response;\n\n for (const interceptor of this.responseInterceptors) {\n currentResponse = await interceptor(currentResponse, context);\n }\n\n return currentResponse;\n }\n\n /**\n * 执行错误拦截器链\n */\n async runErrorInterceptors(error: unknown, context: RequestContext): Promise<unknown> {\n let currentError = error;\n\n for (const interceptor of this.errorInterceptors) {\n try {\n // 错误拦截器可以:\n // 1. 抛出新错误\n // 2. 返回原错误(继续传递)\n // 3. 返回 Response(恢复请求)\n currentError = await interceptor(currentError, context);\n } catch (e) {\n currentError = e;\n }\n }\n\n return currentError;\n }\n\n /**\n * 清除所有拦截器\n */\n clear(): void {\n this.requestInterceptors = [];\n this.responseInterceptors = [];\n this.errorInterceptors = [];\n }\n}\n\n/**\n * 创建 Token 刷新拦截器\n *\n * 当收到 401 错误时自动刷新 token 并重试请求\n */\nexport function createTokenRefreshInterceptor(options: {\n /** 刷新 token 的函数 */\n refreshToken: () => Promise<string>;\n /** 判断是否需要刷新 */\n shouldRefresh?: (response: Response) => boolean;\n /** 最大刷新重试次数 */\n maxRetries?: number;\n}): ResponseInterceptor {\n const {\n refreshToken,\n shouldRefresh = (response) => response.status === 401,\n maxRetries = 1,\n } = options;\n\n let refreshPromise: Promise<string> | null = null;\n let retryCount = 0;\n\n return async (response, context) => {\n if (!shouldRefresh(response) || retryCount >= maxRetries) {\n retryCount = 0;\n return response;\n }\n\n retryCount++;\n\n // 避免并发刷新\n if (!refreshPromise) {\n refreshPromise = refreshToken().finally(() => {\n refreshPromise = null;\n });\n }\n\n try {\n const newToken = await refreshPromise;\n\n // 用新 token 重试请求\n const headers = new Headers(context.init.headers);\n headers.set('Authorization', `Bearer ${newToken}`);\n\n const newResponse = await fetch(context.url, {\n ...context.init,\n headers,\n });\n\n retryCount = 0;\n return newResponse;\n } catch {\n retryCount = 0;\n return response;\n }\n };\n}\n\n/**\n * 创建请求去重拦截器\n *\n * 相同请求(URL + Method)在进行中时,复用同一个 Promise\n */\nexport function createDedupeInterceptor(): {\n interceptor: RequestInterceptor;\n clear: () => void;\n} {\n const pendingRequests = new Map<string, Promise<RequestContext>>();\n\n const getKey = (context: RequestContext): string => {\n return `${context.init.method ?? 'GET'}:${context.url}`;\n };\n\n return {\n interceptor: (context) => {\n const key = getKey(context);\n const pending = pendingRequests.get(key);\n\n if (pending) {\n // 复用进行中的请求\n return pending;\n }\n\n // 标记请求进行中(实际不做去重,只是示例)\n // 真正的去重需要在 fetch 层面实现\n return context;\n },\n clear: () => {\n pendingRequests.clear();\n },\n };\n}\n\n/**\n * 创建请求缓存拦截器\n *\n * 缓存 GET 请求的响应\n */\nexport function createCacheInterceptor(options: {\n /** 缓存 TTL(毫秒) */\n ttlMs?: number;\n /** 判断是否应该缓存 */\n shouldCache?: (context: RequestContext) => boolean;\n /** 最大缓存条目数 */\n maxSize?: number;\n}): {\n requestInterceptor: RequestInterceptor;\n responseInterceptor: ResponseInterceptor;\n clear: () => void;\n} {\n const {\n ttlMs = 60000,\n shouldCache = (context) => context.init.method === 'GET' || !context.init.method,\n maxSize = 100,\n } = options;\n\n interface CacheEntry {\n response: Response;\n timestamp: number;\n }\n\n const cache = new Map<string, CacheEntry>();\n\n const getKey = (context: RequestContext): string => {\n return `${context.init.method ?? 'GET'}:${context.url}`;\n };\n\n const isExpired = (entry: CacheEntry): boolean => {\n return Date.now() - entry.timestamp > ttlMs;\n };\n\n const evictOldest = (): void => {\n if (cache.size >= maxSize) {\n const oldestKey = cache.keys().next().value;\n if (oldestKey) {\n cache.delete(oldestKey);\n }\n }\n };\n\n return {\n requestInterceptor: (context) => {\n if (!shouldCache(context)) {\n return context;\n }\n\n const key = getKey(context);\n const entry = cache.get(key);\n\n if (entry && !isExpired(entry)) {\n // 标记使用缓存(实际需要特殊处理)\n context.meta = { ...context.meta, fromCache: true, cachedResponse: entry.response.clone() };\n }\n\n return context;\n },\n responseInterceptor: (response, context) => {\n if (!shouldCache(context) || !response.ok) {\n return response;\n }\n\n const key = getKey(context);\n evictOldest();\n cache.set(key, {\n response: response.clone(),\n timestamp: Date.now(),\n });\n\n return response;\n },\n clear: () => {\n cache.clear();\n },\n };\n}\n","/**\n * @djvlc/openapi-client-core - 请求去重\n *\n * 避免相同的 GET 请求并发执行多次,复用进行中的请求。\n */\n\n/**\n * 请求去重器选项\n */\nexport interface DedupeOptions {\n /**\n * 生成请求唯一标识的函数\n *\n * 默认使用 `${method}:${url}`\n */\n keyGenerator?: (url: string, init?: RequestInit) => string;\n\n /**\n * 是否只对 GET 请求去重\n *\n * @default true\n */\n getOnly?: boolean;\n\n /**\n * 调试日志\n */\n onDedupe?: (key: string, pending: number) => void;\n}\n\n/**\n * 请求去重器\n *\n * @example\n * ```typescript\n * const deduper = createRequestDeduper();\n *\n * // 包装 fetch\n * const dedupedFetch = deduper.wrap(fetch);\n *\n * // 相同的请求只会执行一次\n * const [r1, r2] = await Promise.all([\n * dedupedFetch('/api/user'),\n * dedupedFetch('/api/user'),\n * ]);\n * ```\n */\nexport function createRequestDeduper(options: DedupeOptions = {}) {\n const {\n keyGenerator = defaultKeyGenerator,\n getOnly = true,\n onDedupe,\n } = options;\n\n // 进行中的请求映射\n const inflightRequests = new Map<string, Promise<Response>>();\n\n // 每个请求的等待者数量\n const pendingCounts = new Map<string, number>();\n\n function defaultKeyGenerator(url: string, init?: RequestInit): string {\n const method = (init?.method ?? 'GET').toUpperCase();\n\n // 非幂等请求不去重\n if (getOnly && method !== 'GET') {\n return `${method}:${url}:${Date.now()}:${Math.random()}`;\n }\n\n return `${method}:${url}`;\n }\n\n return {\n /**\n * 包装 fetch 函数,添加请求去重能力\n */\n wrap: (fetchFn: typeof fetch): typeof fetch => {\n return (async (\n input: RequestInfo | URL,\n init?: RequestInit\n ): Promise<Response> => {\n const url = typeof input === 'string'\n ? input\n : input instanceof URL\n ? input.href\n : input.url;\n\n const key = keyGenerator(url, init);\n\n // 检查是否有相同请求在进行中\n const inflight = inflightRequests.get(key);\n if (inflight) {\n // 增加等待者计数\n pendingCounts.set(key, (pendingCounts.get(key) ?? 1) + 1);\n onDedupe?.(key, pendingCounts.get(key)!);\n\n // 复用进行中的请求,返回克隆的响应\n return inflight.then((response) => response.clone());\n }\n\n // 发起新请求\n const promise = fetchFn(input, init)\n .then((response) => {\n // 保存响应供后续克隆\n return response;\n })\n .finally(() => {\n // 请求完成后清理\n inflightRequests.delete(key);\n pendingCounts.delete(key);\n });\n\n // 记录进行中的请求\n inflightRequests.set(key, promise);\n pendingCounts.set(key, 1);\n\n return promise;\n }) as typeof fetch;\n },\n\n /**\n * 获取当前进行中的请求数量\n */\n getPendingCount(): number {\n return inflightRequests.size;\n },\n\n /**\n * 获取所有进行中的请求 key\n */\n getPendingKeys(): string[] {\n return Array.from(inflightRequests.keys());\n },\n\n /**\n * 清除所有进行中的请求记录\n *\n * 注意:这不会取消请求,只是清除去重映射\n */\n clear(): void {\n inflightRequests.clear();\n pendingCounts.clear();\n },\n };\n}\n\n/**\n * 请求去重器类型\n */\nexport type RequestDeduper = ReturnType<typeof createRequestDeduper>;\n","/**\n * @djvlc/openapi-client-core - 指标收集\n *\n * 提供请求级别的指标收集能力,用于可观测性和性能监控。\n */\n\nimport type { Middleware, RequestContext, ResponseContext } from './types';\n\n/**\n * 请求指标\n */\nexport interface RequestMetrics {\n /** 请求 ID(唯一标识) */\n requestId: string;\n /** 请求 URL */\n url: string;\n /** 请求路径(不含 base URL 和 query) */\n path: string;\n /** HTTP 方法 */\n method: string;\n /** 请求开始时间戳(毫秒) */\n startTime: number;\n /** 请求结束时间戳(毫秒) */\n endTime: number;\n /** 请求耗时(毫秒) */\n durationMs: number;\n /** HTTP 状态码 */\n status: number;\n /** 是否成功(2xx) */\n success: boolean;\n /** 是否来自缓存 */\n fromCache?: boolean;\n /** 重试次数 */\n retryCount?: number;\n /** 请求体大小(字节) */\n requestSize?: number;\n /** 响应体大小(字节,如果可获取) */\n responseSize?: number;\n /** 错误信息(如果失败) */\n error?: string;\n /** 追踪 ID */\n traceId?: string;\n}\n\n/**\n * 指标摘要\n */\nexport interface MetricsSummary {\n /** 总请求数 */\n totalRequests: number;\n /** 成功请求数 */\n successCount: number;\n /** 失败请求数 */\n failureCount: number;\n /** 成功率 */\n successRate: number;\n /** 平均耗时(毫秒) */\n avgDurationMs: number;\n /** P50 耗时(毫秒) */\n p50Ms: number;\n /** P90 耗时(毫秒) */\n p90Ms: number;\n /** P95 耗时(毫秒) */\n p95Ms: number;\n /** P99 耗时(毫秒) */\n p99Ms: number;\n /** 最小耗时(毫秒) */\n minMs: number;\n /** 最大耗时(毫秒) */\n maxMs: number;\n /** 按状态码分组的计数 */\n statusCodeCounts: Record<number, number>;\n /** 按路径分组的计数 */\n pathCounts: Record<string, number>;\n /** 统计时间范围 */\n timeRange: {\n start: number;\n end: number;\n };\n}\n\n/**\n * 指标收集器选项\n */\nexport interface MetricsCollectorOptions {\n /** 最大保留的指标数量(避免内存泄漏) */\n maxMetrics?: number;\n /** 指标 TTL(毫秒,超过此时间的指标会被清理) */\n ttlMs?: number;\n /** 是否自动清理过期指标 */\n autoCleanup?: boolean;\n /** 清理间隔(毫秒) */\n cleanupIntervalMs?: number;\n /** 指标收集回调(每次请求完成时调用) */\n onMetrics?: (metrics: RequestMetrics) => void;\n}\n\n/**\n * 指标收集器\n */\nexport interface MetricsCollector {\n /** 收集指标 */\n collect(metrics: RequestMetrics): void;\n /** 获取所有指标 */\n getMetrics(): RequestMetrics[];\n /** 获取并清空所有指标 */\n flush(): RequestMetrics[];\n /** 获取指标摘要 */\n summary(): MetricsSummary;\n /** 按路径获取指标 */\n getByPath(path: string): RequestMetrics[];\n /** 按时间范围获取指标 */\n getByTimeRange(startTime: number, endTime: number): RequestMetrics[];\n /** 清除所有指标 */\n clear(): void;\n /** 销毁收集器(清理定时器等) */\n destroy(): void;\n}\n\n/**\n * 创建指标收集器\n *\n * @example\n * ```typescript\n * const metrics = createMetricsCollector({\n * maxMetrics: 1000,\n * onMetrics: (m) => console.log(`${m.method} ${m.path} - ${m.durationMs}ms`),\n * });\n *\n * // 使用 middleware 收集指标\n * const client = createClient({\n * middleware: [createMetricsMiddleware(metrics)],\n * });\n *\n * // 获取摘要\n * const summary = metrics.summary();\n * console.log(`成功率: ${(summary.successRate * 100).toFixed(1)}%`);\n * console.log(`P95: ${summary.p95Ms}ms`);\n * ```\n */\nexport function createMetricsCollector(\n options: MetricsCollectorOptions = {}\n): MetricsCollector {\n const {\n maxMetrics = 10000,\n ttlMs = 3600000, // 1 小时\n autoCleanup = true,\n cleanupIntervalMs = 60000, // 1 分钟\n onMetrics,\n } = options;\n\n const metricsStore: RequestMetrics[] = [];\n let cleanupTimer: ReturnType<typeof setInterval> | null = null;\n\n // 自动清理过期指标\n if (autoCleanup) {\n cleanupTimer = setInterval(() => {\n const now = Date.now();\n const cutoff = now - ttlMs;\n \n // 清理过期指标\n let i = 0;\n while (i < metricsStore.length && metricsStore[i].endTime < cutoff) {\n i++;\n }\n if (i > 0) {\n metricsStore.splice(0, i);\n }\n }, cleanupIntervalMs);\n }\n\n function collect(metrics: RequestMetrics): void {\n // 限制最大数量\n if (metricsStore.length >= maxMetrics) {\n metricsStore.shift();\n }\n \n metricsStore.push(metrics);\n onMetrics?.(metrics);\n }\n\n function getMetrics(): RequestMetrics[] {\n return [...metricsStore];\n }\n\n function flush(): RequestMetrics[] {\n const result = [...metricsStore];\n metricsStore.length = 0;\n return result;\n }\n\n function summary(): MetricsSummary {\n if (metricsStore.length === 0) {\n return {\n totalRequests: 0,\n successCount: 0,\n failureCount: 0,\n successRate: 0,\n avgDurationMs: 0,\n p50Ms: 0,\n p90Ms: 0,\n p95Ms: 0,\n p99Ms: 0,\n minMs: 0,\n maxMs: 0,\n statusCodeCounts: {},\n pathCounts: {},\n timeRange: { start: 0, end: 0 },\n };\n }\n\n const durations = metricsStore.map((m) => m.durationMs).sort((a, b) => a - b);\n const successCount = metricsStore.filter((m) => m.success).length;\n const failureCount = metricsStore.length - successCount;\n\n const statusCodeCounts: Record<number, number> = {};\n const pathCounts: Record<string, number> = {};\n\n for (const m of metricsStore) {\n statusCodeCounts[m.status] = (statusCodeCounts[m.status] ?? 0) + 1;\n pathCounts[m.path] = (pathCounts[m.path] ?? 0) + 1;\n }\n\n const getPercentile = (arr: number[], p: number): number => {\n const index = Math.floor(arr.length * p);\n return arr[Math.min(index, arr.length - 1)] ?? 0;\n };\n\n return {\n totalRequests: metricsStore.length,\n successCount,\n failureCount,\n successRate: successCount / metricsStore.length,\n avgDurationMs:\n durations.reduce((a, b) => a + b, 0) / durations.length,\n p50Ms: getPercentile(durations, 0.5),\n p90Ms: getPercentile(durations, 0.9),\n p95Ms: getPercentile(durations, 0.95),\n p99Ms: getPercentile(durations, 0.99),\n minMs: durations[0] ?? 0,\n maxMs: durations[durations.length - 1] ?? 0,\n statusCodeCounts,\n pathCounts,\n timeRange: {\n start: metricsStore[0]?.startTime ?? 0,\n end: metricsStore[metricsStore.length - 1]?.endTime ?? 0,\n },\n };\n }\n\n function getByPath(path: string): RequestMetrics[] {\n return metricsStore.filter((m) => m.path === path);\n }\n\n function getByTimeRange(startTime: number, endTime: number): RequestMetrics[] {\n return metricsStore.filter(\n (m) => m.startTime >= startTime && m.endTime <= endTime\n );\n }\n\n function clear(): void {\n metricsStore.length = 0;\n }\n\n function destroy(): void {\n if (cleanupTimer) {\n clearInterval(cleanupTimer);\n cleanupTimer = null;\n }\n clear();\n }\n\n return {\n collect,\n getMetrics,\n flush,\n summary,\n getByPath,\n getByTimeRange,\n clear,\n destroy,\n };\n}\n\n/**\n * 生成请求 ID\n */\nfunction generateRequestId(): string {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\n}\n\n/**\n * 从 URL 提取路径\n */\nfunction extractPath(url: string): string {\n try {\n const parsed = new URL(url);\n return parsed.pathname;\n } catch {\n // URL 可能是相对路径\n const match = url.match(/^[^?#]*/);\n return match?.[0] ?? url;\n }\n}\n\n/**\n * 创建指标收集 Middleware\n *\n * @example\n * ```typescript\n * const metrics = createMetricsCollector();\n * const middleware = createMetricsMiddleware(metrics);\n *\n * const client = createClient({\n * middleware: [middleware],\n * });\n * ```\n */\nexport function createMetricsMiddleware(collector: MetricsCollector): Middleware {\n const requestStarts = new Map<string, number>();\n\n return {\n pre(context: RequestContext): RequestContext {\n const requestId = generateRequestId();\n requestStarts.set(requestId, Date.now());\n \n return {\n ...context,\n meta: {\n ...context.meta,\n metricsRequestId: requestId,\n },\n };\n },\n\n post(context: ResponseContext): void {\n const requestId = context.meta?.metricsRequestId as string | undefined;\n if (!requestId) return;\n\n const startTime = requestStarts.get(requestId);\n if (!startTime) return;\n\n requestStarts.delete(requestId);\n const endTime = Date.now();\n\n const metrics: RequestMetrics = {\n requestId,\n url: context.url,\n path: extractPath(context.url),\n method: (context.init.method ?? 'GET').toUpperCase(),\n startTime,\n endTime,\n durationMs: endTime - startTime,\n status: context.response.status,\n success: context.response.ok,\n fromCache: context.meta?.fromCache as boolean | undefined,\n retryCount: context.meta?.retryCount as number | undefined,\n traceId: context.response.headers.get('x-request-id') ?? undefined,\n };\n\n // 尝试获取响应大小\n const contentLength = context.response.headers.get('content-length');\n if (contentLength) {\n metrics.responseSize = parseInt(contentLength, 10);\n }\n\n // 获取请求体大小\n if (context.init.body) {\n if (typeof context.init.body === 'string') {\n metrics.requestSize = new TextEncoder().encode(context.init.body).length;\n }\n }\n\n collector.collect(metrics);\n },\n };\n}\n","/**\n * @djvlc/openapi-client-core - 日志系统\n */\n\nimport type { Logger } from './types';\n\n/**\n * 创建控制台日志器\n */\nexport function createConsoleLogger(options: {\n /** 日志前缀 */\n prefix?: string;\n /** 是否启用 */\n enabled?: boolean;\n /** 日志级别:'debug' | 'info' | 'warn' | 'error' */\n level?: 'debug' | 'info' | 'warn' | 'error';\n /** 是否包含时间戳 */\n timestamp?: boolean;\n /** 是否包含请求体 */\n includeBody?: boolean;\n} = {}): Logger {\n const {\n prefix = '[DJV-API]',\n enabled = true,\n level = 'info',\n timestamp = true,\n includeBody = false,\n } = options;\n\n const levels = ['debug', 'info', 'warn', 'error'];\n const currentLevelIndex = levels.indexOf(level);\n\n const shouldLog = (logLevel: string): boolean => {\n return enabled && levels.indexOf(logLevel) >= currentLevelIndex;\n };\n\n const formatTime = (): string => {\n if (!timestamp) return '';\n return `[${new Date().toISOString()}] `;\n };\n\n const formatMethod = (init: RequestInit): string => {\n return init.method ?? 'GET';\n };\n\n return {\n request: (url, init) => {\n if (!shouldLog('debug')) return;\n\n const method = formatMethod(init);\n console.log(`${formatTime()}${prefix} -> ${method} ${url}`);\n\n if (includeBody && init.body) {\n try {\n const body = typeof init.body === 'string' ? JSON.parse(init.body) : init.body;\n console.log(`${prefix} Body:`, body);\n } catch {\n console.log(`${prefix} Body: [non-JSON]`);\n }\n }\n },\n\n response: (url, response, durationMs) => {\n if (!shouldLog('info')) return;\n\n const status = response.status;\n const statusEmoji = status >= 200 && status < 300 ? '✓' : '✗';\n\n console.log(\n `${formatTime()}${prefix} <- ${statusEmoji} ${status} ${url} (${durationMs}ms)`\n );\n },\n\n error: (url, error) => {\n if (!shouldLog('error')) return;\n\n console.error(`${formatTime()}${prefix} !! ${url}`, error);\n },\n\n retry: (url, attempt, error) => {\n if (!shouldLog('warn')) return;\n\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.warn(\n `${formatTime()}${prefix} ↻ Retry #${attempt} ${url} (${errorMessage})`\n );\n },\n };\n}\n\n/**\n * 创建静默日志器(不输出任何日志)\n */\nexport function createSilentLogger(): Logger {\n return {\n request: () => {},\n response: () => {},\n error: () => {},\n retry: () => {},\n };\n}\n\n/**\n * 创建自定义日志器\n *\n * 将日志发送到自定义目标(如监控系统)\n */\nexport function createCustomLogger(handlers: {\n onRequest?: (data: {\n url: string;\n method: string;\n headers?: Record<string, string>;\n timestamp: number;\n }) => void;\n onResponse?: (data: {\n url: string;\n status: number;\n durationMs: number;\n timestamp: number;\n }) => void;\n onError?: (data: {\n url: string;\n error: unknown;\n timestamp: number;\n }) => void;\n onRetry?: (data: {\n url: string;\n attempt: number;\n error: unknown;\n timestamp: number;\n }) => void;\n}): Logger {\n return {\n request: (url, init) => {\n handlers.onRequest?.({\n url,\n method: init.method ?? 'GET',\n timestamp: Date.now(),\n });\n },\n response: (url, response, durationMs) => {\n handlers.onResponse?.({\n url,\n status: response.status,\n durationMs,\n timestamp: Date.now(),\n });\n },\n error: (url, error) => {\n handlers.onError?.({\n url,\n error,\n timestamp: Date.now(),\n });\n },\n retry: (url, attempt, error) => {\n handlers.onRetry?.({\n url,\n attempt,\n error,\n timestamp: Date.now(),\n });\n },\n };\n}\n\n/**\n * 组合多个日志器\n */\nexport function combineLoggers(...loggers: Logger[]): Logger {\n return {\n request: (url, init) => {\n for (const logger of loggers) {\n logger.request?.(url, init);\n }\n },\n response: (url, response, durationMs) => {\n for (const logger of loggers) {\n logger.response?.(url, response, durationMs);\n }\n },\n error: (url, error) => {\n for (const logger of loggers) {\n logger.error?.(url, error);\n }\n },\n retry: (url, attempt, error) => {\n for (const logger of loggers) {\n logger.retry?.(url, attempt, error);\n }\n },\n };\n}\n","/**\n * @djvlc/openapi-client-core - Configuration 类\n *\n * 兼容 openapi-generator 生成的代码,同时提供增强能力。\n */\n\nimport type {\n Middleware,\n ConfigurationParameters,\n BaseClientOptions,\n SdkInfo,\n} from './types';\nimport { createEnhancedFetch } from './fetch';\nimport { createDefaultMiddlewares } from './middleware';\nimport { InterceptorManager } from './interceptors';\nimport { stripTrailingSlash } from './utils';\n\n/**\n * API 配置类\n *\n * 兼容 openapi-generator 的 Configuration,同时提供增强能力。\n */\nexport class Configuration {\n /** 基础路径 */\n basePath: string;\n\n /** fetch 实现 */\n fetchApi: typeof fetch;\n\n /** Middleware 列表 */\n middleware: Middleware[];\n\n /** Cookie 策略 */\n credentials?: RequestCredentials;\n\n /** 拦截器管理器 */\n interceptors: InterceptorManager;\n\n /** SDK 信息 */\n sdkInfo?: SdkInfo;\n\n constructor(params: ConfigurationParameters = {}) {\n this.basePath = params.basePath ?? '';\n this.fetchApi = params.fetchApi ?? fetch;\n this.middleware = params.middleware ?? [];\n this.credentials = params.credentials;\n this.interceptors = new InterceptorManager();\n }\n\n /**\n * 从 ClientOptions 创建 Configuration\n */\n static fromClientOptions(opts: BaseClientOptions, sdkInfo?: SdkInfo): Configuration {\n const config = new Configuration();\n\n config.basePath = stripTrailingSlash(opts.baseUrl);\n config.credentials = opts.credentials ?? 'omit';\n config.sdkInfo = sdkInfo;\n\n // 创建增强版 fetch\n config.fetchApi = createEnhancedFetch({\n fetchApi: opts.fetchApi,\n timeoutMs: opts.timeoutMs ?? 30000,\n retry: opts.retry,\n logger: opts.logger,\n });\n\n // 创建默认 Middleware\n config.middleware = [\n ...createDefaultMiddlewares(opts, sdkInfo),\n ...(opts.middleware ?? []),\n ];\n\n // 设置拦截器\n if (opts.interceptors) {\n config.interceptors = new InterceptorManager(opts.interceptors);\n }\n\n return config;\n }\n}\n\n/**\n * 创建兼容 openapi-generator 的 Configuration\n *\n * 这个函数用于快速创建一个简单的配置,兼容生成的 API 类。\n */\nexport function createConfiguration(\n opts: BaseClientOptions,\n sdkInfo?: SdkInfo\n): Configuration {\n return Configuration.fromClientOptions(opts, sdkInfo);\n}\n","/**\n * @djvlc/openapi-client-core - 客户端工厂\n *\n * 提供通用的客户端创建逻辑。\n */\n\nimport type { BaseClientOptions, SdkInfo } from './types';\nimport { Configuration } from './configuration';\n\n/**\n * API 类构造函数类型\n */\nexport type ApiConstructor<T> = new (configuration: Configuration) => T;\n\n/**\n * API 类映射\n */\nexport type ApiMap = Record<string, ApiConstructor<unknown>>;\n\n/**\n * 从 API 类映射提取实例类型\n */\nexport type ApiInstances<T extends ApiMap> = {\n [K in keyof T]: InstanceType<T[K]>;\n};\n\n/**\n * 创建客户端的通用工厂函数\n *\n * @example\n * ```typescript\n * import * as apis from './gen/apis';\n *\n * const client = createClient(apis, {\n * baseUrl: 'https://api.example.com',\n * getAuthToken: () => token,\n * }, { name: '@djvlc/openapi-user-client', version: '1.0.0' });\n * ```\n */\nexport function createClient<T extends ApiMap>(\n apiClasses: T,\n opts: BaseClientOptions,\n sdkInfo?: SdkInfo\n): {\n config: Configuration;\n apis: ApiInstances<T>;\n} & ApiInstances<T> {\n // 创建配置\n const config = Configuration.fromClientOptions(opts, sdkInfo);\n\n // 实例化所有 API 类\n const apiInstances = {} as ApiInstances<T>;\n\n for (const [name, ApiClass] of Object.entries(apiClasses)) {\n if (typeof ApiClass === 'function' && name.endsWith('Api')) {\n (apiInstances as Record<string, unknown>)[name] = new ApiClass(config);\n }\n }\n\n return {\n config,\n apis: apiInstances,\n ...apiInstances,\n };\n}\n\n/**\n * 过滤出 API 类(以 'Api' 结尾的构造函数)\n */\nexport function filterApiClasses<T extends Record<string, unknown>>(\n exports: T\n): Record<string, ApiConstructor<unknown>> {\n const result: Record<string, ApiConstructor<unknown>> = {};\n\n for (const [name, value] of Object.entries(exports)) {\n if (typeof value === 'function' && name.endsWith('Api')) {\n result[name] = value as ApiConstructor<unknown>;\n }\n }\n\n return result;\n}\n"],"mappings":"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","names":["exports"]}
|