@djvlc/openapi-client-core 1.2.0 → 1.2.2

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 CHANGED
@@ -11695,57 +11695,2194 @@ var require_follow_redirects = __commonJS({
11695
11695
  // src/index.ts
11696
11696
  var index_exports = {};
11697
11697
  __export(index_exports, {
11698
+ AbortError: () => AbortError,
11698
11699
  ApiError: () => ApiError,
11699
- HttpClient: () => HttpClient,
11700
+ ApiKeyAuthenticator: () => ApiKeyAuthenticator,
11701
+ AuthInterceptor: () => AuthInterceptor,
11702
+ BaseClient: () => BaseClient,
11703
+ BaseClientError: () => BaseClientError,
11704
+ BasicAuthenticator: () => BasicAuthenticator,
11705
+ BearerAuthenticator: () => BearerAuthenticator,
11706
+ BufferLogger: () => BufferLogger,
11707
+ ConsoleLogger: () => ConsoleLogger,
11708
+ CustomAuthenticator: () => CustomAuthenticator,
11709
+ DEFAULT_HEADERS: () => DEFAULT_HEADERS,
11710
+ DEFAULT_RETRY_CONFIG: () => DEFAULT_RETRY_CONFIG,
11711
+ DefaultMetricsCollector: () => DefaultMetricsCollector,
11712
+ ErrorTransformInterceptor: () => ErrorTransformInterceptor,
11713
+ FetchClient: () => FetchClient,
11714
+ InterceptorManager: () => InterceptorManager,
11715
+ LOG_LEVEL_PRIORITY: () => LOG_LEVEL_PRIORITY,
11716
+ LoggingInterceptor: () => LoggingInterceptor,
11717
+ MetricsErrorInterceptor: () => MetricsErrorInterceptor,
11718
+ MetricsRequestInterceptor: () => MetricsRequestInterceptor,
11719
+ MetricsResponseInterceptor: () => MetricsResponseInterceptor,
11700
11720
  NetworkError: () => NetworkError,
11721
+ NoAuthenticator: () => NoAuthenticator,
11722
+ ReportingInterceptor: () => ReportingInterceptor,
11723
+ RequestDeduper: () => RequestDeduper,
11724
+ RequestIdInterceptor: () => RequestIdInterceptor,
11725
+ RetryInterceptor: () => RetryInterceptor,
11726
+ SDK_NAME: () => SDK_NAME,
11727
+ SilentLogger: () => SilentLogger,
11701
11728
  TimeoutError: () => TimeoutError,
11729
+ TimeoutInterceptor: () => TimeoutInterceptor,
11730
+ TokenRefreshInterceptor: () => TokenRefreshInterceptor,
11731
+ TraceInterceptor: () => TraceInterceptor,
11702
11732
  VERSION: () => VERSION3,
11733
+ buildUrl: () => buildUrl,
11703
11734
  calculateRetryDelay: () => calculateRetryDelay,
11735
+ createApiKeyAuthenticator: () => createApiKeyAuthenticator,
11736
+ createAuthInterceptor: () => createAuthInterceptor,
11737
+ createAuthMiddleware: () => createAuthMiddleware,
11738
+ createAuthenticatorFromConfig: () => createAuthenticatorFromConfig,
11704
11739
  createAxiosInstance: () => createAxiosInstance,
11705
- createClient: () => createClient,
11740
+ createBasicAuthenticator: () => createBasicAuthenticator,
11741
+ createBearerAuthenticator: () => createBearerAuthenticator,
11742
+ createBufferLogger: () => createBufferLogger,
11743
+ createConsoleLogger: () => createConsoleLogger,
11744
+ createCustomAuthenticator: () => createCustomAuthenticator,
11745
+ createErrorTransformInterceptor: () => createErrorTransformInterceptor,
11746
+ createFetchClient: () => createFetchClient,
11747
+ createInterceptorManager: () => createInterceptorManager,
11748
+ createLoggingInterceptor: () => createLoggingInterceptor,
11749
+ createMetricsCollector: () => createMetricsCollector,
11750
+ createMetricsInterceptors: () => createMetricsInterceptors,
11751
+ createMiddlewares: () => createMiddlewares,
11752
+ createNoAuthenticator: () => createNoAuthenticator,
11753
+ createReportingInterceptor: () => createReportingInterceptor,
11754
+ createRequestDeduper: () => createRequestDeduper,
11755
+ createRequestIdInterceptor: () => createRequestIdInterceptor,
11756
+ createRetryInterceptor: () => createRetryInterceptor,
11757
+ createSilentLogger: () => createSilentLogger,
11758
+ createTimeoutInterceptor: () => createTimeoutInterceptor,
11759
+ createTokenRefreshInterceptor: () => createTokenRefreshInterceptor,
11760
+ createTraceInterceptor: () => createTraceInterceptor,
11761
+ createTrackingMiddleware: () => createTrackingMiddleware,
11762
+ extractPath: () => extractPath,
11763
+ extractResponseHeaders: () => extractResponseHeaders,
11706
11764
  generateRequestId: () => generateRequestId,
11707
- sleep: () => sleep
11765
+ generateTraceId: () => generateTraceId,
11766
+ getErrorType: () => getErrorType,
11767
+ getHeader: () => getHeader,
11768
+ getRecommendedRetryDelay: () => getRecommendedRetryDelay,
11769
+ getRetryDelay: () => getRetryDelay,
11770
+ getSdkInfo: () => getSdkInfo,
11771
+ hasContentType: () => hasContentType,
11772
+ isClientError: () => isClientError,
11773
+ isRetryableError: () => isRetryableError,
11774
+ isValidRequestId: () => isValidRequestId,
11775
+ isValidTraceId: () => isValidTraceId,
11776
+ joinPaths: () => joinPaths,
11777
+ mergeHeaders: () => mergeHeaders,
11778
+ noAuthenticator: () => noAuthenticator,
11779
+ parseQueryString: () => parseQueryString,
11780
+ parseRetryAfter: () => parseRetryAfter,
11781
+ removeHeader: () => removeHeader,
11782
+ setHeader: () => setHeader,
11783
+ silentLogger: () => silentLogger,
11784
+ sleep: () => sleep,
11785
+ sleepWithAbort: () => sleepWithAbort
11708
11786
  });
11709
11787
  module.exports = __toCommonJS(index_exports);
11710
11788
 
11711
- // src/errors.ts
11712
- var ApiError = class extends Error {
11713
- constructor(response, statusCode) {
11714
- super(response.message);
11715
- this.name = "ApiError";
11716
- this.code = response.code;
11717
- this.statusCode = statusCode;
11718
- this.details = response.details;
11719
- this.requestId = response.requestId;
11720
- this.traceId = response.traceId;
11721
- this.retryable = this.isRetryable(statusCode, response.code);
11722
- }
11723
- isRetryable(statusCode, code) {
11724
- if (statusCode >= 500 && statusCode < 600) {
11789
+ // src/types/retry.ts
11790
+ var DEFAULT_RETRY_CONFIG = {
11791
+ maxRetries: 3,
11792
+ initialDelayMs: 1e3,
11793
+ maxDelayMs: 3e4,
11794
+ backoffStrategy: "exponential",
11795
+ retryableStatusCodes: [429, 500, 502, 503, 504],
11796
+ retryOnNetworkError: true,
11797
+ retryOnTimeout: true,
11798
+ respectRetryAfter: true,
11799
+ jitterFactor: 0.1
11800
+ };
11801
+
11802
+ // src/types/logger.ts
11803
+ var LOG_LEVEL_PRIORITY = {
11804
+ debug: 0,
11805
+ info: 1,
11806
+ warn: 2,
11807
+ error: 3
11808
+ };
11809
+
11810
+ // src/errors/base-error.ts
11811
+ var BaseClientError = class extends Error {
11812
+ constructor(message) {
11813
+ super(message);
11814
+ this.name = this.constructor.name;
11815
+ this.timestamp = /* @__PURE__ */ new Date();
11816
+ Object.setPrototypeOf(this, new.target.prototype);
11817
+ if (Error.captureStackTrace) {
11818
+ Error.captureStackTrace(this, this.constructor);
11819
+ }
11820
+ }
11821
+ /**
11822
+ * 转换为 JSON 对象(用于日志和序列化)
11823
+ */
11824
+ toJSON() {
11825
+ return {
11826
+ name: this.name,
11827
+ type: this.type,
11828
+ message: this.message,
11829
+ retryable: this.retryable,
11830
+ timestamp: this.timestamp.toISOString(),
11831
+ stack: this.stack
11832
+ };
11833
+ }
11834
+ /**
11835
+ * 转换为字符串
11836
+ */
11837
+ toString() {
11838
+ return `${this.name}: ${this.message}`;
11839
+ }
11840
+ };
11841
+
11842
+ // src/errors/api-error.ts
11843
+ var ApiError = class _ApiError extends BaseClientError {
11844
+ constructor(config) {
11845
+ super(config.message);
11846
+ this.type = "API_ERROR";
11847
+ this.code = config.code;
11848
+ this.statusCode = config.statusCode;
11849
+ this.details = config.details;
11850
+ this.requestId = config.requestId;
11851
+ this.traceId = config.traceId;
11852
+ this.retryAfterSeconds = config.retryAfter;
11853
+ this.rawResponse = config.rawResponse;
11854
+ }
11855
+ /**
11856
+ * 是否可重试
11857
+ *
11858
+ * 5xx 和 429 错误通常可重试
11859
+ */
11860
+ get retryable() {
11861
+ if (this.statusCode === 429) {
11862
+ return true;
11863
+ }
11864
+ if (this.statusCode >= 500 && this.statusCode < 600 && this.statusCode !== 501) {
11865
+ return true;
11866
+ }
11867
+ return false;
11868
+ }
11869
+ // ============================================================
11870
+ // 状态码判断方法
11871
+ // ============================================================
11872
+ /**
11873
+ * 是否为未授权错误 (401)
11874
+ */
11875
+ isUnauthorized() {
11876
+ return this.statusCode === 401;
11877
+ }
11878
+ /**
11879
+ * 是否为禁止访问错误 (403)
11880
+ */
11881
+ isForbidden() {
11882
+ return this.statusCode === 403;
11883
+ }
11884
+ /**
11885
+ * 是否为认证相关错误 (401/403)
11886
+ */
11887
+ isAuthError() {
11888
+ return this.isUnauthorized() || this.isForbidden();
11889
+ }
11890
+ /**
11891
+ * 是否为未找到错误 (404)
11892
+ */
11893
+ isNotFound() {
11894
+ return this.statusCode === 404;
11895
+ }
11896
+ /**
11897
+ * 是否为冲突错误 (409)
11898
+ */
11899
+ isConflict() {
11900
+ return this.statusCode === 409;
11901
+ }
11902
+ /**
11903
+ * 是否为验证错误 (400/422)
11904
+ */
11905
+ isValidationError() {
11906
+ return this.statusCode === 400 || this.statusCode === 422;
11907
+ }
11908
+ /**
11909
+ * 是否为限流错误 (429)
11910
+ */
11911
+ isRateLimited() {
11912
+ return this.statusCode === 429;
11913
+ }
11914
+ /**
11915
+ * 是否为客户端错误 (4xx)
11916
+ */
11917
+ isClientError() {
11918
+ return this.statusCode >= 400 && this.statusCode < 500;
11919
+ }
11920
+ /**
11921
+ * 是否为服务端错误 (5xx)
11922
+ */
11923
+ isServerError() {
11924
+ return this.statusCode >= 500 && this.statusCode < 600;
11925
+ }
11926
+ // ============================================================
11927
+ // 重试相关方法
11928
+ // ============================================================
11929
+ /**
11930
+ * 获取 Retry-After 值(秒)
11931
+ */
11932
+ getRetryAfter() {
11933
+ return this.retryAfterSeconds;
11934
+ }
11935
+ /**
11936
+ * 获取推荐的重试延迟(毫秒)
11937
+ *
11938
+ * @param defaultMs - 默认延迟(毫秒)
11939
+ */
11940
+ getRetryDelayMs(defaultMs = 1e3) {
11941
+ if (this.retryAfterSeconds !== void 0) {
11942
+ return this.retryAfterSeconds * 1e3;
11943
+ }
11944
+ return defaultMs;
11945
+ }
11946
+ // ============================================================
11947
+ // 序列化
11948
+ // ============================================================
11949
+ toJSON() {
11950
+ return {
11951
+ ...super.toJSON(),
11952
+ code: this.code,
11953
+ statusCode: this.statusCode,
11954
+ details: this.details,
11955
+ requestId: this.requestId,
11956
+ traceId: this.traceId,
11957
+ retryAfterSeconds: this.retryAfterSeconds
11958
+ };
11959
+ }
11960
+ // ============================================================
11961
+ // 静态方法
11962
+ // ============================================================
11963
+ /**
11964
+ * 类型守卫:判断是否为 ApiError
11965
+ */
11966
+ static is(error) {
11967
+ return error instanceof _ApiError;
11968
+ }
11969
+ /**
11970
+ * 从响应数据创建 ApiError
11971
+ */
11972
+ static fromResponse(data, statusCode, retryAfter) {
11973
+ return new _ApiError({
11974
+ message: data.message ?? `HTTP Error ${statusCode}`,
11975
+ code: data.code ?? `HTTP_${statusCode}`,
11976
+ statusCode,
11977
+ details: data.details,
11978
+ requestId: data.requestId ?? "unknown",
11979
+ traceId: data.traceId,
11980
+ retryAfter,
11981
+ rawResponse: data
11982
+ });
11983
+ }
11984
+ };
11985
+
11986
+ // src/errors/network-error.ts
11987
+ var NetworkError = class _NetworkError extends BaseClientError {
11988
+ constructor(message, cause) {
11989
+ super(message);
11990
+ this.type = "NETWORK_ERROR";
11991
+ this.retryable = true;
11992
+ this.cause = cause;
11993
+ }
11994
+ toJSON() {
11995
+ return {
11996
+ ...super.toJSON(),
11997
+ cause: this.cause ? {
11998
+ name: this.cause.name,
11999
+ message: this.cause.message
12000
+ } : void 0
12001
+ };
12002
+ }
12003
+ /**
12004
+ * 类型守卫:判断是否为 NetworkError
12005
+ */
12006
+ static is(error) {
12007
+ return error instanceof _NetworkError;
12008
+ }
12009
+ /**
12010
+ * 从原生 fetch 错误创建 NetworkError
12011
+ */
12012
+ static fromFetchError(error) {
12013
+ const message = error.message.toLowerCase();
12014
+ if (message.includes("network") || message.includes("failed to fetch")) {
12015
+ return new _NetworkError("Network request failed", error);
12016
+ }
12017
+ if (message.includes("dns") || message.includes("getaddrinfo")) {
12018
+ return new _NetworkError("DNS resolution failed", error);
12019
+ }
12020
+ if (message.includes("connection refused") || message.includes("econnrefused")) {
12021
+ return new _NetworkError("Connection refused", error);
12022
+ }
12023
+ if (message.includes("connection reset") || message.includes("econnreset")) {
12024
+ return new _NetworkError("Connection reset", error);
12025
+ }
12026
+ if (message.includes("ssl") || message.includes("certificate")) {
12027
+ return new _NetworkError("SSL/TLS error", error);
12028
+ }
12029
+ return new _NetworkError(error.message || "Unknown network error", error);
12030
+ }
12031
+ };
12032
+
12033
+ // src/errors/timeout-error.ts
12034
+ var TimeoutError = class _TimeoutError extends BaseClientError {
12035
+ constructor(timeoutMs) {
12036
+ super(`Request timeout after ${timeoutMs}ms`);
12037
+ this.type = "TIMEOUT_ERROR";
12038
+ this.retryable = true;
12039
+ this.timeoutMs = timeoutMs;
12040
+ }
12041
+ toJSON() {
12042
+ return {
12043
+ ...super.toJSON(),
12044
+ timeoutMs: this.timeoutMs
12045
+ };
12046
+ }
12047
+ /**
12048
+ * 类型守卫:判断是否为 TimeoutError
12049
+ */
12050
+ static is(error) {
12051
+ return error instanceof _TimeoutError;
12052
+ }
12053
+ };
12054
+
12055
+ // src/errors/abort-error.ts
12056
+ var AbortError = class _AbortError extends BaseClientError {
12057
+ constructor(reason) {
12058
+ super(reason ?? "Request was aborted");
12059
+ this.type = "ABORT_ERROR";
12060
+ this.retryable = false;
12061
+ this.reason = reason;
12062
+ }
12063
+ toJSON() {
12064
+ return {
12065
+ ...super.toJSON(),
12066
+ reason: this.reason
12067
+ };
12068
+ }
12069
+ /**
12070
+ * 类型守卫:判断是否为 AbortError
12071
+ */
12072
+ static is(error) {
12073
+ return error instanceof _AbortError;
12074
+ }
12075
+ /**
12076
+ * 从原生 AbortError 创建
12077
+ */
12078
+ static fromNative(error) {
12079
+ return new _AbortError(error.message);
12080
+ }
12081
+ };
12082
+
12083
+ // src/errors/index.ts
12084
+ function isRetryableError(error) {
12085
+ if (error instanceof ApiError || error instanceof NetworkError || error instanceof TimeoutError) {
12086
+ return error.retryable;
12087
+ }
12088
+ if (error instanceof AbortError) {
12089
+ return false;
12090
+ }
12091
+ return false;
12092
+ }
12093
+ function getRetryDelay(error, defaultMs = 1e3) {
12094
+ if (error instanceof ApiError) {
12095
+ return error.getRetryDelayMs(defaultMs);
12096
+ }
12097
+ return defaultMs;
12098
+ }
12099
+ function isClientError(error) {
12100
+ return error instanceof ApiError || error instanceof NetworkError || error instanceof TimeoutError || error instanceof AbortError;
12101
+ }
12102
+ function getErrorType(error) {
12103
+ if (error instanceof ApiError) {
12104
+ return error.type;
12105
+ }
12106
+ if (error instanceof NetworkError) {
12107
+ return error.type;
12108
+ }
12109
+ if (error instanceof TimeoutError) {
12110
+ return error.type;
12111
+ }
12112
+ if (error instanceof AbortError) {
12113
+ return error.type;
12114
+ }
12115
+ if (error instanceof Error) {
12116
+ return error.name;
12117
+ }
12118
+ return "UNKNOWN_ERROR";
12119
+ }
12120
+
12121
+ // src/auth/bearer-authenticator.ts
12122
+ var BearerAuthenticator = class {
12123
+ constructor(config) {
12124
+ this.type = "bearer";
12125
+ this.getToken = config.getToken;
12126
+ this.headerName = config.headerName ?? "Authorization";
12127
+ this.prefix = config.prefix ?? "Bearer";
12128
+ }
12129
+ async authenticate(headers) {
12130
+ const token = await this.getToken();
12131
+ if (token !== null && token !== "") {
12132
+ headers[this.headerName] = `${this.prefix} ${token}`;
12133
+ }
12134
+ }
12135
+ };
12136
+ function createBearerAuthenticator(config) {
12137
+ return new BearerAuthenticator(config);
12138
+ }
12139
+
12140
+ // src/auth/api-key-authenticator.ts
12141
+ var ApiKeyAuthenticator = class {
12142
+ constructor(config) {
12143
+ this.type = "api-key";
12144
+ this.apiKey = config.apiKey;
12145
+ this.headerName = config.headerName ?? "X-API-Key";
12146
+ }
12147
+ authenticate(headers) {
12148
+ headers[this.headerName] = this.apiKey;
12149
+ }
12150
+ };
12151
+ function createApiKeyAuthenticator(config) {
12152
+ return new ApiKeyAuthenticator(config);
12153
+ }
12154
+
12155
+ // src/auth/basic-authenticator.ts
12156
+ function encodeBase64(str) {
12157
+ if (typeof btoa !== "undefined") {
12158
+ const utf8Bytes = new TextEncoder().encode(str);
12159
+ const binaryString = Array.from(utf8Bytes, (byte) => String.fromCharCode(byte)).join("");
12160
+ return btoa(binaryString);
12161
+ }
12162
+ if (typeof Buffer !== "undefined") {
12163
+ return Buffer.from(str, "utf-8").toString("base64");
12164
+ }
12165
+ throw new Error("Base64 encoding is not supported in this environment");
12166
+ }
12167
+ var BasicAuthenticator = class {
12168
+ constructor(config) {
12169
+ this.type = "basic";
12170
+ this.encodedCredentials = encodeBase64(`${config.username}:${config.password}`);
12171
+ }
12172
+ authenticate(headers) {
12173
+ headers["Authorization"] = `Basic ${this.encodedCredentials}`;
12174
+ }
12175
+ };
12176
+ function createBasicAuthenticator(config) {
12177
+ return new BasicAuthenticator(config);
12178
+ }
12179
+
12180
+ // src/auth/custom-authenticator.ts
12181
+ var CustomAuthenticator = class {
12182
+ constructor(config) {
12183
+ this.type = "custom";
12184
+ this.authenticateFn = config.authenticate;
12185
+ }
12186
+ async authenticate(headers) {
12187
+ await this.authenticateFn(headers);
12188
+ }
12189
+ };
12190
+ function createCustomAuthenticator(config) {
12191
+ return new CustomAuthenticator(config);
12192
+ }
12193
+
12194
+ // src/auth/no-authenticator.ts
12195
+ var NoAuthenticator = class {
12196
+ constructor() {
12197
+ this.type = "none";
12198
+ }
12199
+ authenticate(_headers) {
12200
+ }
12201
+ };
12202
+ function createNoAuthenticator() {
12203
+ return new NoAuthenticator();
12204
+ }
12205
+ var noAuthenticator = new NoAuthenticator();
12206
+
12207
+ // src/auth/index.ts
12208
+ function createAuthenticatorFromConfig(config) {
12209
+ switch (config.type) {
12210
+ case "bearer":
12211
+ return new BearerAuthenticator({ getToken: config.getToken, headerName: config.headerName, prefix: config.prefix });
12212
+ case "api-key":
12213
+ return new ApiKeyAuthenticator({ apiKey: config.apiKey, headerName: config.headerName });
12214
+ case "basic":
12215
+ return new BasicAuthenticator({ username: config.username, password: config.password });
12216
+ case "custom":
12217
+ return new CustomAuthenticator({ authenticate: config.authenticate });
12218
+ case "none":
12219
+ return noAuthenticator;
12220
+ default: {
12221
+ const _exhaustiveCheck = config;
12222
+ throw new Error(`Unknown auth type: ${_exhaustiveCheck.type}`);
12223
+ }
12224
+ }
12225
+ }
12226
+
12227
+ // src/interceptors/manager.ts
12228
+ var InterceptorManager = class {
12229
+ constructor() {
12230
+ this.requestInterceptors = [];
12231
+ this.responseInterceptors = [];
12232
+ this.errorInterceptors = [];
12233
+ }
12234
+ /**
12235
+ * 获取所有拦截器
12236
+ */
12237
+ get interceptors() {
12238
+ return {
12239
+ request: [...this.requestInterceptors],
12240
+ response: [...this.responseInterceptors],
12241
+ error: [...this.errorInterceptors]
12242
+ };
12243
+ }
12244
+ // ============================================================
12245
+ // 注册方法
12246
+ // ============================================================
12247
+ /**
12248
+ * 添加请求拦截器
12249
+ *
12250
+ * @param interceptor - 请求拦截器
12251
+ * @returns 返回自身,支持链式调用
12252
+ */
12253
+ addRequestInterceptor(interceptor) {
12254
+ this.requestInterceptors.push(interceptor);
12255
+ this.sortInterceptors(this.requestInterceptors);
12256
+ return this;
12257
+ }
12258
+ /**
12259
+ * 添加响应拦截器
12260
+ *
12261
+ * @param interceptor - 响应拦截器
12262
+ * @returns 返回自身,支持链式调用
12263
+ */
12264
+ addResponseInterceptor(interceptor) {
12265
+ this.responseInterceptors.push(interceptor);
12266
+ this.sortInterceptors(this.responseInterceptors);
12267
+ return this;
12268
+ }
12269
+ /**
12270
+ * 添加错误拦截器
12271
+ *
12272
+ * @param interceptor - 错误拦截器
12273
+ * @returns 返回自身,支持链式调用
12274
+ */
12275
+ addErrorInterceptor(interceptor) {
12276
+ this.errorInterceptors.push(interceptor);
12277
+ this.sortInterceptors(this.errorInterceptors);
12278
+ return this;
12279
+ }
12280
+ /**
12281
+ * 批量添加拦截器
12282
+ *
12283
+ * @param interceptors - 拦截器配置
12284
+ * @returns 返回自身,支持链式调用
12285
+ */
12286
+ addInterceptors(interceptors) {
12287
+ if (interceptors.request) {
12288
+ for (const i of interceptors.request) {
12289
+ this.addRequestInterceptor(i);
12290
+ }
12291
+ }
12292
+ if (interceptors.response) {
12293
+ for (const i of interceptors.response) {
12294
+ this.addResponseInterceptor(i);
12295
+ }
12296
+ }
12297
+ if (interceptors.error) {
12298
+ for (const i of interceptors.error) {
12299
+ this.addErrorInterceptor(i);
12300
+ }
12301
+ }
12302
+ return this;
12303
+ }
12304
+ // ============================================================
12305
+ // 移除方法
12306
+ // ============================================================
12307
+ /**
12308
+ * 移除请求拦截器
12309
+ *
12310
+ * @param name - 拦截器名称
12311
+ * @returns 是否移除成功
12312
+ */
12313
+ removeRequestInterceptor(name) {
12314
+ return this.removeByName(this.requestInterceptors, name);
12315
+ }
12316
+ /**
12317
+ * 移除响应拦截器
12318
+ *
12319
+ * @param name - 拦截器名称
12320
+ * @returns 是否移除成功
12321
+ */
12322
+ removeResponseInterceptor(name) {
12323
+ return this.removeByName(this.responseInterceptors, name);
12324
+ }
12325
+ /**
12326
+ * 移除错误拦截器
12327
+ *
12328
+ * @param name - 拦截器名称
12329
+ * @returns 是否移除成功
12330
+ */
12331
+ removeErrorInterceptor(name) {
12332
+ return this.removeByName(this.errorInterceptors, name);
12333
+ }
12334
+ /**
12335
+ * 清除所有拦截器
12336
+ */
12337
+ clear() {
12338
+ this.requestInterceptors.length = 0;
12339
+ this.responseInterceptors.length = 0;
12340
+ this.errorInterceptors.length = 0;
12341
+ }
12342
+ // ============================================================
12343
+ // 执行方法
12344
+ // ============================================================
12345
+ /**
12346
+ * 执行请求拦截器链
12347
+ *
12348
+ * @param context - 请求上下文
12349
+ * @returns 修改后的请求选项
12350
+ */
12351
+ async executeRequestInterceptors(context) {
12352
+ let options = context.options;
12353
+ for (const interceptor of this.requestInterceptors) {
12354
+ options = await interceptor.intercept({
12355
+ ...context,
12356
+ options
12357
+ });
12358
+ }
12359
+ return options;
12360
+ }
12361
+ /**
12362
+ * 执行响应拦截器链
12363
+ *
12364
+ * @param response - 响应数据
12365
+ * @param context - 请求上下文
12366
+ * @returns 修改后的响应数据
12367
+ */
12368
+ async executeResponseInterceptors(response, context) {
12369
+ let result = response;
12370
+ for (const interceptor of this.responseInterceptors) {
12371
+ result = await interceptor.intercept(result, context);
12372
+ }
12373
+ return result;
12374
+ }
12375
+ /**
12376
+ * 执行错误拦截器链
12377
+ *
12378
+ * @param error - 错误对象
12379
+ * @param context - 请求上下文
12380
+ * @returns 如果返回 ResponseData,则表示错误被恢复;否则错误继续传播
12381
+ * @throws 如果拦截器抛出新错误,则使用新错误
12382
+ */
12383
+ async executeErrorInterceptors(error, context) {
12384
+ for (const interceptor of this.errorInterceptors) {
12385
+ const result = await interceptor.intercept(error, context);
12386
+ if (result !== void 0) {
12387
+ return result;
12388
+ }
12389
+ }
12390
+ return void 0;
12391
+ }
12392
+ // ============================================================
12393
+ // 私有方法
12394
+ // ============================================================
12395
+ /**
12396
+ * 按 order 排序拦截器
12397
+ */
12398
+ sortInterceptors(interceptors) {
12399
+ interceptors.sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
12400
+ }
12401
+ /**
12402
+ * 按名称移除拦截器
12403
+ */
12404
+ removeByName(interceptors, name) {
12405
+ const index = interceptors.findIndex((i) => i.name === name);
12406
+ if (index !== -1) {
12407
+ interceptors.splice(index, 1);
11725
12408
  return true;
11726
12409
  }
11727
- if (statusCode === 429) {
11728
- return true;
12410
+ return false;
12411
+ }
12412
+ };
12413
+ function createInterceptorManager() {
12414
+ return new InterceptorManager();
12415
+ }
12416
+
12417
+ // src/interceptors/request/auth.interceptor.ts
12418
+ var AuthInterceptor = class {
12419
+ constructor(config) {
12420
+ this.name = "auth";
12421
+ this.authenticator = config.authenticator;
12422
+ this.order = config.order ?? -100;
12423
+ }
12424
+ async intercept(context) {
12425
+ const { options } = context;
12426
+ if (options.skipAuth) {
12427
+ return options;
12428
+ }
12429
+ await this.authenticator.authenticate(options.headers);
12430
+ return options;
12431
+ }
12432
+ };
12433
+ function createAuthInterceptor(config) {
12434
+ return new AuthInterceptor(config);
12435
+ }
12436
+
12437
+ // src/utils/request-id.ts
12438
+ function generateRequestId() {
12439
+ const timestamp = Date.now().toString(36);
12440
+ const random = Math.random().toString(36).slice(2, 9);
12441
+ return `req_${timestamp}_${random}`;
12442
+ }
12443
+ function generateTraceId() {
12444
+ const timestamp = Date.now().toString(36);
12445
+ const random1 = Math.random().toString(36).slice(2, 9);
12446
+ const random2 = Math.random().toString(36).slice(2, 9);
12447
+ return `trace_${timestamp}_${random1}_${random2}`;
12448
+ }
12449
+ function isValidRequestId(id) {
12450
+ return /^req_[a-z0-9]+_[a-z0-9]+$/.test(id);
12451
+ }
12452
+ function isValidTraceId(id) {
12453
+ return /^trace_[a-z0-9]+_[a-z0-9]+_[a-z0-9]+$/.test(id);
12454
+ }
12455
+
12456
+ // src/interceptors/request/request-id.interceptor.ts
12457
+ var RequestIdInterceptor = class {
12458
+ constructor(config = {}) {
12459
+ this.name = "request-id";
12460
+ this.headerName = config.headerName ?? "X-Request-ID";
12461
+ this.generateId = config.generateId ?? generateRequestId;
12462
+ this.order = config.order ?? -90;
12463
+ }
12464
+ intercept(context) {
12465
+ const { options } = context;
12466
+ if (!options.headers[this.headerName]) {
12467
+ options.headers[this.headerName] = context.requestId;
12468
+ }
12469
+ return options;
12470
+ }
12471
+ };
12472
+ function createRequestIdInterceptor(config) {
12473
+ return new RequestIdInterceptor(config);
12474
+ }
12475
+
12476
+ // src/interceptors/request/trace.interceptor.ts
12477
+ var TraceInterceptor = class {
12478
+ constructor(config = {}) {
12479
+ this.name = "trace";
12480
+ this.traceIdHeader = config.traceIdHeader ?? "X-Trace-ID";
12481
+ this.addTraceparent = config.addTraceparent ?? false;
12482
+ this.getTraceId = config.getTraceId;
12483
+ this.getTraceparent = config.getTraceparent;
12484
+ this.order = config.order ?? -80;
12485
+ }
12486
+ intercept(context) {
12487
+ const { options } = context;
12488
+ if (!options.headers[this.traceIdHeader]) {
12489
+ const traceId = this.getTraceId?.() ?? context.traceId ?? generateTraceId();
12490
+ options.headers[this.traceIdHeader] = traceId;
12491
+ }
12492
+ if (this.addTraceparent && this.getTraceparent) {
12493
+ const traceparent = this.getTraceparent();
12494
+ if (traceparent && !options.headers["traceparent"]) {
12495
+ options.headers["traceparent"] = traceparent;
12496
+ }
12497
+ }
12498
+ return options;
12499
+ }
12500
+ };
12501
+ function createTraceInterceptor(config) {
12502
+ return new TraceInterceptor(config);
12503
+ }
12504
+
12505
+ // src/interceptors/request/timeout.interceptor.ts
12506
+ var TimeoutInterceptor = class {
12507
+ constructor(config = {}) {
12508
+ this.name = "timeout";
12509
+ this.defaultTimeout = config.defaultTimeout ?? 3e4;
12510
+ this.methodTimeouts = config.methodTimeouts ?? {};
12511
+ this.pathTimeouts = config.pathTimeouts ?? [];
12512
+ this.order = config.order ?? -70;
12513
+ }
12514
+ intercept(context) {
12515
+ const { options } = context;
12516
+ if (options.timeout !== void 0) {
12517
+ return options;
12518
+ }
12519
+ for (const { pattern, timeout } of this.pathTimeouts) {
12520
+ if (pattern.test(options.path)) {
12521
+ options.timeout = timeout;
12522
+ return options;
12523
+ }
12524
+ }
12525
+ const methodTimeout = this.methodTimeouts[options.method];
12526
+ if (methodTimeout !== void 0) {
12527
+ options.timeout = methodTimeout;
12528
+ return options;
12529
+ }
12530
+ options.timeout = this.defaultTimeout;
12531
+ return options;
12532
+ }
12533
+ };
12534
+ function createTimeoutInterceptor(config) {
12535
+ return new TimeoutInterceptor(config);
12536
+ }
12537
+
12538
+ // src/utils/retry-delay.ts
12539
+ function calculateRetryDelay(config, attempt) {
12540
+ const baseDelay = calculateBaseDelay(config.backoffStrategy, config.initialDelayMs, attempt);
12541
+ const jitterFactor = config.jitterFactor ?? 0.1;
12542
+ const delayWithJitter = addJitter(baseDelay, jitterFactor);
12543
+ return Math.min(delayWithJitter, config.maxDelayMs);
12544
+ }
12545
+ function calculateBaseDelay(strategy, initialDelayMs, attempt) {
12546
+ switch (strategy) {
12547
+ case "fixed":
12548
+ return initialDelayMs;
12549
+ case "linear":
12550
+ return initialDelayMs * (attempt + 1);
12551
+ case "exponential":
12552
+ return initialDelayMs * Math.pow(2, attempt);
12553
+ default: {
12554
+ const _exhaustiveCheck = strategy;
12555
+ throw new Error(`Unknown backoff strategy: ${_exhaustiveCheck}`);
12556
+ }
12557
+ }
12558
+ }
12559
+ function addJitter(delay, factor) {
12560
+ const validFactor = Math.max(0, Math.min(1, factor));
12561
+ const jitterRange = delay * validFactor;
12562
+ const jitter = (Math.random() - 0.5) * 2 * jitterRange;
12563
+ return Math.max(0, delay + jitter);
12564
+ }
12565
+ function parseRetryAfter(retryAfter) {
12566
+ if (!retryAfter) {
12567
+ return void 0;
12568
+ }
12569
+ const seconds = parseInt(retryAfter, 10);
12570
+ if (!isNaN(seconds) && seconds >= 0) {
12571
+ return seconds;
12572
+ }
12573
+ const date = new Date(retryAfter);
12574
+ if (!isNaN(date.getTime())) {
12575
+ const delayMs = date.getTime() - Date.now();
12576
+ return Math.max(0, Math.ceil(delayMs / 1e3));
12577
+ }
12578
+ return void 0;
12579
+ }
12580
+ function getRecommendedRetryDelay(config, attempt, retryAfterSeconds) {
12581
+ if (config.respectRetryAfter !== false && retryAfterSeconds !== void 0) {
12582
+ const retryAfterMs = retryAfterSeconds * 1e3;
12583
+ return Math.min(retryAfterMs, config.maxDelayMs);
12584
+ }
12585
+ return calculateRetryDelay(config, attempt);
12586
+ }
12587
+
12588
+ // src/utils/sleep.ts
12589
+ function sleep(ms) {
12590
+ return new Promise((resolve) => setTimeout(resolve, ms));
12591
+ }
12592
+ function sleepWithAbort(ms, signal) {
12593
+ return new Promise((resolve, reject) => {
12594
+ if (signal?.aborted) {
12595
+ reject(new DOMException("Aborted", "AbortError"));
12596
+ return;
12597
+ }
12598
+ const timeoutId = setTimeout(() => {
12599
+ resolve();
12600
+ }, ms);
12601
+ if (signal) {
12602
+ const abortHandler = () => {
12603
+ clearTimeout(timeoutId);
12604
+ reject(new DOMException("Aborted", "AbortError"));
12605
+ };
12606
+ signal.addEventListener("abort", abortHandler, { once: true });
12607
+ }
12608
+ });
12609
+ }
12610
+
12611
+ // src/interceptors/response/retry.interceptor.ts
12612
+ var RetryInterceptor = class {
12613
+ constructor(config) {
12614
+ this.name = "retry";
12615
+ this.config = {
12616
+ ...DEFAULT_RETRY_CONFIG,
12617
+ maxRetries: config.maxRetries ?? DEFAULT_RETRY_CONFIG.maxRetries,
12618
+ initialDelayMs: config.initialDelayMs ?? DEFAULT_RETRY_CONFIG.initialDelayMs,
12619
+ maxDelayMs: config.maxDelayMs ?? DEFAULT_RETRY_CONFIG.maxDelayMs,
12620
+ backoffStrategy: config.backoffStrategy ?? DEFAULT_RETRY_CONFIG.backoffStrategy,
12621
+ retryableStatusCodes: config.retryableStatusCodes ?? DEFAULT_RETRY_CONFIG.retryableStatusCodes,
12622
+ retryOnNetworkError: config.retryOnNetworkError ?? DEFAULT_RETRY_CONFIG.retryOnNetworkError,
12623
+ retryOnTimeout: config.retryOnTimeout ?? DEFAULT_RETRY_CONFIG.retryOnTimeout,
12624
+ respectRetryAfter: config.respectRetryAfter ?? DEFAULT_RETRY_CONFIG.respectRetryAfter,
12625
+ jitterFactor: config.jitterFactor ?? DEFAULT_RETRY_CONFIG.jitterFactor,
12626
+ onRetry: config.onRetry,
12627
+ shouldRetry: config.shouldRetry
12628
+ };
12629
+ this.executeRequest = config.executeRequest;
12630
+ this.order = config.order ?? 100;
12631
+ }
12632
+ async intercept(error, context) {
12633
+ if (!this.shouldRetry(error, context)) {
12634
+ return void 0;
12635
+ }
12636
+ const retryAfterSeconds = error instanceof ApiError ? error.getRetryAfter() : void 0;
12637
+ const delayMs = getRecommendedRetryDelay(this.config, context.retryCount, retryAfterSeconds);
12638
+ if (this.config.onRetry) {
12639
+ const retryInfo = {
12640
+ attempt: context.retryCount + 1,
12641
+ maxRetries: this.config.maxRetries,
12642
+ delayMs,
12643
+ error,
12644
+ url: context.url,
12645
+ method: context.options.method
12646
+ };
12647
+ this.config.onRetry(retryInfo);
12648
+ }
12649
+ await sleep(delayMs);
12650
+ context.retryCount++;
12651
+ return this.executeRequest(context);
12652
+ }
12653
+ /**
12654
+ * 判断是否应该重试
12655
+ */
12656
+ shouldRetry(error, context) {
12657
+ if (context.retryCount >= this.config.maxRetries) {
12658
+ return false;
12659
+ }
12660
+ if (error instanceof AbortError) {
12661
+ return false;
12662
+ }
12663
+ if (this.config.shouldRetry) {
12664
+ const statusCode = error instanceof ApiError ? error.statusCode : void 0;
12665
+ const retryAfter = error instanceof ApiError ? error.getRetryAfter() : void 0;
12666
+ return this.config.shouldRetry(error, context.retryCount, {
12667
+ url: context.url,
12668
+ method: context.options.method,
12669
+ statusCode,
12670
+ retryAfter
12671
+ });
12672
+ }
12673
+ if (error instanceof NetworkError) {
12674
+ return this.config.retryOnNetworkError !== false;
12675
+ }
12676
+ if (error instanceof TimeoutError) {
12677
+ return this.config.retryOnTimeout !== false;
12678
+ }
12679
+ if (error instanceof ApiError) {
12680
+ const retryableCodes = this.config.retryableStatusCodes ?? [];
12681
+ return retryableCodes.includes(error.statusCode);
12682
+ }
12683
+ return false;
12684
+ }
12685
+ };
12686
+ function createRetryInterceptor(config) {
12687
+ return new RetryInterceptor(config);
12688
+ }
12689
+
12690
+ // src/interceptors/response/token-refresh.interceptor.ts
12691
+ var TokenRefreshInterceptor = class {
12692
+ constructor(config) {
12693
+ this.name = "token-refresh";
12694
+ this.state = {
12695
+ isRefreshing: false,
12696
+ refreshPromise: null,
12697
+ failCount: 0
12698
+ };
12699
+ this.refreshToken = config.refreshToken;
12700
+ this.executeRequest = config.executeRequest;
12701
+ this.triggerStatusCodes = config.triggerStatusCodes ?? [401];
12702
+ this.maxRetries = config.maxRetries ?? 1;
12703
+ this.onTokenRefreshed = config.onTokenRefreshed;
12704
+ this.onRefreshFailed = config.onRefreshFailed;
12705
+ this.order = config.order ?? 50;
12706
+ }
12707
+ async intercept(error, context) {
12708
+ if (!(error instanceof ApiError)) {
12709
+ return void 0;
12710
+ }
12711
+ if (!this.shouldRefresh(error, context)) {
12712
+ return void 0;
12713
+ }
12714
+ try {
12715
+ const newToken = await this.doRefresh();
12716
+ this.onTokenRefreshed?.(newToken);
12717
+ this.state.failCount = 0;
12718
+ return this.executeRequest(context);
12719
+ } catch (refreshError) {
12720
+ this.state.failCount++;
12721
+ this.onRefreshFailed?.(refreshError);
12722
+ return void 0;
12723
+ }
12724
+ }
12725
+ /**
12726
+ * 判断是否应该刷新 Token
12727
+ */
12728
+ shouldRefresh(error, context) {
12729
+ if (!this.triggerStatusCodes.includes(error.statusCode)) {
12730
+ return false;
12731
+ }
12732
+ if (this.state.failCount >= this.maxRetries) {
12733
+ return false;
12734
+ }
12735
+ if (context.metadata["tokenRefreshAttempted"]) {
12736
+ return false;
12737
+ }
12738
+ return true;
12739
+ }
12740
+ /**
12741
+ * 执行 Token 刷新
12742
+ *
12743
+ * 合并并发请求,确保同一时间只有一个刷新请求
12744
+ */
12745
+ async doRefresh() {
12746
+ if (this.state.isRefreshing && this.state.refreshPromise) {
12747
+ return this.state.refreshPromise;
12748
+ }
12749
+ this.state.isRefreshing = true;
12750
+ this.state.refreshPromise = this.refreshToken();
12751
+ try {
12752
+ const newToken = await this.state.refreshPromise;
12753
+ return newToken;
12754
+ } finally {
12755
+ this.state.isRefreshing = false;
12756
+ this.state.refreshPromise = null;
12757
+ }
12758
+ }
12759
+ /**
12760
+ * 重置状态(用于测试或手动重置)
12761
+ */
12762
+ reset() {
12763
+ this.state.isRefreshing = false;
12764
+ this.state.refreshPromise = null;
12765
+ this.state.failCount = 0;
12766
+ }
12767
+ };
12768
+ function createTokenRefreshInterceptor(config) {
12769
+ return new TokenRefreshInterceptor(config);
12770
+ }
12771
+
12772
+ // src/interceptors/response/error-transform.interceptor.ts
12773
+ var ErrorTransformInterceptor = class {
12774
+ constructor(config = {}) {
12775
+ this.name = "error-transform";
12776
+ this.includeRawResponse = config.includeRawResponse ?? false;
12777
+ this.extractErrorMessage = config.extractErrorMessage;
12778
+ this.extractErrorCode = config.extractErrorCode;
12779
+ this.order = config.order ?? 0;
12780
+ }
12781
+ intercept(response, _context) {
12782
+ return response;
12783
+ }
12784
+ };
12785
+ function createErrorTransformInterceptor(config) {
12786
+ return new ErrorTransformInterceptor(config);
12787
+ }
12788
+
12789
+ // src/interceptors/error/logging.interceptor.ts
12790
+ var LoggingInterceptor = class {
12791
+ constructor(config) {
12792
+ this.name = "logging";
12793
+ this.logger = config.logger;
12794
+ this.verbose = config.verbose ?? false;
12795
+ this.logAborted = config.logAborted ?? false;
12796
+ this.filter = config.filter;
12797
+ this.order = config.order ?? -100;
12798
+ }
12799
+ intercept(error, context) {
12800
+ if (this.filter && !this.filter(error, context)) {
12801
+ return void 0;
12802
+ }
12803
+ if (error instanceof AbortError && !this.logAborted) {
12804
+ return void 0;
12805
+ }
12806
+ const logInfo = this.buildLogInfo(error, context);
12807
+ if (error instanceof ApiError && error.isClientError() && !error.isRateLimited()) {
12808
+ this.logger.warn(`[API Error] ${logInfo.summary}`, logInfo);
12809
+ } else if (error instanceof AbortError) {
12810
+ this.logger.debug(`[Aborted] ${logInfo.summary}`, logInfo);
12811
+ } else {
12812
+ this.logger.error(`[Error] ${logInfo.summary}`, logInfo);
12813
+ }
12814
+ return void 0;
12815
+ }
12816
+ /**
12817
+ * 构建日志信息
12818
+ */
12819
+ buildLogInfo(error, context) {
12820
+ const duration = Date.now() - context.startTime;
12821
+ const base = {
12822
+ summary: `${context.options.method} ${context.options.path} - ${error.message}`,
12823
+ requestId: context.requestId,
12824
+ traceId: context.traceId,
12825
+ method: context.options.method,
12826
+ path: context.options.path,
12827
+ url: context.url,
12828
+ duration: `${duration}ms`,
12829
+ retryCount: context.retryCount
12830
+ };
12831
+ if (this.verbose) {
12832
+ const detailed = {
12833
+ ...base,
12834
+ error: {
12835
+ name: error.name,
12836
+ message: error.message,
12837
+ stack: error.stack
12838
+ }
12839
+ };
12840
+ if (error instanceof ApiError) {
12841
+ detailed.apiError = {
12842
+ code: error.code,
12843
+ statusCode: error.statusCode,
12844
+ details: error.details,
12845
+ retryable: error.retryable
12846
+ };
12847
+ } else if (error instanceof TimeoutError) {
12848
+ detailed.timeout = error.timeoutMs;
12849
+ } else if (error instanceof NetworkError) {
12850
+ detailed.networkError = error.cause?.message;
12851
+ }
12852
+ return detailed;
12853
+ }
12854
+ if (error instanceof ApiError) {
12855
+ return {
12856
+ ...base,
12857
+ code: error.code,
12858
+ statusCode: error.statusCode
12859
+ };
12860
+ }
12861
+ if (error instanceof TimeoutError) {
12862
+ return {
12863
+ ...base,
12864
+ timeout: error.timeoutMs
12865
+ };
12866
+ }
12867
+ return base;
12868
+ }
12869
+ };
12870
+ function createLoggingInterceptor(config) {
12871
+ return new LoggingInterceptor(config);
12872
+ }
12873
+
12874
+ // src/interceptors/error/reporting.interceptor.ts
12875
+ var ReportingInterceptor = class {
12876
+ constructor(config) {
12877
+ this.name = "reporting";
12878
+ this.reporter = config.reporter;
12879
+ this.getSeverity = config.getSeverity ?? this.defaultGetSeverity;
12880
+ this.reportClientErrors = config.reportClientErrors ?? false;
12881
+ this.reportAborted = config.reportAborted ?? false;
12882
+ this.reportNetworkErrors = config.reportNetworkErrors ?? true;
12883
+ this.sampleRate = config.sampleRate ?? 1;
12884
+ this.extractContext = config.extractContext;
12885
+ this.order = config.order ?? -50;
12886
+ }
12887
+ intercept(error, context) {
12888
+ if (!this.shouldReport(error)) {
12889
+ return void 0;
12890
+ }
12891
+ if (this.sampleRate < 1 && Math.random() > this.sampleRate) {
12892
+ return void 0;
12893
+ }
12894
+ const reportContext = this.buildReportContext(error, context);
12895
+ try {
12896
+ this.reporter.report(error, reportContext);
12897
+ } catch {
12898
+ }
12899
+ return void 0;
12900
+ }
12901
+ /**
12902
+ * 判断是否应该上报
12903
+ */
12904
+ shouldReport(error) {
12905
+ if (error instanceof AbortError) {
12906
+ return this.reportAborted;
12907
+ }
12908
+ if (error instanceof NetworkError) {
12909
+ return this.reportNetworkErrors;
12910
+ }
12911
+ if (error instanceof ApiError) {
12912
+ if (error.isClientError()) {
12913
+ return this.reportClientErrors;
12914
+ }
12915
+ return true;
12916
+ }
12917
+ if (error instanceof TimeoutError) {
12918
+ return true;
12919
+ }
12920
+ return true;
12921
+ }
12922
+ /**
12923
+ * 构建上报上下文
12924
+ */
12925
+ buildReportContext(error, context) {
12926
+ const baseContext = {
12927
+ severity: this.getSeverity(error),
12928
+ requestId: context.requestId,
12929
+ traceId: context.traceId,
12930
+ url: context.url,
12931
+ method: context.options.method,
12932
+ path: context.options.path,
12933
+ retryCount: context.retryCount,
12934
+ duration: Date.now() - context.startTime
12935
+ };
12936
+ if (error instanceof ApiError) {
12937
+ baseContext["api"] = {
12938
+ code: error.code,
12939
+ statusCode: error.statusCode,
12940
+ retryable: error.retryable
12941
+ };
12942
+ } else if (error instanceof TimeoutError) {
12943
+ baseContext["timeout"] = error.timeoutMs;
12944
+ }
12945
+ if (this.extractContext) {
12946
+ const customContext = this.extractContext(error, context);
12947
+ return { ...baseContext, ...customContext };
12948
+ }
12949
+ return baseContext;
12950
+ }
12951
+ /**
12952
+ * 默认的严重程度判断
12953
+ */
12954
+ defaultGetSeverity(error) {
12955
+ if (error instanceof AbortError) {
12956
+ return "debug";
12957
+ }
12958
+ if (error instanceof ApiError) {
12959
+ if (error.isServerError()) {
12960
+ return "error";
12961
+ }
12962
+ if (error.isRateLimited()) {
12963
+ return "warning";
12964
+ }
12965
+ return "info";
12966
+ }
12967
+ if (error instanceof NetworkError || error instanceof TimeoutError) {
12968
+ return "warning";
12969
+ }
12970
+ return "error";
12971
+ }
12972
+ };
12973
+ function createReportingInterceptor(config) {
12974
+ return new ReportingInterceptor(config);
12975
+ }
12976
+
12977
+ // src/plugins/deduplication.ts
12978
+ var RequestDeduper = class {
12979
+ constructor(config = {}) {
12980
+ this.inflightRequests = /* @__PURE__ */ new Map();
12981
+ this.getOnly = config.getOnly ?? true;
12982
+ this.generateKey = config.generateKey ?? this.defaultGenerateKey;
12983
+ this.maxSize = config.maxSize ?? 100;
12984
+ }
12985
+ /**
12986
+ * 执行请求(带去重)
12987
+ *
12988
+ * @param method - HTTP 方法
12989
+ * @param url - 请求 URL
12990
+ * @param execute - 实际执行请求的函数
12991
+ * @returns 请求结果
12992
+ */
12993
+ async execute(method, url2, execute) {
12994
+ if (!this.shouldDeduplicate(method)) {
12995
+ return execute();
12996
+ }
12997
+ const key = this.generateKey(method, url2);
12998
+ const inflight = this.inflightRequests.get(key);
12999
+ if (inflight) {
13000
+ return inflight.promise;
13001
+ }
13002
+ if (this.inflightRequests.size >= this.maxSize) {
13003
+ this.cleanup();
13004
+ }
13005
+ const promise = execute().finally(() => {
13006
+ this.inflightRequests.delete(key);
13007
+ });
13008
+ this.inflightRequests.set(key, {
13009
+ promise,
13010
+ createdAt: Date.now()
13011
+ });
13012
+ return promise;
13013
+ }
13014
+ /**
13015
+ * 包装 fetch 函数
13016
+ *
13017
+ * @param fetch - 原始 fetch 函数
13018
+ * @returns 去重的 fetch 函数
13019
+ */
13020
+ wrap(fetch2) {
13021
+ return (url2, init) => {
13022
+ const method = init?.method ?? "GET";
13023
+ return this.execute(method, url2, () => fetch2(url2, init));
13024
+ };
13025
+ }
13026
+ /**
13027
+ * 获取当前飞行中的请求数量
13028
+ */
13029
+ get inflightCount() {
13030
+ return this.inflightRequests.size;
13031
+ }
13032
+ /**
13033
+ * 清空所有飞行中的请求
13034
+ */
13035
+ clear() {
13036
+ this.inflightRequests.clear();
13037
+ }
13038
+ /**
13039
+ * 判断是否应该去重
13040
+ */
13041
+ shouldDeduplicate(method) {
13042
+ if (this.getOnly) {
13043
+ return method.toUpperCase() === "GET";
13044
+ }
13045
+ return true;
13046
+ }
13047
+ /**
13048
+ * 默认的键生成函数
13049
+ */
13050
+ defaultGenerateKey(method, url2) {
13051
+ return `${method.toUpperCase()}:${url2}`;
13052
+ }
13053
+ /**
13054
+ * 清理过期的请求
13055
+ */
13056
+ cleanup() {
13057
+ const toDelete = Math.floor(this.maxSize * 0.2);
13058
+ const entries = Array.from(this.inflightRequests.entries()).sort((a, b) => a[1].createdAt - b[1].createdAt);
13059
+ for (let i = 0; i < toDelete && i < entries.length; i++) {
13060
+ this.inflightRequests.delete(entries[i][0]);
13061
+ }
13062
+ }
13063
+ };
13064
+ function createRequestDeduper(config) {
13065
+ return new RequestDeduper(config);
13066
+ }
13067
+
13068
+ // src/utils/url.ts
13069
+ function buildUrl(baseUrl, path, query) {
13070
+ const normalizedBase = baseUrl.replace(/\/+$/, "");
13071
+ const normalizedPath = path.startsWith("/") ? path : `/${path}`;
13072
+ const url2 = new URL(`${normalizedBase}${normalizedPath}`);
13073
+ if (query) {
13074
+ for (const [key, value] of Object.entries(query)) {
13075
+ if (value !== void 0 && value !== null) {
13076
+ url2.searchParams.set(key, String(value));
13077
+ }
13078
+ }
13079
+ }
13080
+ return url2.toString();
13081
+ }
13082
+ function extractPath(url2) {
13083
+ try {
13084
+ const parsed = new URL(url2);
13085
+ return parsed.pathname;
13086
+ } catch {
13087
+ const queryIndex = url2.indexOf("?");
13088
+ const pathPart = queryIndex >= 0 ? url2.slice(0, queryIndex) : url2;
13089
+ return pathPart.startsWith("/") ? pathPart : `/${pathPart}`;
13090
+ }
13091
+ }
13092
+ function parseQueryString(queryString) {
13093
+ const result = {};
13094
+ const normalized = queryString.startsWith("?") ? queryString.slice(1) : queryString;
13095
+ if (!normalized) {
13096
+ return result;
13097
+ }
13098
+ const params = new URLSearchParams(normalized);
13099
+ for (const [key, value] of params.entries()) {
13100
+ result[key] = value;
13101
+ }
13102
+ return result;
13103
+ }
13104
+ function joinPaths(base, path) {
13105
+ const normalizedBase = base.replace(/\/+$/, "");
13106
+ const normalizedPath = path.replace(/^\/+/, "");
13107
+ if (!normalizedPath) {
13108
+ return normalizedBase || "/";
13109
+ }
13110
+ return `${normalizedBase}/${normalizedPath}`;
13111
+ }
13112
+
13113
+ // src/plugins/metrics.ts
13114
+ var DefaultMetricsCollector = class {
13115
+ constructor(config = {}) {
13116
+ this.metrics = [];
13117
+ this.maxMetrics = config.maxMetrics ?? 1e3;
13118
+ this.ttlMs = config.ttlMs ?? 36e5;
13119
+ this.onMetrics = config.onMetrics;
13120
+ }
13121
+ record(metrics) {
13122
+ this.onMetrics?.(metrics);
13123
+ this.metrics.push(metrics);
13124
+ this.cleanup();
13125
+ }
13126
+ summary() {
13127
+ if (this.metrics.length === 0) {
13128
+ return this.emptySummary();
13129
+ }
13130
+ const successful = this.metrics.filter((m) => m.success);
13131
+ const durations = this.metrics.map((m) => m.durationMs).sort((a, b) => a - b);
13132
+ const p = (percentile) => {
13133
+ const index = Math.ceil(durations.length * percentile / 100) - 1;
13134
+ return durations[Math.max(0, index)];
13135
+ };
13136
+ const statusCodeDistribution = {};
13137
+ for (const m of this.metrics) {
13138
+ if (m.status !== void 0) {
13139
+ statusCodeDistribution[m.status] = (statusCodeDistribution[m.status] ?? 0) + 1;
13140
+ }
13141
+ }
13142
+ const pathDistribution = {};
13143
+ const pathGroups = {};
13144
+ for (const m of this.metrics) {
13145
+ if (!pathGroups[m.path]) {
13146
+ pathGroups[m.path] = [];
13147
+ }
13148
+ pathGroups[m.path].push(m);
13149
+ }
13150
+ for (const [path, group] of Object.entries(pathGroups)) {
13151
+ const successCount = group.filter((m) => m.success).length;
13152
+ const avgDuration2 = group.reduce((sum, m) => sum + m.durationMs, 0) / group.length;
13153
+ pathDistribution[path] = {
13154
+ count: group.length,
13155
+ successCount,
13156
+ avgDurationMs: Math.round(avgDuration2)
13157
+ };
13158
+ }
13159
+ const totalRetries = this.metrics.reduce((sum, m) => sum + m.retryCount, 0);
13160
+ const avgDuration = this.metrics.reduce((sum, m) => sum + m.durationMs, 0) / this.metrics.length;
13161
+ return {
13162
+ totalRequests: this.metrics.length,
13163
+ successfulRequests: successful.length,
13164
+ failedRequests: this.metrics.length - successful.length,
13165
+ successRate: successful.length / this.metrics.length,
13166
+ avgDurationMs: Math.round(avgDuration),
13167
+ p50Ms: p(50),
13168
+ p90Ms: p(90),
13169
+ p95Ms: p(95),
13170
+ p99Ms: p(99),
13171
+ minDurationMs: durations[0],
13172
+ maxDurationMs: durations[durations.length - 1],
13173
+ totalRetries,
13174
+ statusCodeDistribution,
13175
+ pathDistribution
13176
+ };
13177
+ }
13178
+ getAll() {
13179
+ return [...this.metrics];
13180
+ }
13181
+ getByPath(path) {
13182
+ return this.metrics.filter((m) => m.path === path);
13183
+ }
13184
+ flush() {
13185
+ const result = [...this.metrics];
13186
+ this.metrics = [];
13187
+ return result;
13188
+ }
13189
+ clear() {
13190
+ this.metrics = [];
13191
+ }
13192
+ cleanup() {
13193
+ const now = Date.now();
13194
+ this.metrics = this.metrics.filter((m) => now - m.startTime < this.ttlMs);
13195
+ while (this.metrics.length > this.maxMetrics) {
13196
+ this.metrics.shift();
13197
+ }
13198
+ }
13199
+ emptySummary() {
13200
+ return {
13201
+ totalRequests: 0,
13202
+ successfulRequests: 0,
13203
+ failedRequests: 0,
13204
+ successRate: 0,
13205
+ avgDurationMs: 0,
13206
+ p50Ms: 0,
13207
+ p90Ms: 0,
13208
+ p95Ms: 0,
13209
+ p99Ms: 0,
13210
+ minDurationMs: 0,
13211
+ maxDurationMs: 0,
13212
+ totalRetries: 0,
13213
+ statusCodeDistribution: {},
13214
+ pathDistribution: {}
13215
+ };
13216
+ }
13217
+ };
13218
+ function createMetricsCollector(config) {
13219
+ return new DefaultMetricsCollector(config);
13220
+ }
13221
+ var MetricsRequestInterceptor = class {
13222
+ constructor() {
13223
+ this.name = "metrics-request";
13224
+ this.order = -1e3;
13225
+ }
13226
+ // 最先执行
13227
+ intercept(context) {
13228
+ return context.options;
13229
+ }
13230
+ };
13231
+ var MetricsResponseInterceptor = class {
13232
+ // 最后执行
13233
+ constructor(collector) {
13234
+ this.collector = collector;
13235
+ this.name = "metrics-response";
13236
+ this.order = 1e3;
13237
+ }
13238
+ intercept(response, context) {
13239
+ const endTime = Date.now();
13240
+ const metrics = {
13241
+ requestId: context.requestId,
13242
+ url: context.url,
13243
+ path: extractPath(context.url),
13244
+ method: context.options.method,
13245
+ startTime: context.startTime,
13246
+ endTime,
13247
+ durationMs: endTime - context.startTime,
13248
+ status: response.status,
13249
+ success: true,
13250
+ retryCount: context.retryCount,
13251
+ traceId: context.traceId
13252
+ };
13253
+ this.collector.record(metrics);
13254
+ return response;
13255
+ }
13256
+ };
13257
+ var MetricsErrorInterceptor = class {
13258
+ // 最后执行
13259
+ constructor(collector) {
13260
+ this.collector = collector;
13261
+ this.name = "metrics-error";
13262
+ this.order = 1e3;
13263
+ }
13264
+ intercept(error, context) {
13265
+ const endTime = Date.now();
13266
+ const metrics = {
13267
+ requestId: context.requestId,
13268
+ url: context.url,
13269
+ path: extractPath(context.url),
13270
+ method: context.options.method,
13271
+ startTime: context.startTime,
13272
+ endTime,
13273
+ durationMs: endTime - context.startTime,
13274
+ success: false,
13275
+ retryCount: context.retryCount,
13276
+ traceId: context.traceId,
13277
+ error: error.message
13278
+ };
13279
+ this.collector.record(metrics);
13280
+ return void 0;
13281
+ }
13282
+ };
13283
+ function createMetricsInterceptors(collector) {
13284
+ return {
13285
+ request: new MetricsRequestInterceptor(),
13286
+ response: new MetricsResponseInterceptor(collector),
13287
+ error: new MetricsErrorInterceptor(collector)
13288
+ };
13289
+ }
13290
+
13291
+ // src/plugins/logger.ts
13292
+ var ConsoleLogger = class {
13293
+ constructor(config = {}) {
13294
+ this.prefix = config.prefix ?? "[DJV-API]";
13295
+ this.level = config.level ?? "info";
13296
+ this.timestamp = config.timestamp ?? true;
13297
+ this.levelPriority = LOG_LEVEL_PRIORITY[this.level];
13298
+ }
13299
+ debug(message, ...args) {
13300
+ this.log("debug", message, args);
13301
+ }
13302
+ info(message, ...args) {
13303
+ this.log("info", message, args);
13304
+ }
13305
+ warn(message, ...args) {
13306
+ this.log("warn", message, args);
13307
+ }
13308
+ error(message, ...args) {
13309
+ this.log("error", message, args);
13310
+ }
13311
+ log(level, message, args) {
13312
+ if (LOG_LEVEL_PRIORITY[level] < this.levelPriority) {
13313
+ return;
13314
+ }
13315
+ const formattedMessage = this.formatMessage(level, message);
13316
+ switch (level) {
13317
+ case "debug":
13318
+ console.debug(formattedMessage, ...args);
13319
+ break;
13320
+ case "info":
13321
+ console.info(formattedMessage, ...args);
13322
+ break;
13323
+ case "warn":
13324
+ console.warn(formattedMessage, ...args);
13325
+ break;
13326
+ case "error":
13327
+ console.error(formattedMessage, ...args);
13328
+ break;
13329
+ }
13330
+ }
13331
+ formatMessage(level, message) {
13332
+ const parts = [];
13333
+ if (this.timestamp) {
13334
+ parts.push(`[${(/* @__PURE__ */ new Date()).toISOString()}]`);
13335
+ }
13336
+ parts.push(this.prefix);
13337
+ parts.push(`[${level.toUpperCase()}]`);
13338
+ parts.push(message);
13339
+ return parts.join(" ");
13340
+ }
13341
+ };
13342
+ function createConsoleLogger(config) {
13343
+ return new ConsoleLogger(config);
13344
+ }
13345
+ var SilentLogger = class {
13346
+ debug(_message, ..._args) {
13347
+ }
13348
+ info(_message, ..._args) {
13349
+ }
13350
+ warn(_message, ..._args) {
13351
+ }
13352
+ error(_message, ..._args) {
13353
+ }
13354
+ };
13355
+ function createSilentLogger() {
13356
+ return new SilentLogger();
13357
+ }
13358
+ var silentLogger = new SilentLogger();
13359
+ var BufferLogger = class {
13360
+ constructor(maxSize = 1e3) {
13361
+ this.buffer = [];
13362
+ this.maxSize = maxSize;
13363
+ }
13364
+ debug(message, ...args) {
13365
+ this.add("debug", message, args);
13366
+ }
13367
+ info(message, ...args) {
13368
+ this.add("info", message, args);
13369
+ }
13370
+ warn(message, ...args) {
13371
+ this.add("warn", message, args);
13372
+ }
13373
+ error(message, ...args) {
13374
+ this.add("error", message, args);
13375
+ }
13376
+ /**
13377
+ * 获取所有日志
13378
+ */
13379
+ getLogs() {
13380
+ return [...this.buffer];
13381
+ }
13382
+ /**
13383
+ * 获取指定级别的日志
13384
+ */
13385
+ getLogsByLevel(level) {
13386
+ return this.buffer.filter((log) => log.level === level);
13387
+ }
13388
+ /**
13389
+ * 清空日志
13390
+ */
13391
+ clear() {
13392
+ this.buffer.length = 0;
13393
+ }
13394
+ /**
13395
+ * 获取日志数量
13396
+ */
13397
+ get size() {
13398
+ return this.buffer.length;
13399
+ }
13400
+ add(level, message, args) {
13401
+ this.buffer.push({
13402
+ level,
13403
+ message,
13404
+ args,
13405
+ timestamp: /* @__PURE__ */ new Date()
13406
+ });
13407
+ while (this.buffer.length > this.maxSize) {
13408
+ this.buffer.shift();
13409
+ }
13410
+ }
13411
+ };
13412
+ function createBufferLogger(maxSize) {
13413
+ return new BufferLogger(maxSize);
13414
+ }
13415
+
13416
+ // src/utils/headers.ts
13417
+ var DEFAULT_HEADERS = {
13418
+ "Content-Type": "application/json",
13419
+ Accept: "application/json"
13420
+ };
13421
+ function mergeHeaders(...headersList) {
13422
+ const result = {};
13423
+ const lowercaseKeyMap = {};
13424
+ for (const headers of headersList) {
13425
+ if (!headers) continue;
13426
+ for (const [key, value] of Object.entries(headers)) {
13427
+ const lowercaseKey = key.toLowerCase();
13428
+ if (lowercaseKeyMap[lowercaseKey]) {
13429
+ delete result[lowercaseKeyMap[lowercaseKey]];
13430
+ }
13431
+ result[key] = value;
13432
+ lowercaseKeyMap[lowercaseKey] = key;
13433
+ }
13434
+ }
13435
+ return result;
13436
+ }
13437
+ function getHeader(headers, name) {
13438
+ const lowercaseName = name.toLowerCase();
13439
+ for (const [key, value] of Object.entries(headers)) {
13440
+ if (key.toLowerCase() === lowercaseName) {
13441
+ return value;
13442
+ }
13443
+ }
13444
+ return void 0;
13445
+ }
13446
+ function setHeader(headers, name, value) {
13447
+ const lowercaseName = name.toLowerCase();
13448
+ for (const key of Object.keys(headers)) {
13449
+ if (key.toLowerCase() === lowercaseName) {
13450
+ delete headers[key];
13451
+ }
13452
+ }
13453
+ headers[name] = value;
13454
+ }
13455
+ function removeHeader(headers, name) {
13456
+ const lowercaseName = name.toLowerCase();
13457
+ let removed = false;
13458
+ for (const key of Object.keys(headers)) {
13459
+ if (key.toLowerCase() === lowercaseName) {
13460
+ delete headers[key];
13461
+ removed = true;
13462
+ }
13463
+ }
13464
+ return removed;
13465
+ }
13466
+ function extractResponseHeaders(response) {
13467
+ const headers = {};
13468
+ response.headers.forEach((value, key) => {
13469
+ headers[key] = value;
13470
+ });
13471
+ return headers;
13472
+ }
13473
+ function hasContentType(headers, contentType) {
13474
+ const value = getHeader(headers, "Content-Type");
13475
+ if (!value) return false;
13476
+ return value.toLowerCase().includes(contentType.toLowerCase());
13477
+ }
13478
+
13479
+ // src/clients/base-client.ts
13480
+ var BaseClient = class {
13481
+ constructor(config) {
13482
+ this.config = {
13483
+ timeout: 3e4,
13484
+ ...config
13485
+ };
13486
+ this.interceptorManager = new InterceptorManager();
13487
+ this.authenticator = config.auth ? createAuthenticatorFromConfig(config.auth) : noAuthenticator;
13488
+ this.registerConfigInterceptors();
13489
+ }
13490
+ /**
13491
+ * GET 请求
13492
+ */
13493
+ async get(path, query) {
13494
+ return this.request({ method: "GET", path, query });
13495
+ }
13496
+ /**
13497
+ * POST 请求
13498
+ */
13499
+ async post(path, body, query) {
13500
+ return this.request({ method: "POST", path, body, query });
13501
+ }
13502
+ /**
13503
+ * PUT 请求
13504
+ */
13505
+ async put(path, body) {
13506
+ return this.request({ method: "PUT", path, body });
13507
+ }
13508
+ /**
13509
+ * PATCH 请求
13510
+ */
13511
+ async patch(path, body) {
13512
+ return this.request({ method: "PATCH", path, body });
13513
+ }
13514
+ /**
13515
+ * DELETE 请求
13516
+ */
13517
+ async delete(path) {
13518
+ return this.request({ method: "DELETE", path });
13519
+ }
13520
+ /**
13521
+ * 获取拦截器管理器
13522
+ */
13523
+ get interceptors() {
13524
+ return this.interceptorManager;
13525
+ }
13526
+ /**
13527
+ * 创建请求上下文
13528
+ */
13529
+ createRequestContext(options) {
13530
+ const requestId = generateRequestId();
13531
+ const traceId = generateTraceId();
13532
+ const url2 = buildUrl(this.config.baseUrl, options.path, options.query);
13533
+ const headers = mergeHeaders(
13534
+ DEFAULT_HEADERS,
13535
+ this.config.headers,
13536
+ options.headers
13537
+ );
13538
+ const mutableOptions = {
13539
+ method: options.method,
13540
+ path: options.path,
13541
+ query: options.query ? { ...options.query } : void 0,
13542
+ body: options.body,
13543
+ headers,
13544
+ timeout: options.timeout ?? this.config.timeout,
13545
+ skipAuth: options.skipAuth ?? false,
13546
+ signal: options.signal,
13547
+ metadata: options.metadata ? { ...options.metadata } : {}
13548
+ };
13549
+ return {
13550
+ requestId,
13551
+ traceId,
13552
+ startTime: Date.now(),
13553
+ retryCount: 0,
13554
+ originalOptions: options,
13555
+ options: mutableOptions,
13556
+ url: url2,
13557
+ metadata: {}
13558
+ };
13559
+ }
13560
+ /**
13561
+ * 执行请求拦截器
13562
+ */
13563
+ async runRequestInterceptors(context) {
13564
+ if (!context.options.skipAuth) {
13565
+ await this.authenticator.authenticate(context.options.headers);
13566
+ }
13567
+ return this.interceptorManager.executeRequestInterceptors(context);
13568
+ }
13569
+ /**
13570
+ * 执行响应拦截器
13571
+ */
13572
+ async runResponseInterceptors(response, context) {
13573
+ return this.interceptorManager.executeResponseInterceptors(response, context);
13574
+ }
13575
+ /**
13576
+ * 执行错误拦截器
13577
+ */
13578
+ async runErrorInterceptors(error, context) {
13579
+ return this.interceptorManager.executeErrorInterceptors(error, context);
13580
+ }
13581
+ /**
13582
+ * 注册配置中的拦截器
13583
+ */
13584
+ registerConfigInterceptors() {
13585
+ if (this.config.requestInterceptors) {
13586
+ for (const interceptor of this.config.requestInterceptors) {
13587
+ this.interceptorManager.addRequestInterceptor(interceptor);
13588
+ }
13589
+ }
13590
+ if (this.config.responseInterceptors) {
13591
+ for (const interceptor of this.config.responseInterceptors) {
13592
+ this.interceptorManager.addResponseInterceptor(interceptor);
13593
+ }
13594
+ }
13595
+ if (this.config.errorInterceptors) {
13596
+ for (const interceptor of this.config.errorInterceptors) {
13597
+ this.interceptorManager.addErrorInterceptor(interceptor);
13598
+ }
13599
+ }
13600
+ }
13601
+ };
13602
+
13603
+ // src/clients/fetch-client.ts
13604
+ var FetchClient = class extends BaseClient {
13605
+ constructor(config) {
13606
+ super(config);
13607
+ this.enableRetry = config.enableRetry !== false;
13608
+ }
13609
+ /**
13610
+ * 发起请求
13611
+ */
13612
+ async request(options) {
13613
+ const context = this.createRequestContext(options);
13614
+ try {
13615
+ const response = await this.executeWithRetry(context);
13616
+ return response.data;
13617
+ } catch (error) {
13618
+ const recovered = await this.runErrorInterceptors(error, context);
13619
+ if (recovered) {
13620
+ return recovered.data;
13621
+ }
13622
+ throw error;
13623
+ }
13624
+ }
13625
+ /**
13626
+ * 带重试的请求执行
13627
+ */
13628
+ async executeWithRetry(context) {
13629
+ const retryConfig = this.config.retry;
13630
+ const maxRetries = this.enableRetry && retryConfig ? retryConfig.maxRetries : 0;
13631
+ for (; ; ) {
13632
+ try {
13633
+ return await this.executeRequest(context);
13634
+ } catch (error) {
13635
+ const err = error;
13636
+ if (!this.shouldRetry(err, context, retryConfig, maxRetries)) {
13637
+ throw err;
13638
+ }
13639
+ const retryAfterSeconds = err instanceof ApiError ? err.getRetryAfter() : void 0;
13640
+ let delayMs = calculateRetryDelay(retryConfig, context.retryCount);
13641
+ if (retryConfig?.respectRetryAfter !== false && retryAfterSeconds !== void 0) {
13642
+ delayMs = Math.min(retryAfterSeconds * 1e3, retryConfig.maxDelayMs);
13643
+ }
13644
+ if (retryConfig?.onRetry) {
13645
+ retryConfig.onRetry({
13646
+ attempt: context.retryCount + 1,
13647
+ maxRetries: retryConfig.maxRetries,
13648
+ delayMs,
13649
+ error: err,
13650
+ url: context.url,
13651
+ method: context.options.method
13652
+ });
13653
+ }
13654
+ this.logDebug(
13655
+ `[Retry] ${context.options.method} ${context.options.path} - attempt ${context.retryCount + 1}/${maxRetries}, delay ${delayMs}ms`
13656
+ );
13657
+ await sleep(delayMs);
13658
+ context.retryCount++;
13659
+ }
13660
+ }
13661
+ }
13662
+ /**
13663
+ * 判断是否应该重试
13664
+ */
13665
+ shouldRetry(error, context, retryConfig, maxRetries) {
13666
+ if (!this.enableRetry || !retryConfig) {
13667
+ return false;
13668
+ }
13669
+ if (context.retryCount >= maxRetries) {
13670
+ return false;
13671
+ }
13672
+ if (error instanceof AbortError) {
13673
+ return false;
13674
+ }
13675
+ if (retryConfig.shouldRetry) {
13676
+ const statusCode = error instanceof ApiError ? error.statusCode : void 0;
13677
+ const retryAfter = error instanceof ApiError ? error.getRetryAfter() : void 0;
13678
+ return retryConfig.shouldRetry(error, context.retryCount, {
13679
+ url: context.url,
13680
+ method: context.options.method,
13681
+ statusCode,
13682
+ retryAfter
13683
+ });
13684
+ }
13685
+ if (error instanceof NetworkError) {
13686
+ return retryConfig.retryOnNetworkError !== false;
13687
+ }
13688
+ if (error instanceof TimeoutError) {
13689
+ return retryConfig.retryOnTimeout !== false;
13690
+ }
13691
+ if (error instanceof ApiError) {
13692
+ const retryableCodes = retryConfig.retryableStatusCodes ?? DEFAULT_RETRY_CONFIG.retryableStatusCodes;
13693
+ return retryableCodes?.includes(error.statusCode) ?? false;
13694
+ }
13695
+ return false;
13696
+ }
13697
+ /**
13698
+ * 执行单次请求
13699
+ */
13700
+ async executeRequest(context) {
13701
+ const options = await this.runRequestInterceptors(context);
13702
+ context.options = options;
13703
+ const url2 = this.buildFullUrl(context);
13704
+ const init = this.buildFetchInit(context);
13705
+ const { signal, cleanup } = this.createTimeoutSignal(
13706
+ options.timeout ?? 3e4,
13707
+ options.signal
13708
+ );
13709
+ this.logDebug(`[Request] ${options.method} ${url2}`, {
13710
+ requestId: context.requestId,
13711
+ headers: options.headers
13712
+ });
13713
+ try {
13714
+ const fetchResponse = await fetch(url2, {
13715
+ ...init,
13716
+ signal
13717
+ });
13718
+ const response = await this.parseResponse(fetchResponse, context);
13719
+ const duration = Date.now() - context.startTime;
13720
+ this.logDebug(
13721
+ `[Response] ${options.method} ${options.path} - ${fetchResponse.status} (${duration}ms)`,
13722
+ { requestId: context.requestId, status: fetchResponse.status, duration }
13723
+ );
13724
+ return this.runResponseInterceptors(response, context);
13725
+ } catch (error) {
13726
+ const transformedError = this.transformError(error, context);
13727
+ const duration = Date.now() - context.startTime;
13728
+ this.logError(
13729
+ `[Error] ${options.method} ${options.path} - ${transformedError.message} (${duration}ms)`,
13730
+ { requestId: context.requestId, error: transformedError.message, duration }
13731
+ );
13732
+ throw transformedError;
13733
+ } finally {
13734
+ cleanup();
13735
+ }
13736
+ }
13737
+ /**
13738
+ * 构建完整 URL
13739
+ */
13740
+ buildFullUrl(context) {
13741
+ const { options } = context;
13742
+ const base = this.config.baseUrl.replace(/\/+$/, "");
13743
+ const path = options.path.startsWith("/") ? options.path : `/${options.path}`;
13744
+ const url2 = new URL(`${base}${path}`);
13745
+ if (options.query) {
13746
+ for (const [key, value] of Object.entries(options.query)) {
13747
+ if (value !== void 0 && value !== null) {
13748
+ url2.searchParams.set(key, String(value));
13749
+ }
13750
+ }
13751
+ }
13752
+ return url2.toString();
13753
+ }
13754
+ /**
13755
+ * 构建 fetch init 对象
13756
+ */
13757
+ buildFetchInit(context) {
13758
+ const { options } = context;
13759
+ const init = {
13760
+ method: options.method,
13761
+ headers: options.headers
13762
+ };
13763
+ if (options.body !== void 0) {
13764
+ init.body = JSON.stringify(options.body);
13765
+ }
13766
+ return init;
13767
+ }
13768
+ /**
13769
+ * 创建超时信号
13770
+ */
13771
+ createTimeoutSignal(timeoutMs, externalSignal) {
13772
+ const controller = new AbortController();
13773
+ const timeoutId = setTimeout(() => {
13774
+ controller.abort(new DOMException(`Timeout of ${timeoutMs}ms exceeded`, "TimeoutError"));
13775
+ }, timeoutMs);
13776
+ if (externalSignal) {
13777
+ if (externalSignal.aborted) {
13778
+ controller.abort(externalSignal.reason);
13779
+ } else {
13780
+ const onAbort = () => {
13781
+ controller.abort(externalSignal.reason);
13782
+ };
13783
+ externalSignal.addEventListener("abort", onAbort, { once: true });
13784
+ }
13785
+ }
13786
+ return {
13787
+ signal: controller.signal,
13788
+ cleanup: () => {
13789
+ if (timeoutId !== void 0) {
13790
+ clearTimeout(timeoutId);
13791
+ }
13792
+ }
13793
+ };
13794
+ }
13795
+ /**
13796
+ * 解析响应
13797
+ */
13798
+ async parseResponse(fetchResponse, context) {
13799
+ const headers = extractResponseHeaders(fetchResponse);
13800
+ let data;
13801
+ try {
13802
+ data = await fetchResponse.json();
13803
+ } catch {
13804
+ if (!fetchResponse.ok) {
13805
+ throw ApiError.fromResponse(
13806
+ {
13807
+ code: `HTTP_${fetchResponse.status}`,
13808
+ message: fetchResponse.statusText || `HTTP Error ${fetchResponse.status}`,
13809
+ requestId: context.requestId
13810
+ },
13811
+ fetchResponse.status,
13812
+ parseRetryAfter(getHeader(headers, "Retry-After"))
13813
+ );
13814
+ }
13815
+ data = {
13816
+ success: true,
13817
+ data: void 0,
13818
+ requestId: context.requestId
13819
+ };
13820
+ }
13821
+ if (!fetchResponse.ok || data.success === false) {
13822
+ throw ApiError.fromResponse(
13823
+ {
13824
+ code: data.code,
13825
+ message: data.message,
13826
+ details: data.details,
13827
+ requestId: data.requestId ?? context.requestId,
13828
+ traceId: data.traceId ?? context.traceId
13829
+ },
13830
+ fetchResponse.status,
13831
+ parseRetryAfter(getHeader(headers, "Retry-After"))
13832
+ );
13833
+ }
13834
+ return {
13835
+ data: data.data,
13836
+ status: fetchResponse.status,
13837
+ statusText: fetchResponse.statusText,
13838
+ headers,
13839
+ requestId: data.requestId ?? context.requestId,
13840
+ traceId: data.traceId ?? context.traceId
13841
+ };
13842
+ }
13843
+ /**
13844
+ * 转换错误
13845
+ */
13846
+ transformError(error, _context) {
13847
+ if (error instanceof ApiError || error instanceof NetworkError || error instanceof TimeoutError || error instanceof AbortError) {
13848
+ return error;
13849
+ }
13850
+ if (error.name === "AbortError") {
13851
+ if (error.message?.includes("Timeout")) {
13852
+ const match = error.message.match(/(\d+)ms/);
13853
+ const timeout = match ? parseInt(match[1], 10) : 3e4;
13854
+ return new TimeoutError(timeout);
13855
+ }
13856
+ return AbortError.fromNative(error);
13857
+ }
13858
+ if (error.name === "TypeError") {
13859
+ return NetworkError.fromFetchError(error);
11729
13860
  }
11730
- const retryableCodes = ["SYSTEM_TIMEOUT", "SYSTEM_SERVICE_UNAVAILABLE"];
11731
- return retryableCodes.includes(code);
13861
+ return new NetworkError(error.message, error);
11732
13862
  }
11733
- };
11734
- var NetworkError = class extends Error {
11735
- constructor(message, cause) {
11736
- super(message);
11737
- this.cause = cause;
11738
- this.retryable = true;
11739
- this.name = "NetworkError";
13863
+ // ============================================================
13864
+ // 日志辅助方法
13865
+ // ============================================================
13866
+ /**
13867
+ * 调试日志
13868
+ */
13869
+ logDebug(message, data) {
13870
+ if (this.config.debug && this.config.logger) {
13871
+ this.config.logger.debug(message, data);
13872
+ }
11740
13873
  }
11741
- };
11742
- var TimeoutError = class extends Error {
11743
- constructor(timeout) {
11744
- super(`Request timeout after ${timeout}ms`);
11745
- this.retryable = true;
11746
- this.name = "TimeoutError";
13874
+ /**
13875
+ * 错误日志
13876
+ */
13877
+ logError(message, data) {
13878
+ if (this.config.logger) {
13879
+ this.config.logger.error(message, data);
13880
+ }
11747
13881
  }
11748
13882
  };
13883
+ function createFetchClient(config) {
13884
+ return new FetchClient(config);
13885
+ }
11749
13886
 
11750
13887
  // ../../node_modules/.pnpm/axios@1.13.2/node_modules/axios/lib/helpers/bind.js
11751
13888
  function bind(fn, thisArg) {
@@ -12402,7 +14539,7 @@ function buildURL(url2, params, options) {
12402
14539
  }
12403
14540
 
12404
14541
  // ../../node_modules/.pnpm/axios@1.13.2/node_modules/axios/lib/core/InterceptorManager.js
12405
- var InterceptorManager = class {
14542
+ var InterceptorManager2 = class {
12406
14543
  constructor() {
12407
14544
  this.handlers = [];
12408
14545
  }
@@ -12463,7 +14600,7 @@ var InterceptorManager = class {
12463
14600
  });
12464
14601
  }
12465
14602
  };
12466
- var InterceptorManager_default = InterceptorManager;
14603
+ var InterceptorManager_default = InterceptorManager2;
12467
14604
 
12468
14605
  // ../../node_modules/.pnpm/axios@1.13.2/node_modules/axios/lib/defaults/transitional.js
12469
14606
  var transitional_default = {
@@ -12476,8 +14613,8 @@ var transitional_default = {
12476
14613
  var import_crypto = __toESM(require("crypto"), 1);
12477
14614
 
12478
14615
  // ../../node_modules/.pnpm/axios@1.13.2/node_modules/axios/lib/platform/node/classes/URLSearchParams.js
12479
- var import_url = __toESM(require("url"), 1);
12480
- var URLSearchParams_default = import_url.default.URLSearchParams;
14616
+ var import_url3 = __toESM(require("url"), 1);
14617
+ var URLSearchParams_default = import_url3.default.URLSearchParams;
12481
14618
 
12482
14619
  // ../../node_modules/.pnpm/axios@1.13.2/node_modules/axios/lib/platform/node/index.js
12483
14620
  var ALPHA = "abcdefghijklmnopqrstuvwxyz";
@@ -12812,7 +14949,7 @@ var AxiosHeaders = class {
12812
14949
  }
12813
14950
  set(header, valueOrRewrite, rewrite) {
12814
14951
  const self2 = this;
12815
- function setHeader(_value, _header, _rewrite) {
14952
+ function setHeader2(_value, _header, _rewrite) {
12816
14953
  const lHeader = normalizeHeader(_header);
12817
14954
  if (!lHeader) {
12818
14955
  throw new Error("header name must be a non-empty string");
@@ -12822,7 +14959,7 @@ var AxiosHeaders = class {
12822
14959
  self2[key || _header] = normalizeValue(_value);
12823
14960
  }
12824
14961
  }
12825
- const setHeaders = (headers, _rewrite) => utils_default.forEach(headers, (_value, _header) => setHeader(_value, _header, _rewrite));
14962
+ const setHeaders = (headers, _rewrite) => utils_default.forEach(headers, (_value, _header) => setHeader2(_value, _header, _rewrite));
12826
14963
  if (utils_default.isPlainObject(header) || header instanceof this.constructor) {
12827
14964
  setHeaders(header, valueOrRewrite);
12828
14965
  } else if (utils_default.isString(header) && (header = header.trim()) && !isValidHeaderName(header)) {
@@ -12837,7 +14974,7 @@ var AxiosHeaders = class {
12837
14974
  }
12838
14975
  setHeaders(obj, valueOrRewrite);
12839
14976
  } else {
12840
- header != null && setHeader(valueOrRewrite, header, rewrite);
14977
+ header != null && setHeader2(valueOrRewrite, header, rewrite);
12841
14978
  }
12842
14979
  return this;
12843
14980
  }
@@ -14596,7 +16733,7 @@ var factory = (env2) => {
14596
16733
  const encodeText = isFetchSupported && (typeof TextEncoder2 === "function" ? /* @__PURE__ */ ((encoder) => (str) => encoder.encode(str))(new TextEncoder2()) : async (str) => new Uint8Array(await new Request(str).arrayBuffer()));
14597
16734
  const supportsRequestStream = isRequestSupported && isReadableStreamSupported && test(() => {
14598
16735
  let duplexAccessed = false;
14599
- const hasContentType = new Request(platform_default.origin, {
16736
+ const hasContentType2 = new Request(platform_default.origin, {
14600
16737
  body: new ReadableStream2(),
14601
16738
  method: "POST",
14602
16739
  get duplex() {
@@ -14604,7 +16741,7 @@ var factory = (env2) => {
14604
16741
  return "half";
14605
16742
  }
14606
16743
  }).headers.has("Content-Type");
14607
- return duplexAccessed && !hasContentType;
16744
+ return duplexAccessed && !hasContentType2;
14608
16745
  });
14609
16746
  const supportsResponseStream = isResponseSupported && isReadableStreamSupported && test(() => utils_default.isReadableStream(new Response("").body));
14610
16747
  const resolvers = {
@@ -15358,113 +17495,7 @@ var {
15358
17495
  mergeConfig: mergeConfig2
15359
17496
  } = axios_default;
15360
17497
 
15361
- // src/auth.ts
15362
- async function addAuthToAxiosConfig(config, auth) {
15363
- switch (auth.type) {
15364
- case "bearer": {
15365
- if (auth.getToken) {
15366
- const token = typeof auth.getToken === "function" ? await auth.getToken() : auth.getToken;
15367
- if (token) {
15368
- config.headers.set("Authorization", `Bearer ${token}`);
15369
- }
15370
- }
15371
- break;
15372
- }
15373
- case "api-key": {
15374
- if (auth.apiKey) {
15375
- const headerName = auth.apiKeyHeader ?? "X-API-Key";
15376
- config.headers.set(headerName, auth.apiKey);
15377
- }
15378
- break;
15379
- }
15380
- case "basic": {
15381
- if (auth.username && auth.password) {
15382
- const encoded = btoa(`${auth.username}:${auth.password}`);
15383
- config.headers.set("Authorization", `Basic ${encoded}`);
15384
- }
15385
- break;
15386
- }
15387
- case "custom": {
15388
- if (auth.customAuth) {
15389
- const headers = {};
15390
- await auth.customAuth(headers);
15391
- Object.entries(headers).forEach(([key, value]) => {
15392
- config.headers.set(key, value);
15393
- });
15394
- }
15395
- break;
15396
- }
15397
- }
15398
- }
15399
- async function addAuthToHeaders(headers, auth) {
15400
- switch (auth.type) {
15401
- case "bearer": {
15402
- if (auth.getToken) {
15403
- const token = typeof auth.getToken === "function" ? await auth.getToken() : auth.getToken;
15404
- if (token) {
15405
- headers["Authorization"] = `Bearer ${token}`;
15406
- }
15407
- }
15408
- break;
15409
- }
15410
- case "api-key": {
15411
- if (auth.apiKey) {
15412
- const headerName = auth.apiKeyHeader ?? "X-API-Key";
15413
- headers[headerName] = auth.apiKey;
15414
- }
15415
- break;
15416
- }
15417
- case "basic": {
15418
- if (auth.username && auth.password) {
15419
- const encoded = btoa(`${auth.username}:${auth.password}`);
15420
- headers["Authorization"] = `Basic ${encoded}`;
15421
- }
15422
- break;
15423
- }
15424
- case "custom": {
15425
- if (auth.customAuth) {
15426
- await auth.customAuth(headers);
15427
- }
15428
- break;
15429
- }
15430
- }
15431
- }
15432
-
15433
- // src/utils.ts
15434
- function generateRequestId() {
15435
- return `req_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 9)}`;
15436
- }
15437
- function sleep(ms) {
15438
- return new Promise((resolve) => setTimeout(resolve, ms));
15439
- }
15440
- function calculateRetryDelay(retry, attempt) {
15441
- let delay;
15442
- switch (retry.backoff) {
15443
- case "fixed":
15444
- delay = retry.initialDelay;
15445
- break;
15446
- case "linear":
15447
- delay = retry.initialDelay * (attempt + 1);
15448
- break;
15449
- case "exponential":
15450
- default:
15451
- delay = retry.initialDelay * Math.pow(2, attempt);
15452
- break;
15453
- }
15454
- const jitter = delay * 0.1 * Math.random();
15455
- delay += jitter;
15456
- return Math.min(delay, retry.maxDelay);
15457
- }
15458
-
15459
- // src/axios-instance.ts
15460
- function shouldRetryAxios(error, retry) {
15461
- if (!error.response) {
15462
- return retry.retryOnNetworkError !== false;
15463
- }
15464
- const status = error.response.status;
15465
- const retryableCodes = retry.retryableStatusCodes ?? [429, 500, 502, 503, 504];
15466
- return retryableCodes.includes(status);
15467
- }
17498
+ // src/clients/axios-client.ts
15468
17499
  function createAxiosInstance(config) {
15469
17500
  const instance = axios_default.create({
15470
17501
  baseURL: config.baseUrl,
@@ -15475,248 +17506,644 @@ function createAxiosInstance(config) {
15475
17506
  ...config.headers
15476
17507
  }
15477
17508
  });
17509
+ const authenticator = config.auth ? createAuthenticatorFromConfig(config.auth) : noAuthenticator;
17510
+ const logger = config.logger;
17511
+ const debug = config.debug ?? false;
15478
17512
  instance.interceptors.request.use(
15479
17513
  async (axiosConfig) => {
17514
+ axiosConfig.__startTime = Date.now();
15480
17515
  const requestId = generateRequestId();
17516
+ const traceId = generateTraceId();
17517
+ axiosConfig.__requestId = requestId;
17518
+ axiosConfig.__traceId = traceId;
15481
17519
  axiosConfig.headers.set("X-Request-ID", requestId);
15482
- if (config.auth) {
15483
- await addAuthToAxiosConfig(axiosConfig, config.auth);
17520
+ axiosConfig.headers.set("X-Trace-ID", traceId);
17521
+ const headers = {};
17522
+ await authenticator.authenticate(headers);
17523
+ for (const [key, value] of Object.entries(headers)) {
17524
+ axiosConfig.headers.set(key, value);
17525
+ }
17526
+ if (config.requestInterceptors) {
17527
+ await executeRequestInterceptors(config.requestInterceptors, axiosConfig);
17528
+ }
17529
+ if (debug && logger) {
17530
+ logger.debug(`[Request] ${axiosConfig.method?.toUpperCase()} ${axiosConfig.url}`, {
17531
+ requestId,
17532
+ headers: Object.fromEntries(
17533
+ Object.entries(axiosConfig.headers).filter(([, v]) => typeof v === "string")
17534
+ )
17535
+ });
15484
17536
  }
15485
17537
  return axiosConfig;
15486
17538
  },
15487
17539
  (error) => Promise.reject(error)
15488
17540
  );
15489
17541
  instance.interceptors.response.use(
15490
- (response) => response,
17542
+ async (response) => {
17543
+ const axiosConfig = response.config;
17544
+ const duration = Date.now() - (axiosConfig.__startTime ?? Date.now());
17545
+ if (debug && logger) {
17546
+ logger.debug(
17547
+ `[Response] ${axiosConfig.method?.toUpperCase()} ${axiosConfig.url} - ${response.status} (${duration}ms)`,
17548
+ {
17549
+ requestId: axiosConfig.__requestId,
17550
+ status: response.status,
17551
+ duration
17552
+ }
17553
+ );
17554
+ }
17555
+ if (config.responseInterceptors) {
17556
+ await executeResponseInterceptors(config.responseInterceptors, response);
17557
+ }
17558
+ return response;
17559
+ },
15491
17560
  async (error) => {
15492
- if (config.retry && shouldRetryAxios(error, config.retry)) {
15493
- const errorConfig = error.config;
15494
- const retryCount = errorConfig?.__retryCount ?? 0;
17561
+ const axiosConfig = error.config;
17562
+ const duration = Date.now() - (axiosConfig?.__startTime ?? Date.now());
17563
+ const customError = transformAxiosError(error);
17564
+ if (logger) {
17565
+ logger.error(
17566
+ `[Error] ${axiosConfig?.method?.toUpperCase()} ${axiosConfig?.url} - ${customError.message} (${duration}ms)`,
17567
+ {
17568
+ requestId: axiosConfig?.__requestId,
17569
+ error: customError.message,
17570
+ duration
17571
+ }
17572
+ );
17573
+ }
17574
+ if (config.errorInterceptors) {
17575
+ const recovered = await executeErrorInterceptors(
17576
+ config.errorInterceptors,
17577
+ customError,
17578
+ axiosConfig
17579
+ );
17580
+ if (recovered) {
17581
+ return recovered;
17582
+ }
17583
+ }
17584
+ if (config.enableRetry !== false && config.retry && shouldRetry(error, config.retry)) {
17585
+ const retryCount = axiosConfig?.__retryCount ?? 0;
15495
17586
  if (retryCount < config.retry.maxRetries) {
15496
- const delay = calculateRetryDelay(config.retry, retryCount);
15497
- await sleep(delay);
15498
- if (errorConfig) {
15499
- errorConfig.__retryCount = retryCount + 1;
15500
- return instance.request(errorConfig);
17587
+ let delayMs = calculateRetryDelay(config.retry, retryCount);
17588
+ if (config.retry.respectRetryAfter !== false && error.response) {
17589
+ const retryAfter = parseRetryAfter(
17590
+ error.response.headers["retry-after"]
17591
+ );
17592
+ if (retryAfter !== void 0) {
17593
+ delayMs = Math.min(retryAfter * 1e3, config.retry.maxDelayMs);
17594
+ }
17595
+ }
17596
+ if (config.retry.onRetry) {
17597
+ config.retry.onRetry({
17598
+ attempt: retryCount + 1,
17599
+ maxRetries: config.retry.maxRetries,
17600
+ delayMs,
17601
+ error: customError,
17602
+ url: axiosConfig?.url ?? "",
17603
+ method: axiosConfig?.method?.toUpperCase() ?? "GET"
17604
+ });
17605
+ }
17606
+ if (debug && logger) {
17607
+ logger.debug(
17608
+ `[Retry] ${axiosConfig?.method?.toUpperCase()} ${axiosConfig?.url} - attempt ${retryCount + 1}/${config.retry.maxRetries}, delay ${delayMs}ms`
17609
+ );
17610
+ }
17611
+ await sleep(delayMs);
17612
+ if (axiosConfig) {
17613
+ axiosConfig.__retryCount = retryCount + 1;
17614
+ return instance.request(axiosConfig);
15501
17615
  }
15502
17616
  }
15503
17617
  }
15504
- return Promise.reject(error);
17618
+ return Promise.reject(customError);
15505
17619
  }
15506
17620
  );
15507
17621
  return instance;
15508
17622
  }
15509
-
15510
- // src/http-client.ts
15511
- var HttpClient = class {
15512
- constructor(config) {
15513
- this.config = {
15514
- timeout: 3e4,
15515
- headers: {},
15516
- ...config
17623
+ async function executeRequestInterceptors(interceptors, axiosConfig) {
17624
+ const sorted = [...interceptors].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
17625
+ for (const interceptor of sorted) {
17626
+ const context = {
17627
+ requestId: axiosConfig.__requestId ?? "",
17628
+ traceId: axiosConfig.__traceId,
17629
+ startTime: axiosConfig.__startTime ?? Date.now(),
17630
+ retryCount: axiosConfig.__retryCount ?? 0,
17631
+ originalOptions: {
17632
+ method: axiosConfig.method?.toUpperCase() ?? "GET",
17633
+ path: axiosConfig.url ?? ""
17634
+ },
17635
+ options: {
17636
+ method: axiosConfig.method?.toUpperCase() ?? "GET",
17637
+ path: axiosConfig.url ?? "",
17638
+ headers: Object.fromEntries(
17639
+ Object.entries(axiosConfig.headers).filter(([, v]) => typeof v === "string")
17640
+ ),
17641
+ body: axiosConfig.data,
17642
+ timeout: axiosConfig.timeout,
17643
+ metadata: {}
17644
+ },
17645
+ url: `${axiosConfig.baseURL ?? ""}${axiosConfig.url ?? ""}`,
17646
+ metadata: {}
15517
17647
  };
17648
+ const result = await interceptor.intercept(context);
17649
+ if (result.headers) {
17650
+ for (const [key, value] of Object.entries(result.headers)) {
17651
+ axiosConfig.headers.set(key, value);
17652
+ }
17653
+ }
17654
+ if (result.timeout !== void 0) {
17655
+ axiosConfig.timeout = result.timeout;
17656
+ }
15518
17657
  }
15519
- /**
15520
- * 发起请求
15521
- */
15522
- async request(options) {
15523
- let opts = { ...options };
15524
- for (const interceptor of this.config.onRequest || []) {
15525
- opts = await interceptor(opts);
15526
- }
15527
- const url2 = this.buildUrl(opts.path, opts.query);
15528
- const headers = await this.buildHeaders(opts);
15529
- const body = opts.body ? JSON.stringify(opts.body) : void 0;
15530
- const response = await this.executeWithRetry(
15531
- url2,
15532
- {
15533
- method: opts.method,
15534
- headers,
15535
- body,
15536
- timeout: opts.timeout || this.config.timeout
15537
- },
15538
- opts
15539
- );
15540
- return response;
17658
+ }
17659
+ async function executeResponseInterceptors(interceptors, response) {
17660
+ const sorted = [...interceptors].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
17661
+ const axiosConfig = response.config;
17662
+ for (const interceptor of sorted) {
17663
+ const context = {
17664
+ requestId: axiosConfig.__requestId ?? "",
17665
+ traceId: axiosConfig.__traceId,
17666
+ startTime: axiosConfig.__startTime ?? Date.now(),
17667
+ retryCount: axiosConfig.__retryCount ?? 0,
17668
+ originalOptions: {
17669
+ method: axiosConfig.method?.toUpperCase() ?? "GET",
17670
+ path: axiosConfig.url ?? ""
17671
+ },
17672
+ options: {
17673
+ method: axiosConfig.method?.toUpperCase() ?? "GET",
17674
+ path: axiosConfig.url ?? "",
17675
+ headers: Object.fromEntries(
17676
+ Object.entries(axiosConfig.headers).filter(([, v]) => typeof v === "string")
17677
+ ),
17678
+ body: axiosConfig.data,
17679
+ timeout: axiosConfig.timeout,
17680
+ metadata: {}
17681
+ },
17682
+ url: `${axiosConfig.baseURL ?? ""}${axiosConfig.url ?? ""}`,
17683
+ metadata: {}
17684
+ };
17685
+ const responseData = {
17686
+ data: response.data,
17687
+ status: response.status,
17688
+ statusText: response.statusText,
17689
+ headers: response.headers,
17690
+ requestId: axiosConfig.__requestId ?? "",
17691
+ traceId: axiosConfig.__traceId
17692
+ };
17693
+ await interceptor.intercept(responseData, context);
15541
17694
  }
15542
- /**
15543
- * GET 请求
15544
- */
15545
- async get(path, query) {
15546
- return this.request({ method: "GET", path, query });
17695
+ }
17696
+ async function executeErrorInterceptors(interceptors, error, axiosConfig) {
17697
+ const sorted = [...interceptors].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
17698
+ for (const interceptor of sorted) {
17699
+ const context = {
17700
+ requestId: axiosConfig?.__requestId ?? "",
17701
+ traceId: axiosConfig?.__traceId,
17702
+ startTime: axiosConfig?.__startTime ?? Date.now(),
17703
+ retryCount: axiosConfig?.__retryCount ?? 0,
17704
+ originalOptions: {
17705
+ method: axiosConfig?.method?.toUpperCase() ?? "GET",
17706
+ path: axiosConfig?.url ?? ""
17707
+ },
17708
+ options: {
17709
+ method: axiosConfig?.method?.toUpperCase() ?? "GET",
17710
+ path: axiosConfig?.url ?? "",
17711
+ headers: axiosConfig ? Object.fromEntries(
17712
+ Object.entries(axiosConfig.headers).filter(([, v]) => typeof v === "string")
17713
+ ) : {},
17714
+ body: axiosConfig?.data,
17715
+ timeout: axiosConfig?.timeout,
17716
+ metadata: {}
17717
+ },
17718
+ url: `${axiosConfig?.baseURL ?? ""}${axiosConfig?.url ?? ""}`,
17719
+ metadata: {}
17720
+ };
17721
+ const result = await interceptor.intercept(error, context);
17722
+ if (result !== void 0) {
17723
+ return {
17724
+ data: result.data,
17725
+ status: result.status,
17726
+ statusText: result.statusText,
17727
+ headers: result.headers,
17728
+ config: axiosConfig
17729
+ };
17730
+ }
15547
17731
  }
15548
- /**
15549
- * POST 请求
15550
- */
15551
- async post(path, body, query) {
15552
- return this.request({ method: "POST", path, body, query });
17732
+ return void 0;
17733
+ }
17734
+ function shouldRetry(error, retry) {
17735
+ if (!retry) return false;
17736
+ if (!error.response) {
17737
+ return retry.retryOnNetworkError !== false;
15553
17738
  }
15554
- /**
15555
- * PUT 请求
15556
- */
15557
- async put(path, body) {
15558
- return this.request({ method: "PUT", path, body });
17739
+ const status = error.response.status;
17740
+ const retryableCodes = retry.retryableStatusCodes ?? DEFAULT_RETRY_CONFIG.retryableStatusCodes;
17741
+ return retryableCodes?.includes(status) ?? false;
17742
+ }
17743
+ function transformAxiosError(error) {
17744
+ if (error.code === "ECONNABORTED" || error.code === "ETIMEDOUT") {
17745
+ const timeout = error.config?.timeout ?? 3e4;
17746
+ return new TimeoutError(timeout);
15559
17747
  }
15560
- /**
15561
- * PATCH 请求
15562
- */
15563
- async patch(path, body) {
15564
- return this.request({ method: "PATCH", path, body });
17748
+ if (!error.response) {
17749
+ return new NetworkError(error.message, error);
15565
17750
  }
15566
- /**
15567
- * DELETE 请求
15568
- */
15569
- async delete(path) {
15570
- return this.request({ method: "DELETE", path });
17751
+ const response = error.response;
17752
+ const retryAfter = parseRetryAfter(
17753
+ response.headers["retry-after"]
17754
+ );
17755
+ return ApiError.fromResponse(
17756
+ {
17757
+ code: response.data?.code,
17758
+ message: response.data?.message ?? error.message,
17759
+ details: response.data?.details,
17760
+ requestId: response.data?.requestId ?? error.config?.headers?.["X-Request-ID"],
17761
+ traceId: response.data?.traceId
17762
+ },
17763
+ response.status,
17764
+ retryAfter
17765
+ );
17766
+ }
17767
+
17768
+ // src/clients/middleware-factory.ts
17769
+ function generateUniqueRequestKey() {
17770
+ return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
17771
+ }
17772
+ var REQUEST_KEY_HEADER = "X-Internal-Request-Key";
17773
+ var retryStateMap = /* @__PURE__ */ new Map();
17774
+ function getRequestKey(init) {
17775
+ const headers = init.headers;
17776
+ return headers?.[REQUEST_KEY_HEADER] ?? "";
17777
+ }
17778
+ function createMiddlewares(config = {}) {
17779
+ const middlewares = [];
17780
+ middlewares.push(createRequestMiddleware(config));
17781
+ if (config.logger) {
17782
+ middlewares.push(createLoggingMiddleware(config.logger, config.debug ?? false));
15571
17783
  }
15572
- /**
15573
- * 构建完整 URL
15574
- */
15575
- buildUrl(path, query) {
15576
- const base = this.config.baseUrl.replace(/\/$/, "");
15577
- const pathname = path.startsWith("/") ? path : `/${path}`;
15578
- const url2 = new URL(`${base}${pathname}`);
15579
- if (query) {
15580
- for (const [key, value] of Object.entries(query)) {
15581
- if (value !== void 0) {
15582
- url2.searchParams.set(key, String(value));
15583
- }
15584
- }
15585
- }
15586
- return url2.toString();
17784
+ if (config.enableRetry !== false && config.retry) {
17785
+ middlewares.push(createRetryMiddleware(config));
15587
17786
  }
15588
- /**
15589
- * 构建请求头
15590
- */
15591
- async buildHeaders(options) {
15592
- const headers = {
15593
- "Content-Type": "application/json",
15594
- Accept: "application/json",
15595
- ...this.config.headers,
15596
- ...options.headers
15597
- };
15598
- if (options.context?.requestId) {
15599
- headers["X-Request-ID"] = options.context.requestId;
15600
- } else {
15601
- headers["X-Request-ID"] = generateRequestId();
17787
+ if (config.preMiddlewares?.length) {
17788
+ for (const preFn of config.preMiddlewares) {
17789
+ middlewares.push({ pre: preFn });
15602
17790
  }
15603
- if (options.context?.traceId) {
15604
- headers["X-Trace-ID"] = options.context.traceId;
15605
- }
15606
- if (!options.skipAuth && this.config.auth) {
15607
- await addAuthToHeaders(headers, this.config.auth);
17791
+ }
17792
+ if (config.postMiddlewares?.length) {
17793
+ for (const postFn of config.postMiddlewares) {
17794
+ middlewares.push({ post: postFn });
15608
17795
  }
15609
- return headers;
15610
17796
  }
15611
- /**
15612
- * 带重试的请求执行
15613
- */
15614
- async executeWithRetry(url2, init, options) {
15615
- const retry = this.config.retry || {
15616
- maxRetries: 0,
15617
- initialDelay: 1e3,
15618
- maxDelay: 3e4,
15619
- backoff: "exponential"
15620
- };
15621
- let lastError;
15622
- let attempt = 0;
15623
- while (attempt <= retry.maxRetries) {
15624
- try {
15625
- return await this.execute(url2, init, options);
15626
- } catch (error) {
15627
- lastError = error;
15628
- const shouldRetry = this.shouldRetry(error, retry, attempt);
15629
- if (!shouldRetry) {
15630
- throw error;
15631
- }
15632
- const delay = calculateRetryDelay(retry, attempt);
15633
- await sleep(delay);
15634
- attempt++;
15635
- }
17797
+ if (config.errorMiddlewares?.length) {
17798
+ for (const errorFn of config.errorMiddlewares) {
17799
+ middlewares.push({ onError: errorFn });
15636
17800
  }
15637
- throw lastError;
15638
17801
  }
15639
- /**
15640
- * 执行单次请求
15641
- */
15642
- async execute(url2, init, options) {
15643
- const controller = new AbortController();
15644
- const timeout = init.timeout || 3e4;
15645
- const timeoutId = setTimeout(() => controller.abort(), timeout);
15646
- try {
15647
- const response = await fetch(url2, {
15648
- ...init,
15649
- signal: controller.signal
17802
+ return middlewares;
17803
+ }
17804
+ function createRequestMiddleware(config) {
17805
+ const authenticator = config.auth ? createAuthenticatorFromConfig(config.auth) : noAuthenticator;
17806
+ return {
17807
+ async pre(context) {
17808
+ const requestId = generateRequestId();
17809
+ const traceId = generateTraceId();
17810
+ const requestKey = generateUniqueRequestKey();
17811
+ retryStateMap.set(requestKey, {
17812
+ attempt: 0,
17813
+ startTime: Date.now(),
17814
+ requestId,
17815
+ traceId
15650
17816
  });
15651
- clearTimeout(timeoutId);
15652
- const data = await response.json();
15653
- if (!response.ok || !data.success) {
15654
- const errorResponse = {
15655
- success: false,
15656
- code: data.code || "UNKNOWN_ERROR",
15657
- message: data.message || "Unknown error",
15658
- requestId: data.requestId || generateRequestId(),
15659
- timestamp: data.timestamp || (/* @__PURE__ */ new Date()).toISOString(),
15660
- details: data.details,
15661
- traceId: data.traceId
15662
- };
15663
- const error = new ApiError(errorResponse, response.status);
15664
- for (const interceptor of this.config.onError || []) {
15665
- await interceptor(error, options);
17817
+ const existingHeaders = context.init.headers ?? {};
17818
+ const headers = {};
17819
+ if (existingHeaders instanceof Headers) {
17820
+ existingHeaders.forEach((value, key) => {
17821
+ headers[key] = value;
17822
+ });
17823
+ } else if (Array.isArray(existingHeaders)) {
17824
+ for (const [key, value] of existingHeaders) {
17825
+ headers[key] = value;
15666
17826
  }
15667
- throw error;
15668
- }
15669
- const successResponse = data;
15670
- for (const interceptor of this.config.onResponse || []) {
15671
- await interceptor(successResponse, options);
17827
+ } else {
17828
+ Object.assign(headers, existingHeaders);
17829
+ }
17830
+ headers[REQUEST_KEY_HEADER] = requestKey;
17831
+ headers["X-Request-ID"] = requestId;
17832
+ headers["X-Trace-ID"] = traceId;
17833
+ if (config.headers) {
17834
+ Object.assign(headers, config.headers);
17835
+ }
17836
+ await authenticator.authenticate(headers);
17837
+ return {
17838
+ url: context.url,
17839
+ init: {
17840
+ ...context.init,
17841
+ headers
17842
+ }
17843
+ };
17844
+ }
17845
+ };
17846
+ }
17847
+ function createLoggingMiddleware(logger, debugMode) {
17848
+ return {
17849
+ async pre(context) {
17850
+ if (!debugMode) return void 0;
17851
+ const method = context.init.method ?? "GET";
17852
+ const requestId = context.init.headers?.["X-Request-ID"] ?? "";
17853
+ logger.debug(`[Request] ${method} ${context.url}`, { requestId });
17854
+ return void 0;
17855
+ },
17856
+ async post(context) {
17857
+ const requestKey = getRequestKey(context.init);
17858
+ const state = retryStateMap.get(requestKey);
17859
+ const duration = state ? Date.now() - state.startTime : 0;
17860
+ if (requestKey) {
17861
+ retryStateMap.delete(requestKey);
17862
+ }
17863
+ if (!debugMode) return void 0;
17864
+ const method = context.init.method ?? "GET";
17865
+ const requestId = context.init.headers?.["X-Request-ID"] ?? "";
17866
+ logger.debug(`[Response] ${method} ${context.url} - ${context.response.status} (${duration}ms)`, {
17867
+ requestId,
17868
+ status: context.response.status,
17869
+ duration
17870
+ });
17871
+ return void 0;
17872
+ },
17873
+ async onError(context) {
17874
+ const method = context.init.method ?? "GET";
17875
+ const requestId = context.init.headers?.["X-Request-ID"] ?? "";
17876
+ const requestKey = getRequestKey(context.init);
17877
+ const state = retryStateMap.get(requestKey);
17878
+ const duration = state ? Date.now() - state.startTime : 0;
17879
+ const errorMessage = context.error instanceof Error ? context.error.message : String(context.error);
17880
+ logger.error(`[Error] ${method} ${context.url} - ${errorMessage} (${duration}ms)`, {
17881
+ requestId,
17882
+ error: errorMessage,
17883
+ duration
17884
+ });
17885
+ return void 0;
17886
+ }
17887
+ };
17888
+ }
17889
+ function createRetryMiddleware(config) {
17890
+ const retryConfig = config.retry;
17891
+ const maxRetries = retryConfig.maxRetries;
17892
+ const logger = config.logger;
17893
+ const debug = config.debug ?? false;
17894
+ return {
17895
+ async onError(context) {
17896
+ const requestKey = getRequestKey(context.init);
17897
+ const state = retryStateMap.get(requestKey);
17898
+ if (!state) {
17899
+ return void 0;
17900
+ }
17901
+ if (!shouldRetry2(context.error, state.attempt, maxRetries, retryConfig)) {
17902
+ retryStateMap.delete(requestKey);
17903
+ return void 0;
17904
+ }
17905
+ state.attempt++;
17906
+ const delay = calculateRetryDelay2(state.attempt, retryConfig);
17907
+ if (retryConfig.onRetry) {
17908
+ const method = context.init.method ?? "GET";
17909
+ retryConfig.onRetry({
17910
+ attempt: state.attempt,
17911
+ maxRetries,
17912
+ delayMs: delay,
17913
+ error: context.error instanceof Error ? context.error : new Error(String(context.error)),
17914
+ url: context.url,
17915
+ method
17916
+ });
15672
17917
  }
15673
- return successResponse.data;
15674
- } catch (error) {
15675
- clearTimeout(timeoutId);
15676
- if (error instanceof ApiError) {
15677
- throw error;
17918
+ if (debug && logger) {
17919
+ const method = context.init.method ?? "GET";
17920
+ logger.debug(`[Retry] ${method} ${context.url} - attempt ${state.attempt}/${maxRetries}, delay ${delay}ms`);
15678
17921
  }
15679
- if (error.name === "AbortError") {
15680
- throw new TimeoutError(timeout);
17922
+ await sleep(delay);
17923
+ try {
17924
+ const response = await context.fetch(context.url, context.init);
17925
+ if (!response.ok && shouldRetryStatus(response.status, state.attempt, maxRetries, retryConfig)) {
17926
+ state.attempt++;
17927
+ const nextDelay = calculateRetryDelay2(state.attempt, retryConfig);
17928
+ if (debug && logger) {
17929
+ const method = context.init.method ?? "GET";
17930
+ logger.debug(`[Retry] ${method} ${context.url} - status ${response.status}, attempt ${state.attempt}/${maxRetries}, delay ${nextDelay}ms`);
17931
+ }
17932
+ await sleep(nextDelay);
17933
+ return context.fetch(context.url, context.init);
17934
+ }
17935
+ retryStateMap.delete(requestKey);
17936
+ return response;
17937
+ } catch (retryError) {
17938
+ if (state.attempt < maxRetries) {
17939
+ throw retryError;
17940
+ }
17941
+ retryStateMap.delete(requestKey);
17942
+ throw retryError;
15681
17943
  }
15682
- throw new NetworkError(error.message, error);
15683
17944
  }
17945
+ };
17946
+ }
17947
+ function shouldRetry2(error, attempt, maxRetries, retryConfig) {
17948
+ if (attempt >= maxRetries) return false;
17949
+ if (error instanceof Error && error.name === "AbortError") {
17950
+ return false;
15684
17951
  }
15685
- /**
15686
- * 判断是否应该重试
15687
- */
15688
- shouldRetry(error, retry, attempt) {
15689
- if (attempt >= retry.maxRetries) {
15690
- return false;
15691
- }
15692
- if (error instanceof TimeoutError || error instanceof NetworkError) {
15693
- return retry.retryOnNetworkError !== false;
17952
+ if (error instanceof TypeError || error instanceof NetworkError) {
17953
+ return retryConfig.retryOnNetworkError !== false;
17954
+ }
17955
+ if (error instanceof TimeoutError) {
17956
+ return retryConfig.retryOnTimeout !== false;
17957
+ }
17958
+ return true;
17959
+ }
17960
+ function shouldRetryStatus(status, attempt, maxRetries, retryConfig) {
17961
+ if (attempt >= maxRetries) return false;
17962
+ const retryableCodes = retryConfig.retryableStatusCodes ?? [429, 500, 502, 503, 504];
17963
+ return retryableCodes.includes(status);
17964
+ }
17965
+ function calculateRetryDelay2(attempt, retryConfig) {
17966
+ const {
17967
+ initialDelayMs = 1e3,
17968
+ maxDelayMs = 3e4,
17969
+ backoffStrategy = "exponential",
17970
+ jitterFactor = 0.1
17971
+ } = retryConfig;
17972
+ let delay;
17973
+ switch (backoffStrategy) {
17974
+ case "fixed":
17975
+ delay = initialDelayMs;
17976
+ break;
17977
+ case "linear":
17978
+ delay = initialDelayMs * attempt;
17979
+ break;
17980
+ case "exponential":
17981
+ default:
17982
+ delay = initialDelayMs * Math.pow(2, attempt - 1);
17983
+ break;
17984
+ }
17985
+ delay = Math.min(delay, maxDelayMs);
17986
+ if (jitterFactor > 0) {
17987
+ const jitter = delay * jitterFactor * (Math.random() * 2 - 1);
17988
+ delay = Math.max(0, delay + jitter);
17989
+ }
17990
+ return Math.round(delay);
17991
+ }
17992
+ function createAuthMiddleware(authConfig) {
17993
+ const authenticator = createAuthenticatorFromConfig(authConfig);
17994
+ return {
17995
+ async pre(context) {
17996
+ const headers = {};
17997
+ const existingHeaders = context.init.headers ?? {};
17998
+ if (existingHeaders instanceof Headers) {
17999
+ existingHeaders.forEach((value, key) => {
18000
+ headers[key] = value;
18001
+ });
18002
+ } else if (Array.isArray(existingHeaders)) {
18003
+ for (const [key, value] of existingHeaders) {
18004
+ headers[key] = value;
18005
+ }
18006
+ } else {
18007
+ Object.assign(headers, existingHeaders);
18008
+ }
18009
+ await authenticator.authenticate(headers);
18010
+ return {
18011
+ url: context.url,
18012
+ init: {
18013
+ ...context.init,
18014
+ headers
18015
+ }
18016
+ };
15694
18017
  }
15695
- if (error instanceof ApiError) {
15696
- const retryableCodes = retry.retryableStatusCodes || [429, 500, 502, 503, 504];
15697
- return error.retryable || retryableCodes.includes(error.statusCode);
18018
+ };
18019
+ }
18020
+ function createTrackingMiddleware() {
18021
+ return {
18022
+ async pre(context) {
18023
+ const requestId = generateRequestId();
18024
+ const traceId = generateTraceId();
18025
+ const headers = {};
18026
+ const existingHeaders = context.init.headers ?? {};
18027
+ if (existingHeaders instanceof Headers) {
18028
+ existingHeaders.forEach((value, key) => {
18029
+ headers[key] = value;
18030
+ });
18031
+ } else if (Array.isArray(existingHeaders)) {
18032
+ for (const [key, value] of existingHeaders) {
18033
+ headers[key] = value;
18034
+ }
18035
+ } else {
18036
+ Object.assign(headers, existingHeaders);
18037
+ }
18038
+ headers["X-Request-ID"] = requestId;
18039
+ headers["X-Trace-ID"] = traceId;
18040
+ return {
18041
+ url: context.url,
18042
+ init: {
18043
+ ...context.init,
18044
+ headers
18045
+ }
18046
+ };
15698
18047
  }
15699
- return false;
15700
- }
15701
- };
15702
- function createClient(config) {
15703
- return new HttpClient(config);
18048
+ };
15704
18049
  }
15705
18050
 
15706
18051
  // src/index.ts
15707
18052
  var VERSION3 = "2.0.0";
18053
+ var SDK_NAME = "@djvlc/openapi-client-core";
18054
+ function getSdkInfo() {
18055
+ return { name: SDK_NAME, version: VERSION3 };
18056
+ }
15708
18057
  // Annotate the CommonJS export names for ESM import in node:
15709
18058
  0 && (module.exports = {
18059
+ AbortError,
15710
18060
  ApiError,
15711
- HttpClient,
18061
+ ApiKeyAuthenticator,
18062
+ AuthInterceptor,
18063
+ BaseClient,
18064
+ BaseClientError,
18065
+ BasicAuthenticator,
18066
+ BearerAuthenticator,
18067
+ BufferLogger,
18068
+ ConsoleLogger,
18069
+ CustomAuthenticator,
18070
+ DEFAULT_HEADERS,
18071
+ DEFAULT_RETRY_CONFIG,
18072
+ DefaultMetricsCollector,
18073
+ ErrorTransformInterceptor,
18074
+ FetchClient,
18075
+ InterceptorManager,
18076
+ LOG_LEVEL_PRIORITY,
18077
+ LoggingInterceptor,
18078
+ MetricsErrorInterceptor,
18079
+ MetricsRequestInterceptor,
18080
+ MetricsResponseInterceptor,
15712
18081
  NetworkError,
18082
+ NoAuthenticator,
18083
+ ReportingInterceptor,
18084
+ RequestDeduper,
18085
+ RequestIdInterceptor,
18086
+ RetryInterceptor,
18087
+ SDK_NAME,
18088
+ SilentLogger,
15713
18089
  TimeoutError,
18090
+ TimeoutInterceptor,
18091
+ TokenRefreshInterceptor,
18092
+ TraceInterceptor,
15714
18093
  VERSION,
18094
+ buildUrl,
15715
18095
  calculateRetryDelay,
18096
+ createApiKeyAuthenticator,
18097
+ createAuthInterceptor,
18098
+ createAuthMiddleware,
18099
+ createAuthenticatorFromConfig,
15716
18100
  createAxiosInstance,
15717
- createClient,
18101
+ createBasicAuthenticator,
18102
+ createBearerAuthenticator,
18103
+ createBufferLogger,
18104
+ createConsoleLogger,
18105
+ createCustomAuthenticator,
18106
+ createErrorTransformInterceptor,
18107
+ createFetchClient,
18108
+ createInterceptorManager,
18109
+ createLoggingInterceptor,
18110
+ createMetricsCollector,
18111
+ createMetricsInterceptors,
18112
+ createMiddlewares,
18113
+ createNoAuthenticator,
18114
+ createReportingInterceptor,
18115
+ createRequestDeduper,
18116
+ createRequestIdInterceptor,
18117
+ createRetryInterceptor,
18118
+ createSilentLogger,
18119
+ createTimeoutInterceptor,
18120
+ createTokenRefreshInterceptor,
18121
+ createTraceInterceptor,
18122
+ createTrackingMiddleware,
18123
+ extractPath,
18124
+ extractResponseHeaders,
15718
18125
  generateRequestId,
15719
- sleep
18126
+ generateTraceId,
18127
+ getErrorType,
18128
+ getHeader,
18129
+ getRecommendedRetryDelay,
18130
+ getRetryDelay,
18131
+ getSdkInfo,
18132
+ hasContentType,
18133
+ isClientError,
18134
+ isRetryableError,
18135
+ isValidRequestId,
18136
+ isValidTraceId,
18137
+ joinPaths,
18138
+ mergeHeaders,
18139
+ noAuthenticator,
18140
+ parseQueryString,
18141
+ parseRetryAfter,
18142
+ removeHeader,
18143
+ setHeader,
18144
+ silentLogger,
18145
+ sleep,
18146
+ sleepWithAbort
15720
18147
  });
15721
18148
  /*! Bundled license information:
15722
18149
 
@@ -15736,4 +18163,3 @@ mime-types/index.js:
15736
18163
  * MIT Licensed
15737
18164
  *)
15738
18165
  */
15739
- //# sourceMappingURL=index.js.map