@longzai-intelligence-transport/http-core 0.1.0 → 0.1.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.d.ts CHANGED
@@ -430,18 +430,48 @@ type RequestConfig = {
430
430
  withCsrf?: boolean;
431
431
  };
432
432
  /**
433
- * 路由定义类型
433
+ * 流式响应元数据
434
+ *
435
+ * 描述二进制流响应(文件下载、图片返回等)的附加信息,供 OpenAPI 文档生成、
436
+ * 响应头设置和客户端下载命名使用。
437
+ */
438
+ type StreamResponseMeta = {
439
+ /**
440
+ * MIME 类型,如 application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;
441
+ * 省略时按 application/octet-stream 处理
442
+ */
443
+ mimeType?: string;
444
+ /**
445
+ * 建议下载文件名,用于 Content-Disposition 响应头
446
+ */
447
+ fileName?: string;
448
+ /**
449
+ * 文件大小(字节),可选,用于 Content-Length
450
+ */
451
+ fileSize?: number;
452
+ };
453
+ /**
454
+ * 平台无关的二进制流响应标记类型
455
+ *
456
+ * core 层不绑定具体运行时(StreamableFile / ReadableStream / Blob),
457
+ * 各 adapter 通过 InferStreamRouteResponse<T> 将其映射为平台具体类型。
458
+ * phantom 类型,不含运行时数据,仅供类型推导占位。
459
+ */
460
+ type BinaryStreamMarker = {
461
+ readonly __binaryStreamResponse: unique symbol;
462
+ };
463
+ /**
464
+ * 路由基础定义
434
465
  *
435
- * 描述一个 API 路由的完整契约,包括方法、路径、参数、请求体和响应
466
+ * 承载与响应形态无关的公共字段,由 JsonResponseRoute 与 StreamResponseRoute 复用。
436
467
  *
437
468
  * @typeParam TMethod - HTTP 方法类型
438
469
  * @typeParam TPath - 路径模板字符串
439
470
  * @typeParam TParams - 路径参数 Zod Schema
440
471
  * @typeParam TQuery - 查询参数 Zod Schema
441
472
  * @typeParam TBody - 请求体 Zod Schema
442
- * @typeParam TResponse - 响应 Zod Schema
443
473
  */
444
- type RouteDefinition<TMethod extends HttpMethod = HttpMethod, TPath extends string = string, TParams extends ZodType | undefined = ZodType | undefined, TQuery extends ZodType | undefined = ZodType | undefined, TBody extends ZodType | undefined = ZodType | undefined, TResponse extends ZodType = ZodType> = {
474
+ type RouteBaseDef<TMethod extends HttpMethod = HttpMethod, TPath extends string = string, TParams extends ZodType | undefined = ZodType | undefined, TQuery extends ZodType | undefined = ZodType | undefined, TBody extends ZodType | undefined = ZodType | undefined> = {
445
475
  /**
446
476
  * HTTP 方法
447
477
  */
@@ -462,10 +492,6 @@ type RouteDefinition<TMethod extends HttpMethod = HttpMethod, TPath extends stri
462
492
  * 请求体 Schema
463
493
  */
464
494
  body?: TBody;
465
- /**
466
- * 响应 Schema
467
- */
468
- response: TResponse;
469
495
  /**
470
496
  * 接口摘要描述
471
497
  */
@@ -493,36 +519,104 @@ type RouteDefinition<TMethod extends HttpMethod = HttpMethod, TPath extends stri
493
519
  */
494
520
  basePath?: string;
495
521
  };
522
+ /**
523
+ * JSON 响应路由
524
+ *
525
+ * 响应经 ApiResponse<T> 包装的 JSON 信封,response 字段为必填 Zod Schema,
526
+ * 描述 ApiResponse<T> 中的 T。responseType 默认 'json',现有路由字面量无需显式声明。
527
+ *
528
+ * @typeParam TMethod - HTTP 方法类型
529
+ * @typeParam TPath - 路径模板字符串
530
+ * @typeParam TParams - 路径参数 Zod Schema
531
+ * @typeParam TQuery - 查询参数 Zod Schema
532
+ * @typeParam TBody - 请求体 Zod Schema
533
+ * @typeParam TResponse - 响应 Zod Schema
534
+ */
535
+ type JsonResponseRoute<TMethod extends HttpMethod = HttpMethod, TPath extends string = string, TParams extends ZodType | undefined = ZodType | undefined, TQuery extends ZodType | undefined = ZodType | undefined, TBody extends ZodType | undefined = ZodType | undefined, TResponse extends ZodType = ZodType> = RouteBaseDef<TMethod, TPath, TParams, TQuery, TBody> & {
536
+ /**
537
+ * 响应类型标记,默认 'json' 可省略
538
+ */
539
+ responseType?: 'json';
540
+ /**
541
+ * 响应 Schema,描述 ApiResponse<T> 中的 T
542
+ */
543
+ response: TResponse;
544
+ };
545
+ /**
546
+ * 流式响应路由
547
+ *
548
+ * 响应为二进制流(文件下载、图片返回等),无 Zod Schema。
549
+ * responseType 必填 'stream',stream 字段描述响应元数据。
550
+ *
551
+ * @typeParam TMethod - HTTP 方法类型
552
+ * @typeParam TPath - 路径模板字符串
553
+ * @typeParam TParams - 路径参数 Zod Schema
554
+ * @typeParam TQuery - 查询参数 Zod Schema
555
+ * @typeParam TBody - 请求体 Zod Schema
556
+ */
557
+ type StreamResponseRoute<TMethod extends HttpMethod = HttpMethod, TPath extends string = string, TParams extends ZodType | undefined = ZodType | undefined, TQuery extends ZodType | undefined = ZodType | undefined, TBody extends ZodType | undefined = ZodType | undefined> = RouteBaseDef<TMethod, TPath, TParams, TQuery, TBody> & {
558
+ /**
559
+ * 响应类型标记:二进制流,显式必填
560
+ */
561
+ responseType: 'stream';
562
+ /**
563
+ * 流式响应元数据
564
+ */
565
+ stream: StreamResponseMeta;
566
+ };
567
+ /**
568
+ * 路由定义类型
569
+ *
570
+ * 描述一个 API 路由的完整契约,包括方法、路径、参数、请求体和响应。
571
+ * 为 JsonResponseRoute 与 StreamResponseRoute 的 discriminated union,
572
+ * 通过 responseType 字段判别。现有 JSON 路由字面量(无 responseType 字段)
573
+ * 自动归属 JsonResponseRoute 分支。
574
+ *
575
+ * @typeParam TMethod - HTTP 方法类型
576
+ * @typeParam TPath - 路径模板字符串
577
+ * @typeParam TParams - 路径参数 Zod Schema
578
+ * @typeParam TQuery - 查询参数 Zod Schema
579
+ * @typeParam TBody - 请求体 Zod Schema
580
+ * @typeParam TResponse - 响应 Zod Schema(仅 JsonResponseRoute 分支使用)
581
+ */
582
+ type RouteDefinition<TMethod extends HttpMethod = HttpMethod, TPath extends string = string, TParams extends ZodType | undefined = ZodType | undefined, TQuery extends ZodType | undefined = ZodType | undefined, TBody extends ZodType | undefined = ZodType | undefined, TResponse extends ZodType = ZodType> = JsonResponseRoute<TMethod, TPath, TParams, TQuery, TBody, TResponse> | StreamResponseRoute<TMethod, TPath, TParams, TQuery, TBody>;
496
583
  /**
497
584
  * 从路由定义中推断路径参数类型
498
585
  *
586
+ * 使用位置泛型匹配直接捕获 TParams 参数,避免结构属性匹配中
587
+ * 可选属性 `?` 剥离联合类型中 `undefined` 导致的推断偏差。
588
+ *
499
589
  * @example
500
590
  * type Params = InferRouteParams<typeof routes.detail>;
501
591
  * // { id: string }
502
592
  *
503
593
  * @typeParam T - 路由定义类型
504
594
  */
505
- type InferRouteParams<T extends RouteDefinition> = T extends RouteDefinition<HttpMethod, string, infer P, ZodType | undefined, ZodType | undefined, ZodType> ? [P] extends [ZodType] ? P['_output'] : undefined : undefined;
595
+ type InferRouteParams<T extends RouteDefinition> = T extends JsonResponseRoute<HttpMethod, string, infer P, ZodType | undefined, ZodType | undefined, ZodType> ? [P] extends [ZodType] ? P['_output'] : undefined : T extends StreamResponseRoute<HttpMethod, string, infer P, ZodType | undefined, ZodType | undefined> ? [P] extends [ZodType] ? P['_output'] : undefined : undefined;
506
596
  /**
507
597
  * 从路由定义中推断查询参数类型
508
598
  *
599
+ * 使用位置泛型匹配直接捕获 TQuery 参数。
600
+ *
509
601
  * @example
510
602
  * type Query = InferRouteQuery<typeof routes.list>;
511
603
  * // { page?: number; pageSize?: number }
512
604
  *
513
605
  * @typeParam T - 路由定义类型
514
606
  */
515
- type InferRouteQuery<T extends RouteDefinition> = T extends RouteDefinition<HttpMethod, string, ZodType | undefined, infer Q, ZodType | undefined, ZodType> ? [Q] extends [ZodType] ? Q['_output'] : undefined : undefined;
607
+ type InferRouteQuery<T extends RouteDefinition> = T extends JsonResponseRoute<HttpMethod, string, ZodType | undefined, infer Q, ZodType | undefined, ZodType> ? [Q] extends [ZodType] ? Q['_output'] : undefined : T extends StreamResponseRoute<HttpMethod, string, ZodType | undefined, infer Q, ZodType | undefined> ? [Q] extends [ZodType] ? Q['_output'] : undefined : undefined;
516
608
  /**
517
609
  * 从路由定义中推断请求体类型
518
610
  *
611
+ * 使用位置泛型匹配直接捕获 TBody 参数。
612
+ *
519
613
  * @example
520
614
  * type Body = InferRouteBody<typeof routes.create>;
521
615
  * // { name: string; price: number }
522
616
  *
523
617
  * @typeParam T - 路由定义类型
524
618
  */
525
- type InferRouteBody<T extends RouteDefinition> = T extends RouteDefinition<HttpMethod, string, ZodType | undefined, ZodType | undefined, infer B, ZodType> ? [B] extends [ZodType] ? B['_output'] : undefined : undefined;
619
+ type InferRouteBody<T extends RouteDefinition> = T extends JsonResponseRoute<HttpMethod, string, ZodType | undefined, ZodType | undefined, infer B, ZodType> ? [B] extends [ZodType] ? B['_output'] : undefined : T extends StreamResponseRoute<HttpMethod, string, ZodType | undefined, ZodType | undefined, infer B> ? [B] extends [ZodType] ? B['_output'] : undefined : undefined;
526
620
  /**
527
621
  * 从路由定义中推断响应数据类型
528
622
  *
@@ -534,7 +628,11 @@ type InferRouteBody<T extends RouteDefinition> = T extends RouteDefinition<HttpM
534
628
  *
535
629
  * @typeParam T - 路由定义类型
536
630
  */
537
- type InferRouteResponse<T extends RouteDefinition> = T extends RouteDefinition<HttpMethod, string, ZodType | undefined, ZodType | undefined, ZodType | undefined, infer R> ? [R] extends [ZodType] ? ExtractData<R['_output']> : never : never;
631
+ type InferRouteResponse<T extends RouteDefinition> = T extends {
632
+ responseType: 'stream';
633
+ } ? BinaryStreamMarker : T extends {
634
+ response: infer R;
635
+ } ? R extends ZodType ? ExtractData<R['_output']> : never : never;
538
636
  /**
539
637
  * 从路由定义中推断完整的响应类型
540
638
  *
@@ -546,7 +644,11 @@ type InferRouteResponse<T extends RouteDefinition> = T extends RouteDefinition<H
546
644
  *
547
645
  * @typeParam T - 路由定义类型
548
646
  */
549
- type InferRouteFullResponse<T extends RouteDefinition> = T extends RouteDefinition<HttpMethod, string, ZodType | undefined, ZodType | undefined, ZodType | undefined, infer R> ? [R] extends [ZodType] ? ApiResponse<ExtractData<R['_output']>> : never : never;
647
+ type InferRouteFullResponse<T extends RouteDefinition> = T extends {
648
+ responseType: 'stream';
649
+ } ? BinaryStreamMarker : T extends {
650
+ response: infer R;
651
+ } ? R extends ZodType ? ApiResponse<ExtractData<R['_output']>> : never : never;
550
652
  /**
551
653
  * 从路由定义中推断分页响应的项类型
552
654
  *
@@ -1764,6 +1866,56 @@ type DefineRouteConfig<TMethod extends HttpMethod, TPath extends string, TParams
1764
1866
  */
1765
1867
  tags?: string[];
1766
1868
  };
1869
+ /**
1870
+ * 流式路由配置类型
1871
+ *
1872
+ * 用于 defineRoute 创建二进制流响应路由,responseType 必填 'stream',
1873
+ * stream 字段描述响应元数据,无 response Zod Schema。
1874
+ *
1875
+ * @typeParam TMethod - HTTP 方法类型
1876
+ * @typeParam TPath - 路径模板字符串
1877
+ * @typeParam TParams - 路径参数 Schema 类型
1878
+ * @typeParam TQuery - 查询参数 Schema 类型
1879
+ * @typeParam TBody - 请求体 Schema 类型
1880
+ */
1881
+ type StreamRouteDefineConfig<TMethod extends HttpMethod, TPath extends string, TParams extends ZodType | undefined, TQuery extends ZodType | undefined, TBody extends ZodType | undefined> = {
1882
+ /**
1883
+ * HTTP 请求方法
1884
+ */
1885
+ method: TMethod;
1886
+ /**
1887
+ * API 路径模板
1888
+ */
1889
+ path: TPath;
1890
+ /**
1891
+ * 路径参数 Schema
1892
+ */
1893
+ params?: TParams;
1894
+ /**
1895
+ * 查询参数 Schema
1896
+ */
1897
+ query?: TQuery;
1898
+ /**
1899
+ * 请求体 Schema
1900
+ */
1901
+ body?: TBody;
1902
+ /**
1903
+ * 响应类型标记:二进制流,显式必填
1904
+ */
1905
+ responseType: 'stream';
1906
+ /**
1907
+ * 流式响应元数据
1908
+ */
1909
+ stream: StreamResponseMeta;
1910
+ /**
1911
+ * 接口描述信息
1912
+ */
1913
+ summary?: string;
1914
+ /**
1915
+ * 接口标签
1916
+ */
1917
+ tags?: string[];
1918
+ };
1767
1919
  /**
1768
1920
  * 定义 API 路由
1769
1921
  *
@@ -1789,7 +1941,31 @@ type DefineRouteConfig<TMethod extends HttpMethod, TPath extends string, TParams
1789
1941
  * @returns 类型安全的路由定义
1790
1942
  * @throws {@link Error} 当路由定义创建失败时抛出错误
1791
1943
  */
1792
- declare function defineRoute<TMethod extends HttpMethod, TPath extends string, TParams extends ZodType | undefined, TQuery extends ZodType | undefined, TBody extends ZodType | undefined, TResponse extends ZodType>(config: DefineRouteConfig<TMethod, TPath, TParams, TQuery, TBody, TResponse>): RouteDefinition<TMethod, TPath, TParams, TQuery, TBody, TResponse>;
1944
+ /**
1945
+ * defineRoute 重载:流式响应路由
1946
+ *
1947
+ * config 包含 responseType: 'stream' 与 stream 元数据,返回 StreamResponseRoute。
1948
+ *
1949
+ * @typeParam TMethod - HTTP 方法类型
1950
+ * @typeParam TPath - 路径模板字符串
1951
+ * @typeParam TParams - 路径参数 Schema 类型
1952
+ * @typeParam TQuery - 查询参数 Schema 类型
1953
+ * @typeParam TBody - 请求体 Schema 类型
1954
+ */
1955
+ declare function defineRoute<TMethod extends HttpMethod, TPath extends string, TParams extends ZodType | undefined, TQuery extends ZodType | undefined, TBody extends ZodType | undefined>(config: StreamRouteDefineConfig<TMethod, TPath, TParams, TQuery, TBody>): StreamResponseRoute<TMethod, TPath, TParams, TQuery, TBody>;
1956
+ /**
1957
+ * defineRoute 重载:JSON 响应路由(原有形态)
1958
+ *
1959
+ * config 包含 response Zod Schema,返回 JsonResponseRoute。
1960
+ *
1961
+ * @typeParam TMethod - HTTP 方法类型
1962
+ * @typeParam TPath - 路径模板字符串
1963
+ * @typeParam TParams - 路径参数 Schema 类型
1964
+ * @typeParam TQuery - 查询参数 Schema 类型
1965
+ * @typeParam TBody - 请求体 Schema 类型
1966
+ * @typeParam TResponse - 响应 Schema 类型
1967
+ */
1968
+ declare function defineRoute<TMethod extends HttpMethod, TPath extends string, TParams extends ZodType | undefined, TQuery extends ZodType | undefined, TBody extends ZodType | undefined, TResponse extends ZodType>(config: DefineRouteConfig<TMethod, TPath, TParams, TQuery, TBody, TResponse>): JsonResponseRoute<TMethod, TPath, TParams, TQuery, TBody, TResponse>;
1793
1969
  /**
1794
1970
  * 构建完整 URL 路径
1795
1971
  *
@@ -2091,32 +2267,45 @@ type ProcessedRoute<T extends RouteDefinition = RouteDefinition> = T & {
2091
2267
  *
2092
2268
  * @typeParam T - 路由配置值类型
2093
2269
  */
2094
- type InferRouteDefinitionFromValue<T> = T extends {
2095
- /**
2096
- * HTTP 方法
2097
- */
2270
+ type InferRouteDefinitionFromValue<T> =
2271
+ /**
2272
+ * 流式响应分支:config 含 responseType: 'stream'
2273
+ */
2274
+ T extends {
2275
+ responseType: 'stream';
2098
2276
  method: infer M extends HttpMethod;
2099
- /**
2100
- * 请求路径
2101
- */
2102
2277
  path: string;
2278
+ } ? StreamResponseRoute<M, string, T extends {
2279
+ params?: infer PA;
2280
+ } ? ([PA] extends [ZodType] ? PA : undefined) : undefined, T extends {
2281
+ query?: infer Q;
2282
+ } ? ([Q] extends [ZodType] ? Q : undefined) : undefined, T extends {
2283
+ body?: infer B;
2284
+ } ? ([B] extends [ZodType] ? B : undefined) : undefined> & {
2103
2285
  /**
2104
- * 响应 Schema
2286
+ * 接口摘要描述
2105
2287
  */
2106
- response: infer R extends ZodType;
2288
+ summary?: string;
2107
2289
  /**
2108
- * 路径参数 Schema
2290
+ * 接口标签分组
2109
2291
  */
2110
- params?: infer PA;
2292
+ tags?: string[];
2111
2293
  /**
2112
- * 查询参数 Schema
2294
+ * 是否需要 CSRF 令牌保护
2113
2295
  */
2114
- query?: infer Q;
2296
+ csrf?: boolean;
2115
2297
  /**
2116
- * 请求体 Schema
2298
+ * 请求内容类型
2117
2299
  */
2300
+ contentType?: 'json' | 'formData';
2301
+ } : T extends {
2302
+ method: infer M extends HttpMethod;
2303
+ path: string;
2304
+ response: infer R extends ZodType;
2305
+ params?: infer PA;
2306
+ query?: infer Q;
2118
2307
  body?: infer B;
2119
- } ? RouteDefinition<M, string, [PA] extends [ZodType] ? PA : undefined, [Q] extends [ZodType] ? Q : undefined, [B] extends [ZodType] ? B : undefined, R> & {
2308
+ } ? JsonResponseRoute<M, string, [PA] extends [ZodType] ? PA : undefined, [Q] extends [ZodType] ? Q : undefined, [B] extends [ZodType] ? B : undefined, R> & {
2120
2309
  /**
2121
2310
  * 接口摘要描述
2122
2311
  */
@@ -2561,6 +2750,32 @@ declare function createTypedResponse<R extends RouteDefinition>(_route: R): Type
2561
2750
  * @returns 无参函数,返回空 ApiResponse
2562
2751
  */
2563
2752
  declare function createTypedEmpty<R extends RouteDefinition>(_route: R): TypedEmptyFunction;
2753
+ /**
2754
+ * 类型安全的流式响应函数类型
2755
+ *
2756
+ * 接受平台无关的 BinaryStreamMarker 并透传。
2757
+ * 各 adapter 通过 InferStreamRouteResponse<T> 映射为平台具体流类型
2758
+ * (NestJS 的 StreamableFile、Bun 的 ReadableStream、客户端的 Blob 等)。
2759
+ */
2760
+ type TypedStreamFunction = (stream: BinaryStreamMarker) => BinaryStreamMarker;
2761
+ /**
2762
+ * 创建类型安全的流式响应函数
2763
+ *
2764
+ * 工厂模式:创建时绑定路由定义,返回的函数接受流数据并透传。
2765
+ * 仅对 StreamResponseRoute 有效,传入 JsonResponseRoute 会编译报错,
2766
+ * 与 createTypedResponse 形成错用保护。
2767
+ *
2768
+ * @example
2769
+ * ```typescript
2770
+ * const typedStream = createTypedStream(downloadRoute);
2771
+ * return typedStream(streamableFile);
2772
+ * ```
2773
+ *
2774
+ * @typeParam R - 流式路由定义类型,约束为 StreamResponseRoute
2775
+ * @param _route - 路由定义(创建时绑定,用于类型约束)
2776
+ * @returns 流式响应函数,接受流数据并透传
2777
+ */
2778
+ declare function createTypedStream<R extends StreamResponseRoute>(_route: R): TypedStreamFunction;
2564
2779
  //#endregion
2565
2780
  //#region src/utils/unwrap-result.util.d.ts
2566
2781
  /**
@@ -2603,6 +2818,46 @@ declare function isRecord(value: unknown): value is Record<string, unknown>;
2603
2818
  */
2604
2819
  declare function isType<T>(value: unknown): value is T;
2605
2820
  //#endregion
2821
+ //#region src/utils/route-type-guards.util.d.ts
2822
+ /**
2823
+ * 判断路由是否为流式响应路由
2824
+ *
2825
+ * 通过 responseType 字段判别 StreamResponseRoute 分支。
2826
+ * 窄化后 route 为 Extract<T, StreamResponseRoute>,可安全访问 stream 字段。
2827
+ *
2828
+ * @typeParam T - 路由定义类型
2829
+ * @param route - 路由定义
2830
+ * @returns 若 responseType 为 'stream' 则为流式路由
2831
+ *
2832
+ * @example
2833
+ * ```typescript
2834
+ * if (isStreamRoute(route)) {
2835
+ * // route 窄化为 StreamResponseRoute,可访问 route.stream
2836
+ * console.log(route.stream.mimeType);
2837
+ * }
2838
+ * ```
2839
+ */
2840
+ declare function isStreamRoute<T extends RouteDefinition>(route: T): route is Extract<T, StreamResponseRoute>;
2841
+ /**
2842
+ * 判断路由是否为 JSON 响应路由
2843
+ *
2844
+ * 通过 responseType 字段判别 JsonResponseRoute 分支(含默认情况)。
2845
+ * 窄化后 route 为 Extract<T, JsonResponseRoute>,可安全访问 response 字段。
2846
+ *
2847
+ * @typeParam T - 路由定义类型
2848
+ * @param route - 路由定义
2849
+ * @returns 若 responseType 不为 'stream' 则为 JSON 路由
2850
+ *
2851
+ * @example
2852
+ * ```typescript
2853
+ * if (isJsonRoute(route)) {
2854
+ * // route 窄化为 JsonResponseRoute,可访问 route.response
2855
+ * validateResponse(data, route.response);
2856
+ * }
2857
+ * ```
2858
+ */
2859
+ declare function isJsonRoute<T extends RouteDefinition>(route: T): route is Extract<T, JsonResponseRoute>;
2860
+ //#endregion
2606
2861
  //#region src/client/create-http-client.utils.d.ts
2607
2862
  /**
2608
2863
  * 创建 HTTP 客户端
@@ -3133,4 +3388,4 @@ type RouteConfig<T extends RouteDefinition> = {
3133
3388
  handler: RouteHandler<T>;
3134
3389
  };
3135
3390
  //#endregion
3136
- export { type ApiCompactPaginatedListData, ApiCompactPaginatedListDataSchema, type ApiError, type ApiErrorResponse, ApiErrorResponseSchema, ApiErrorSchema, type ApiFailResponse, type ApiFunctions, type ApiListData, ApiListDataSchema, ApiListDataUtil, type ApiPaginatedListData, ApiPaginatedListDataSchema, type ApiResponse, ApiResponseSchema, ApiResponseUtil, type ApiSuccessResponse, type ApiVersion, type ArrayElement, type AuthInterceptorConfig, type AuthStrategy, type AwaitedData, type AxiosAdapterConfig, type CreateApiFunction, type CreateDeleteFunction, type CreateGetFunction, type CreatePostFunction, type CreateUpdateFunction, type CsrfInterceptorConfig, type CsrfProvider, type CursorPaginatedResult, type CursorPaginationParams, CursorPaginationParamsSchema, DEFAULT_RETRY_STATUS_CODES, type DateRangeQuery, DateRangeQuerySchema, type DeepPartial, type DeepReadonly, type DeepRequired, ERROR_HTTP_STATUS, ERROR_MESSAGES, type EmptyResponse, EmptyResponseSchema, ErrorCode, type ErrorCodeConfig, ErrorCodeSchema, type ExtractData, type FilterQuery, FilterQuerySchema, type FormDataConvertConfig, type HttpAdapter, type HttpClient, type HttpClientConfig, type HttpMethod, type HttpPaginationConfig, type IdParams, IdParamsSchema, type InferRouteBody, type InferRouteFullResponse, type InferRouteItem, type InferRouteParams, type InferRouteQuery, type InferRouteResponse, type InferRouteReturn, type InterceptorExecutorConfig, type LoggingInterceptorConfig, type Merge, type MockRequest, type MockRequestContext, type NonNullableData, type ObjectKeys, type ObjectValues, type OffsetPaginatedResult, type OffsetPaginationParams, OffsetPaginationParamsSchema, type OmitByValue, type OptionalKeyOf, type OptionalKeys, type PaginatedResult, type PaginationParams, PaginationParamsSchema, type PaginationQuery, PaginationQuerySchema, type PickByValue, type RequestConfig, type RequestDataToValidate, type RequestInterceptor, type RequestInterceptorContext, type RequiredKeyOf, type RequiredKeys, type ResponseInterceptor, type ResponseInterceptorContext, type ResponseTransformer, type RetryConfig, type ReturnDataType, type RouteConfig, type RouteDefineConfig, type RouteDefineResult, type RouteDefinition, type RouteGroup, type RouteGroupConfig, type RouteHandler, type RouteMockRequestOptions, type RouteResponseBuilder, type SchemaValidationFailure, type SchemaValidationResult, type SchemaValidationSuccess, type SearchQuery, SearchQuerySchema, type TaroAdapterConfig, type TokenProvider, type UnwrapApiListData, type UnwrapApiPaginatedListData, type UnwrapApiResponse, type ValidationError, type ValidationErrorDetail, type ValidationInterceptorConfig, type ValidationResult, type VersionedPrefix, buildPath, buildQuery, calculateOffset, calculateTotalPages, concatPath, createApiClientFactory, createAuthStrategyInterceptor, createAuthTokenInterceptor, createAxiosAdapter, createAxiosInstance, createBearerAuthStrategy, createConfigurableMockHttpClient, createCookieAuthStrategy, createCsrfInterceptor, createCustomAuthStrategy, createDelayedMockHttpClient, createErrorCodeSchema, createErrorMockHttpClient, createExecutorConfigFromClientConfig, createFilterQuerySchema, createHttpClient, createHttpPaginationSchema, createInterceptorExecutor, createLoggingInterceptor, createLoggingRequestInterceptor, createLoggingResponseInterceptor, createMockHttpClient, createNoneAuthStrategy, createPaginatedResult, createRequestInterceptorsFromConfig, createResponseInterceptorsFromConfig, createResponseTransformerInterceptor, createRetryInterceptor, createRouteMock, createRouteResponseBuilder, createTypedEmpty, createTypedResponse, createValidationErrorResponse, createValidationErrorResponseFromError, createValidationInterceptor, defaultLogger, defineRoute, defineRouteGroup, exponentialBackoff, extractErrorDetails, getErrorMessage, getHttpStatus, isBlob, isFile, isFormDataContentType, isLegacyConfig, isRecord, isType, normalizePagination, objectToFormData, setHttpClientConfig, unwrapResult, validateRequest, warnDeprecatedConfig };
3391
+ export { type ApiCompactPaginatedListData, ApiCompactPaginatedListDataSchema, type ApiError, type ApiErrorResponse, ApiErrorResponseSchema, ApiErrorSchema, type ApiFailResponse, type ApiFunctions, type ApiListData, ApiListDataSchema, ApiListDataUtil, type ApiPaginatedListData, ApiPaginatedListDataSchema, type ApiResponse, ApiResponseSchema, ApiResponseUtil, type ApiSuccessResponse, type ApiVersion, type ArrayElement, type AuthInterceptorConfig, type AuthStrategy, type AwaitedData, type AxiosAdapterConfig, type BinaryStreamMarker, type CreateApiFunction, type CreateDeleteFunction, type CreateGetFunction, type CreatePostFunction, type CreateUpdateFunction, type CsrfInterceptorConfig, type CsrfProvider, type CursorPaginatedResult, type CursorPaginationParams, CursorPaginationParamsSchema, DEFAULT_RETRY_STATUS_CODES, type DateRangeQuery, DateRangeQuerySchema, type DeepPartial, type DeepReadonly, type DeepRequired, ERROR_HTTP_STATUS, ERROR_MESSAGES, type EmptyResponse, EmptyResponseSchema, ErrorCode, type ErrorCodeConfig, ErrorCodeSchema, type ExtractData, type FilterQuery, FilterQuerySchema, type FormDataConvertConfig, type HttpAdapter, type HttpClient, type HttpClientConfig, type HttpMethod, type HttpPaginationConfig, type IdParams, IdParamsSchema, type InferRouteBody, type InferRouteFullResponse, type InferRouteItem, type InferRouteParams, type InferRouteQuery, type InferRouteResponse, type InferRouteReturn, type InterceptorExecutorConfig, type JsonResponseRoute, type LoggingInterceptorConfig, type Merge, type MockRequest, type MockRequestContext, type NonNullableData, type ObjectKeys, type ObjectValues, type OffsetPaginatedResult, type OffsetPaginationParams, OffsetPaginationParamsSchema, type OmitByValue, type OptionalKeyOf, type OptionalKeys, type PaginatedResult, type PaginationParams, PaginationParamsSchema, type PaginationQuery, PaginationQuerySchema, type PickByValue, type RequestConfig, type RequestDataToValidate, type RequestInterceptor, type RequestInterceptorContext, type RequiredKeyOf, type RequiredKeys, type ResponseInterceptor, type ResponseInterceptorContext, type ResponseTransformer, type RetryConfig, type ReturnDataType, type RouteBaseDef, type RouteConfig, type RouteDefineConfig, type RouteDefineResult, type RouteDefinition, type RouteGroup, type RouteGroupConfig, type RouteHandler, type RouteMockRequestOptions, type RouteResponseBuilder, type SchemaValidationFailure, type SchemaValidationResult, type SchemaValidationSuccess, type SearchQuery, SearchQuerySchema, type StreamResponseMeta, type StreamResponseRoute, type TaroAdapterConfig, type TokenProvider, type UnwrapApiListData, type UnwrapApiPaginatedListData, type UnwrapApiResponse, type ValidationError, type ValidationErrorDetail, type ValidationInterceptorConfig, type ValidationResult, type VersionedPrefix, buildPath, buildQuery, calculateOffset, calculateTotalPages, concatPath, createApiClientFactory, createAuthStrategyInterceptor, createAuthTokenInterceptor, createAxiosAdapter, createAxiosInstance, createBearerAuthStrategy, createConfigurableMockHttpClient, createCookieAuthStrategy, createCsrfInterceptor, createCustomAuthStrategy, createDelayedMockHttpClient, createErrorCodeSchema, createErrorMockHttpClient, createExecutorConfigFromClientConfig, createFilterQuerySchema, createHttpClient, createHttpPaginationSchema, createInterceptorExecutor, createLoggingInterceptor, createLoggingRequestInterceptor, createLoggingResponseInterceptor, createMockHttpClient, createNoneAuthStrategy, createPaginatedResult, createRequestInterceptorsFromConfig, createResponseInterceptorsFromConfig, createResponseTransformerInterceptor, createRetryInterceptor, createRouteMock, createRouteResponseBuilder, createTypedEmpty, createTypedResponse, createTypedStream, createValidationErrorResponse, createValidationErrorResponseFromError, createValidationInterceptor, defaultLogger, defineRoute, defineRouteGroup, exponentialBackoff, extractErrorDetails, getErrorMessage, getHttpStatus, isBlob, isFile, isFormDataContentType, isJsonRoute, isLegacyConfig, isRecord, isStreamRoute, isType, normalizePagination, objectToFormData, setHttpClientConfig, unwrapResult, validateRequest, warnDeprecatedConfig };
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import*as e from"zod";import{CursorPaginationParamsSchema as t,OffsetPaginationParamsSchema as n,PAGINATION_DEFAULTS as r,PaginationParamsSchema as i,SortParamsSchema as a,calculateOffset as o,calculateTotalPages as s,createCompactPaginatedResultSchema as c,createPaginatedResult as l,createPaginatedResult as u,createPaginatedResultSchema as d,createPaginationDefaults as f,createSortParamsSchema as p,normalizePagination as ee}from"@longzai-intelligence/pagination";import{createOptionalStringSchema as m,defineEnumSchema as h}from"@longzai-intelligence/zod-utils";import{isSuccess as te}from"@longzai-intelligence/shared-kernel";import g from"axios";const _=e.object({code:e.string(),message:e.string(),details:e.record(e.string(),e.unknown()).optional()}),v=t=>e.object({success:e.boolean(),data:t.optional(),message:e.string().optional(),error:_.optional(),timestamp:e.number().optional()}),ne=t=>e.object({items:e.array(t),total:e.number()}),re=e=>d(e),ie=e=>c(e),ae=v(e.void()),oe=e.object({id:e.string()}),se=i.extend({page:e.coerce.number().int().min(1).optional().default(r.page),pageSize:e.coerce.number().int().min(r.minPageSize).max(r.maxPageSize).optional().default(r.pageSize)});function ce(t){let n=t?.pageSizeField??`pageSize`,r=f({page:t?.defaultPage,pageSize:t?.defaultPageSize,maxPageSize:t?.maxPageSize,minPageSize:t?.minPageSize});return e.object({page:e.coerce.number().int().min(1).optional().default(r.page),[n]:e.coerce.number().int().min(r.minPageSize).max(r.maxPageSize).optional().default(r.pageSize)})}const le=e.object({filter:m(),sortBy:a.shape.sortBy,sortOrder:a.shape.sortOrder});function ue(t){let n=p(t);return e.object({filter:m(),sortBy:n.shape.sortBy,sortOrder:n.shape.sortOrder})}const de=e.object({startDate:m(),endDate:m()}),fe=e.object({keyword:m()});function y(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function b(e){return e!=null}const x=h([`UNKNOWN`,`INVALID_PARAMETER`,`RESOURCE_NOT_FOUND`,`RESOURCE_ALREADY_EXISTS`,`OPERATION_FAILED`,`PERMISSION_DENIED`,`UNAUTHORIZED`,`TOKEN_EXPIRED`,`TOKEN_INVALID`,`LOGIN_FAILED`,`ACCOUNT_DISABLED`,`PASSWORD_INCORRECT`,`DATABASE_ERROR`,`EXTERNAL_SERVICE_ERROR`,`RATE_LIMIT_EXCEEDED`,`DUPLICATE_REQUEST`,`VALIDATION_ERROR`],`通用错误码`),S={UNKNOWN:`未知错误`,INVALID_PARAMETER:`参数无效`,RESOURCE_NOT_FOUND:`资源不存在`,RESOURCE_ALREADY_EXISTS:`资源已存在`,OPERATION_FAILED:`操作失败`,PERMISSION_DENIED:`权限不足`,UNAUTHORIZED:`未授权`,TOKEN_EXPIRED:`令牌已过期`,TOKEN_INVALID:`令牌无效`,LOGIN_FAILED:`登录失败`,ACCOUNT_DISABLED:`账户已禁用`,PASSWORD_INCORRECT:`密码错误`,DATABASE_ERROR:`数据库错误`,EXTERNAL_SERVICE_ERROR:`外部服务错误`,RATE_LIMIT_EXCEEDED:`请求频率超限`,DUPLICATE_REQUEST:`重复请求`,VALIDATION_ERROR:`参数验证失败`};function pe(e){return S[e]||S.UNKNOWN}const C={UNAUTHORIZED:401,TOKEN_EXPIRED:401,TOKEN_INVALID:401,LOGIN_FAILED:401,ACCOUNT_DISABLED:401,PASSWORD_INCORRECT:401,PERMISSION_DENIED:403,RESOURCE_NOT_FOUND:404,INVALID_PARAMETER:400,VALIDATION_ERROR:400,DATABASE_ERROR:500,EXTERNAL_SERVICE_ERROR:500};function me(e){return C[e]??400}function he(e,t){let n=[...x.options,...e];if(b(n))return h(n,t??`错误码`);throw Error(`错误码合并失败`)}const ge=e.object({code:x,message:e.string(),data:e.unknown().nullable()});function _e(e){if(b(e))return e;throw Error(`路由定义创建失败`)}function ve(e,t,n){let r=e;if(t)for(let[e,n]of Object.entries(t))r=r.replace(`:${e}`,String(n));if(n){let e=new URLSearchParams;for(let[t,r]of Object.entries(n))r!==void 0&&e.append(t,String(r));let t=e.toString();t&&(r=`${r}?${t}`)}return r}function ye(e){if(!e)return``;let t=new URLSearchParams;for(let[n,r]of Object.entries(e))r!==void 0&&t.append(n,String(r));let n=t.toString();return n?`?${n}`:``}function w(e,t){return`${e}${t}`}function be(e){return`basePath`in e?typeof e.basePath==`string`:!1}function xe(e){let{parent:t,prefix:n,version:r,auth:i,tags:a}=e,o=n??``,s,c,l;return t?(s=o===``?t.prefix:`${t.prefix}/${o}`,c=i??t.auth,l=a??t.tags):(s=r?o.startsWith(`/`)?`/${r}${o}`:o===``?`/${r}`:`/${r}/${o}`:o,c=i,l=a),{fullPrefix:s,finalAuth:c,finalTags:l}}function Se(e,t){let n={};for(let[r,i]of Object.entries(e))be(i)?n[r]=i:n[r]=t(i);return n}function Ce(e,t,n){function r(r){let i=[...n??[],...r.tags??[]],a=r.auth??t,o={...r,path:w(e,r.path),basePath:r.path,tags:i.length>0?i:void 0,auth:a};if(b(o))return o;throw Error(`路由定义创建失败`)}return r}function we(e){let{routes:t}=e,{fullPrefix:n,finalAuth:r,finalTags:i}=xe(e),a=Ce(n,r,i),o=b(n)?n:void 0;if(o===void 0)throw Error(`路径前缀类型推断失败`);let s={prefix:o,version:e.version,auth:r,tags:i,defineRoute:a};if(!t){if(b(s))return s;throw Error(`路由分组创建失败`)}let c=Se(t,e=>a(e)),l={...s,routes:Object.freeze(c)};if(b(l))return l;throw Error(`路由分组创建失败`)}function T(e){return e instanceof File}function E(e){return e instanceof Blob}function D(e,t){let n=new FormData,r=new Set(t?.fileFields??[]),i=t?.arrayFormat??`brackets`,a=(e,t)=>{if(t!=null){if(T(t)||E(t)){n.append(e,t);return}if(r.has(e)&&typeof t==`string`){n.append(e,t);return}if(Array.isArray(t)){t.forEach((t,n)=>{a(i===`indices`?`${e}[${n}]`:i===`brackets`?`${e}[]`:e,t)});return}if(typeof t==`object`&&t){y(t)&&Object.entries(t).forEach(([t,n])=>{a(`${e}[${t}]`,n)});return}n.append(e,String(t))}};return Object.entries(e).forEach(([e,t])=>{a(e,t)}),n}function O(e){return e===`formData`}function Te(e){return{hasParams:`params`in e&&e.params!==void 0,hasQuery:`query`in e&&e.query!==void 0,hasBody:`body`in e&&e.body!==void 0}}function Ee(e,t){return t&&y(e)&&!(e instanceof FormData)?D(e):e}function De(e,t){let n=Te(e),r=O(e.contentType),i=e.method!==`GET`&&e.method!==`DELETE`,a=(...a)=>{let o=0,s=n.hasParams?a[o++]:void 0,c=i&&n.hasBody?a[o++]:void 0,l=n.hasQuery?a[o]:void 0,u=Ee(c,r),d=b(s)?s:void 0,f=b(l)?l:void 0,p=b(u)?u:void 0;return t.request({route:e,params:d,query:f,body:p})};if(b(a))return a;throw Error(`路由函数创建失败`)}function Oe(e,t){let n={};for(let r in e)if(Object.prototype.hasOwnProperty.call(e,r)){let i=e[r];i&&(n[r]=De(i,t))}if(b(n))return n;throw Error(`API 函数集合创建失败`)}function ke(e,t){return Oe(e,t)}function Ae(e){return t=>ke(t,e)}const k={success(e,t){return{success:!0,data:e,message:t,timestamp:Date.now()}},data(e){return{success:!0,data:e,timestamp:Date.now()}},message(e){return{success:!0,data:void 0,message:e,timestamp:Date.now()}},fail(e,t){return{success:!1,message:e,data:t,timestamp:Date.now()}},empty(){return{success:!0,data:void 0,timestamp:Date.now()}}},je={empty(){return{items:[],total:0}},from(e){return{items:e,total:e.length}},withTotal(e,t){return{items:e,total:t}},paginated(e,t,n,r){return u(e,t,n,r)}};function Me(e){return{success:e=>k.data(e),successWithMessage:(e,t)=>k.success(e,t),fail:(e,t)=>t?{success:!1,error:t,message:e,timestamp:Date.now()}:k.fail(e),empty:()=>k.empty()}}function Ne(e){return e=>k.data(e)}function Pe(e){return()=>k.empty()}function Fe(e){if(te(e))return k.data(e.value);throw e.error}function A(e){let t=g.create({timeout:e?.timeout??3e4});return{async execute(e){let n=await t.request({url:e.url,method:e.method,headers:e.headers,data:e.body,params:e.query,signal:e.config?.signal,timeout:e.config?.timeout});return{status:n.status,headers:b(n.headers)?n.headers:{},data:n.data}}}}async function j(e,t){let n=e;for(let e of t)e.onRequest&&(n=await e.onRequest(n));return n}async function M(e,t,n){let r=e;for(let e=n.length-1;e>=0;e--){let i=n[e];i?.onError&&(r=await i.onError(r,t))}return r}async function N(e,t,n){let r=e;for(let e of n)e.onResponse&&(r=await e.onResponse(r,t));return r}async function P(e,t,n){let r=e;for(let e=n.length-1;e>=0;e--){let i=n[e];if(i?.onError){let e=await i.onError(r,t);if(F(e))return e;r=e}}return r}function F(e){return typeof e==`object`&&!!e&&`success`in e&&typeof e.success==`boolean`}function I(e){let t={code:`UNKNOWN_ERROR`,message:`请求失败`};return e instanceof Error&&(e.message.includes(`timeout`)?(t.code=`TIMEOUT`,t.message=`请求超时`):e.message.includes(`network`)||e.message.includes(`Network`)?(t.code=`NETWORK_ERROR`,t.message=`网络错误`):t.message=e.message),{success:!1,error:t}}async function Ie(e,t){try{return await j(e,t)}catch(n){return I(await M(n,e,t))}}async function Le(e,t,n){try{return{response:await t.execute(e)}}catch(t){let r=await P(t,{status:0,headers:{},request:e},n);return F(r)?{error:r}:{error:I(r)}}}function Re(e,t,n){let{status:r,headers:i,data:a}=e,o={status:r,headers:i,request:t},s;return s=F(a)?a:{success:!0,data:a},r===401&&n&&n(),{response:s,context:o}}async function ze(e,t,n){let r=await Ie(e,t.requestInterceptors);if(!(`method`in r))return r;let i=r,a=await Le(i,n,t.responseInterceptors);if(a.error)return a.error;let{response:o,context:s}=Re(a.response,i,t.onUnauthorized);try{return await N(o,s,t.responseInterceptors)}catch(e){let n=await P(e,s,t.responseInterceptors);return F(n)?n:I(n)}}function L(e,t){return{execute:n=>ze(n,e,t),executeRequestInterceptors:t=>j(t,e.requestInterceptors),executeResponseInterceptors:(t,n)=>N(t,n,e.responseInterceptors),handleRequestError:(t,n)=>M(t,n,e.requestInterceptors),handleResponseError:(t,n)=>P(t,n,e.responseInterceptors)}}function Be(e){return{requestInterceptors:e.requestInterceptors??[],responseInterceptors:e.responseInterceptors??[],onUnauthorized:e.onUnauthorized}}function R(e,t){let n=t?.withAuth??!0,r=t?.tokenPrefix??`Bearer`,i=t?.headerName??`Authorization`;return{async onRequest(t){if(!(t.config?.withAuth??n))return t;let a=await e.getToken();return a&&(t.headers[i]=`${r} ${a}`),t}}}function z(e){return{async onRequest(t){switch(e.type){case`bearer`:{let n=await e.tokenProvider.getToken();n&&(t.headers.Authorization=`Bearer ${n}`);break}case`cookie`:t.metadata.credentials=e.credentials??`include`;break;case`custom`:{let n=e.injector({url:t.url,method:t.method,headers:t.headers,params:t.params,query:t.query,body:t.body});n.headers&&Object.assign(t.headers,n.headers);break}case`none`:break}return t}}}function Ve(e){return{type:`bearer`,tokenProvider:e}}function He(e){return{type:`cookie`,credentials:e}}function Ue(e){return{type:`custom`,injector:e}}function We(){return{type:`none`}}function B(e,t){let n=t?.headerName??`X-CSRF-Token`,r=t?.injectAll??!1,i=t?.onTokenError??`warn`;return{async onRequest(t){return!(r||(t.route?.csrf??!1))||!(t.config?.withCsrf??!0)?t:Ge(t,e,n,i)}}}async function Ge(e,t,n,r){try{let r=await t.getToken();r&&(e.headers[n]=r)}catch(e){switch(r){case`warn`:console.warn(`[http-utils] CSRF 令牌获取失败:`,e);break;case`throw`:throw e;case`ignore`:break}}return e}function V(e){return{async onResponse(t,n){try{let n=e(t.data);return{success:n.success,data:n.data,message:n.message,error:n.error,timestamp:n.timestamp}}catch{return{success:!1,error:{code:`TRANSFORM_ERROR`,message:`响应转换失败`}}}}}}const H=[408,429,500,502,503,504];function Ke(e){let t=e?.maxRetries??0,n=e?.baseDelay??1e3,r=e?.retryOn??H,i=e?.retryCondition,a=typeof e?.retryDelay==`function`?e.retryDelay:t=>{let r=e?.retryDelay??n*2**t;return typeof r==`number`?r:n*2**t};return{onError(e,n){let o=Number(n.request.metadata.retryCount);return o>=t||!(i?i(e,n):r.includes(n.status))?e:(n.request.metadata.retryCount=o+1,{success:!1,error:{code:`RETRY_PENDING`,message:`请求将在 ${a(o)}ms 后重试 (${o+1}/${t})`},metadata:{retryCount:o+1,retryDelay:a(o)}})}}}function qe(e,t=1e3){return t*2**e}function U(e){let t=e?.mode??`development`,n=e?.onValidationError??`warn`,r=e?.logger,i=()=>t===!0?!0:t===!1?!1:t===`development`?process.env.NODE_ENV===`development`:!1;return{async onResponse(e,t){if(!i())return e;let a=t.request.route;return a?.response?Je(e,a.response,t,n,r):e}}}function Je(e,t,n,r,i){if(e.success&&e.data!==void 0){let a=t.safeParse(e.data);if(!a.success){let e=`响应验证失败: ${n.request.url}`;switch(r){case`warn`:i&&i.warn(e,{error:a.error});break;case`throw`:throw Error(`${e}: ${a.error}`,{cause:a.error});case`ignore`:break}}}return e}function W(e,t,n){let r=`[${new Date().toISOString()}] [${e.toUpperCase()}]`;n===void 0?console.log(r,t):console.log(r,t,n)}function G(e){let t=e?.level??`info`,n=e?.logBody??!1,r=e?.logger??W;return{onRequest(e){let i=Date.now();e.metadata.startTime=i;let a={method:e.method,url:e.url};return n&&e.body&&(a.body=e.body),r(t,`请求开始`,a),e},onError(e,t){let n=Date.now()-Number(t.metadata.startTime);return r(`error`,`请求失败`,{method:t.method,url:t.url,duration:`${n}ms`,error:e}),e}}}function K(e){let t=e?.level??`info`,n=e?.logResponse??!1,r=e?.logger??W;return{onResponse(e,i){let a=Date.now()-Number(i.request.metadata.startTime),o={method:i.request.method,url:i.request.url,status:i.status,duration:`${a}ms`,success:e.success};return n&&e.data&&(o.data=e.data),!e.success&&e.error?(o.error=e.error,r(`warn`,`请求完成(失败)`,o)):r(t,`请求完成`,o),e},onError(e,t){let n=Date.now()-Number(t.request.metadata.startTime);return r(`error`,`响应处理失败`,{method:t.request.method,url:t.request.url,status:t.status,duration:`${n}ms`,error:e}),e}}}function Ye(e){return{request:G(e),response:K(e)}}function q(e){let t=[];return e.requestInterceptors&&t.push(...e.requestInterceptors),e.authStrategy?t.push(z(e.authStrategy)):e.tokenProvider&&t.push(R(e.tokenProvider)),e.csrfProvider&&t.push(B(e.csrfProvider,{headerName:e.csrfHeaderName})),t}function J(e){let t=[];return e.validation!==!1&&t.push(U(e.validation===void 0?void 0:e.validation)),e.responseInterceptors&&t.push(...e.responseInterceptors),e.responseTransformer&&t.push(V(e.responseTransformer)),t}function Y(e){return e.tokenProvider!==void 0||e.authStrategy!==void 0||e.responseTransformer!==void 0||e.csrfProvider!==void 0}function Xe(e){let t=[];e.tokenProvider&&t.push(`tokenProvider (使用 createAuthTokenInterceptor)`),e.authStrategy&&t.push(`authStrategy (使用 createAuthStrategyInterceptor)`),e.responseTransformer&&t.push(`responseTransformer (使用 createResponseTransformerInterceptor)`),e.csrfProvider&&t.push(`csrfProvider (使用 createCsrfInterceptor)`),t.length>0&&console.warn(`[http-utils] 以下配置项已弃用,将在未来版本中移除:
1
+ import*as e from"zod";import{CursorPaginationParamsSchema as t,OffsetPaginationParamsSchema as n,PAGINATION_DEFAULTS as r,PaginationParamsSchema as i,SortParamsSchema as a,calculateOffset as o,calculateTotalPages as s,createCompactPaginatedResultSchema as c,createPaginatedResult as l,createPaginatedResult as u,createPaginatedResultSchema as d,createPaginationDefaults as f,createSortParamsSchema as p,normalizePagination as ee}from"@longzai-intelligence/pagination";import{createOptionalStringSchema as m,defineEnumSchema as h}from"@longzai-intelligence/zod-utils";import{isSuccess as te}from"@longzai-intelligence/shared-kernel";import g from"axios";const _=e.object({code:e.string(),message:e.string(),details:e.record(e.string(),e.unknown()).optional()}),v=t=>e.object({success:e.boolean(),data:t.optional(),message:e.string().optional(),error:_.optional(),timestamp:e.number().optional()}),ne=t=>e.object({items:e.array(t),total:e.number()}),re=e=>d(e),ie=e=>c(e),ae=v(e.void()),oe=e.object({id:e.string()}),se=i.extend({page:e.coerce.number().int().min(1).optional().default(r.page),pageSize:e.coerce.number().int().min(r.minPageSize).max(r.maxPageSize).optional().default(r.pageSize)});function ce(t){let n=t?.pageSizeField??`pageSize`,r=f({page:t?.defaultPage,pageSize:t?.defaultPageSize,maxPageSize:t?.maxPageSize,minPageSize:t?.minPageSize});return e.object({page:e.coerce.number().int().min(1).optional().default(r.page),[n]:e.coerce.number().int().min(r.minPageSize).max(r.maxPageSize).optional().default(r.pageSize)})}const le=e.object({filter:m(),sortBy:a.shape.sortBy,sortOrder:a.shape.sortOrder});function ue(t){let n=p(t);return e.object({filter:m(),sortBy:n.shape.sortBy,sortOrder:n.shape.sortOrder})}const de=e.object({startDate:m(),endDate:m()}),fe=e.object({keyword:m()});function y(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function b(e){return e!=null}const x=h([`UNKNOWN`,`INVALID_PARAMETER`,`RESOURCE_NOT_FOUND`,`RESOURCE_ALREADY_EXISTS`,`OPERATION_FAILED`,`PERMISSION_DENIED`,`UNAUTHORIZED`,`TOKEN_EXPIRED`,`TOKEN_INVALID`,`LOGIN_FAILED`,`ACCOUNT_DISABLED`,`PASSWORD_INCORRECT`,`DATABASE_ERROR`,`EXTERNAL_SERVICE_ERROR`,`RATE_LIMIT_EXCEEDED`,`DUPLICATE_REQUEST`,`VALIDATION_ERROR`],`通用错误码`),S={UNKNOWN:`未知错误`,INVALID_PARAMETER:`参数无效`,RESOURCE_NOT_FOUND:`资源不存在`,RESOURCE_ALREADY_EXISTS:`资源已存在`,OPERATION_FAILED:`操作失败`,PERMISSION_DENIED:`权限不足`,UNAUTHORIZED:`未授权`,TOKEN_EXPIRED:`令牌已过期`,TOKEN_INVALID:`令牌无效`,LOGIN_FAILED:`登录失败`,ACCOUNT_DISABLED:`账户已禁用`,PASSWORD_INCORRECT:`密码错误`,DATABASE_ERROR:`数据库错误`,EXTERNAL_SERVICE_ERROR:`外部服务错误`,RATE_LIMIT_EXCEEDED:`请求频率超限`,DUPLICATE_REQUEST:`重复请求`,VALIDATION_ERROR:`参数验证失败`};function pe(e){return S[e]||S.UNKNOWN}const C={UNAUTHORIZED:401,TOKEN_EXPIRED:401,TOKEN_INVALID:401,LOGIN_FAILED:401,ACCOUNT_DISABLED:401,PASSWORD_INCORRECT:401,PERMISSION_DENIED:403,RESOURCE_NOT_FOUND:404,INVALID_PARAMETER:400,VALIDATION_ERROR:400,DATABASE_ERROR:500,EXTERNAL_SERVICE_ERROR:500};function me(e){return C[e]??400}function he(e,t){let n=[...x.options,...e];if(b(n))return h(n,t??`错误码`);throw Error(`错误码合并失败`)}const ge=e.object({code:x,message:e.string(),data:e.unknown().nullable()});function _e(e){if(b(e))return e;throw Error(`路由定义创建失败`)}function ve(e,t,n){let r=e;if(t)for(let[e,n]of Object.entries(t))r=r.replace(`:${e}`,String(n));if(n){let e=new URLSearchParams;for(let[t,r]of Object.entries(n))r!==void 0&&e.append(t,String(r));let t=e.toString();t&&(r=`${r}?${t}`)}return r}function ye(e){if(!e)return``;let t=new URLSearchParams;for(let[n,r]of Object.entries(e))r!==void 0&&t.append(n,String(r));let n=t.toString();return n?`?${n}`:``}function w(e,t){return`${e}${t}`}function be(e){return`basePath`in e?typeof e.basePath==`string`:!1}function xe(e){let{parent:t,prefix:n,version:r,auth:i,tags:a}=e,o=n??``,s,c,l;return t?(s=o===``?t.prefix:`${t.prefix}/${o}`,c=i??t.auth,l=a??t.tags):(s=r?o.startsWith(`/`)?`/${r}${o}`:o===``?`/${r}`:`/${r}/${o}`:o,c=i,l=a),{fullPrefix:s,finalAuth:c,finalTags:l}}function Se(e,t){let n={};for(let[r,i]of Object.entries(e))be(i)?n[r]=i:n[r]=t(i);return n}function Ce(e,t,n){function r(r){let i=[...n??[],...r.tags??[]],a=r.auth??t,o={...r,path:w(e,r.path),basePath:r.path,tags:i.length>0?i:void 0,auth:a};if(b(o))return o;throw Error(`路由定义创建失败`)}return r}function we(e){let{routes:t}=e,{fullPrefix:n,finalAuth:r,finalTags:i}=xe(e),a=Ce(n,r,i),o=b(n)?n:void 0;if(o===void 0)throw Error(`路径前缀类型推断失败`);let s={prefix:o,version:e.version,auth:r,tags:i,defineRoute:a};if(!t){if(b(s))return s;throw Error(`路由分组创建失败`)}let c=Se(t,e=>a(e)),l={...s,routes:Object.freeze(c)};if(b(l))return l;throw Error(`路由分组创建失败`)}function T(e){return e instanceof File}function E(e){return e instanceof Blob}function D(e,t){let n=new FormData,r=new Set(t?.fileFields??[]),i=t?.arrayFormat??`brackets`,a=(e,t)=>{if(t!=null){if(T(t)||E(t)){n.append(e,t);return}if(r.has(e)&&typeof t==`string`){n.append(e,t);return}if(Array.isArray(t)){t.forEach((t,n)=>{a(i===`indices`?`${e}[${n}]`:i===`brackets`?`${e}[]`:e,t)});return}if(typeof t==`object`&&t){y(t)&&Object.entries(t).forEach(([t,n])=>{a(`${e}[${t}]`,n)});return}n.append(e,String(t))}};return Object.entries(e).forEach(([e,t])=>{a(e,t)}),n}function O(e){return e===`formData`}function Te(e){return{hasParams:`params`in e&&e.params!==void 0,hasQuery:`query`in e&&e.query!==void 0,hasBody:`body`in e&&e.body!==void 0}}function Ee(e,t){return t&&y(e)&&!(e instanceof FormData)?D(e):e}function De(e,t){let n=Te(e),r=O(e.contentType),i=e.method!==`GET`&&e.method!==`DELETE`,a=(...a)=>{let o=0,s=n.hasParams?a[o++]:void 0,c=i&&n.hasBody?a[o++]:void 0,l=n.hasQuery?a[o]:void 0,u=Ee(c,r),d=b(s)?s:void 0,f=b(l)?l:void 0,p=b(u)?u:void 0;return t.request({route:e,params:d,query:f,body:p})};if(b(a))return a;throw Error(`路由函数创建失败`)}function Oe(e,t){let n={};for(let r in e)if(Object.prototype.hasOwnProperty.call(e,r)){let i=e[r];i&&(n[r]=De(i,t))}if(b(n))return n;throw Error(`API 函数集合创建失败`)}function ke(e,t){return Oe(e,t)}function Ae(e){return t=>ke(t,e)}const k={success(e,t){return{success:!0,data:e,message:t,timestamp:Date.now()}},data(e){return{success:!0,data:e,timestamp:Date.now()}},message(e){return{success:!0,data:void 0,message:e,timestamp:Date.now()}},fail(e,t){return{success:!1,message:e,data:t,timestamp:Date.now()}},empty(){return{success:!0,data:void 0,timestamp:Date.now()}}},je={empty(){return{items:[],total:0}},from(e){return{items:e,total:e.length}},withTotal(e,t){return{items:e,total:t}},paginated(e,t,n,r){return u(e,t,n,r)}};function Me(e){return{success:e=>k.data(e),successWithMessage:(e,t)=>k.success(e,t),fail:(e,t)=>t?{success:!1,error:t,message:e,timestamp:Date.now()}:k.fail(e),empty:()=>k.empty()}}function Ne(e){return e=>k.data(e)}function Pe(e){return()=>k.empty()}function Fe(e){return e=>e}function Ie(e){if(te(e))return k.data(e.value);throw e.error}function A(e){return e.responseType===`stream`}function Le(e){return e.responseType!==`stream`}function j(e){let t=g.create({timeout:e?.timeout??3e4});return{async execute(e){let n=await t.request({url:e.url,method:e.method,headers:e.headers,data:e.body,params:e.query,signal:e.config?.signal,timeout:e.config?.timeout});return{status:n.status,headers:b(n.headers)?n.headers:{},data:n.data}}}}async function M(e,t){let n=e;for(let e of t)e.onRequest&&(n=await e.onRequest(n));return n}async function N(e,t,n){let r=e;for(let e=n.length-1;e>=0;e--){let i=n[e];i?.onError&&(r=await i.onError(r,t))}return r}async function P(e,t,n){let r=e;for(let e of n)e.onResponse&&(r=await e.onResponse(r,t));return r}async function F(e,t,n){let r=e;for(let e=n.length-1;e>=0;e--){let i=n[e];if(i?.onError){let e=await i.onError(r,t);if(I(e))return e;r=e}}return r}function I(e){return typeof e==`object`&&!!e&&`success`in e&&typeof e.success==`boolean`}function L(e){let t={code:`UNKNOWN_ERROR`,message:`请求失败`};return e instanceof Error&&(e.message.includes(`timeout`)?(t.code=`TIMEOUT`,t.message=`请求超时`):e.message.includes(`network`)||e.message.includes(`Network`)?(t.code=`NETWORK_ERROR`,t.message=`网络错误`):t.message=e.message),{success:!1,error:t}}async function Re(e,t){try{return await M(e,t)}catch(n){return L(await N(n,e,t))}}async function ze(e,t,n){try{return{response:await t.execute(e)}}catch(t){let r=await F(t,{status:0,headers:{},request:e},n);return I(r)?{error:r}:{error:L(r)}}}function Be(e,t,n){let{status:r,headers:i,data:a}=e,o={status:r,headers:i,request:t},s;return s=I(a)?a:{success:!0,data:a},r===401&&n&&n(),{response:s,context:o}}async function Ve(e,t,n){let r=await Re(e,t.requestInterceptors);if(!(`method`in r))return r;let i=r,a=await ze(i,n,t.responseInterceptors);if(a.error)return a.error;let{response:o,context:s}=Be(a.response,i,t.onUnauthorized);try{return await P(o,s,t.responseInterceptors)}catch(e){let n=await F(e,s,t.responseInterceptors);return I(n)?n:L(n)}}function R(e,t){return{execute:n=>Ve(n,e,t),executeRequestInterceptors:t=>M(t,e.requestInterceptors),executeResponseInterceptors:(t,n)=>P(t,n,e.responseInterceptors),handleRequestError:(t,n)=>N(t,n,e.requestInterceptors),handleResponseError:(t,n)=>F(t,n,e.responseInterceptors)}}function He(e){return{requestInterceptors:e.requestInterceptors??[],responseInterceptors:e.responseInterceptors??[],onUnauthorized:e.onUnauthorized}}function z(e,t){let n=t?.withAuth??!0,r=t?.tokenPrefix??`Bearer`,i=t?.headerName??`Authorization`;return{async onRequest(t){if(!(t.config?.withAuth??n))return t;let a=await e.getToken();return a&&(t.headers[i]=`${r} ${a}`),t}}}function B(e){return{async onRequest(t){switch(e.type){case`bearer`:{let n=await e.tokenProvider.getToken();n&&(t.headers.Authorization=`Bearer ${n}`);break}case`cookie`:t.metadata.credentials=e.credentials??`include`;break;case`custom`:{let n=e.injector({url:t.url,method:t.method,headers:t.headers,params:t.params,query:t.query,body:t.body});n.headers&&Object.assign(t.headers,n.headers);break}case`none`:break}return t}}}function Ue(e){return{type:`bearer`,tokenProvider:e}}function We(e){return{type:`cookie`,credentials:e}}function Ge(e){return{type:`custom`,injector:e}}function Ke(){return{type:`none`}}function V(e,t){let n=t?.headerName??`X-CSRF-Token`,r=t?.injectAll??!1,i=t?.onTokenError??`warn`;return{async onRequest(t){return!(r||(t.route?.csrf??!1))||!(t.config?.withCsrf??!0)?t:qe(t,e,n,i)}}}async function qe(e,t,n,r){try{let r=await t.getToken();r&&(e.headers[n]=r)}catch(e){switch(r){case`warn`:console.warn(`[http-utils] CSRF 令牌获取失败:`,e);break;case`throw`:throw e;case`ignore`:break}}return e}function H(e){return{async onResponse(t,n){try{let n=e(t.data);return{success:n.success,data:n.data,message:n.message,error:n.error,timestamp:n.timestamp}}catch{return{success:!1,error:{code:`TRANSFORM_ERROR`,message:`响应转换失败`}}}}}}const U=[408,429,500,502,503,504];function Je(e){let t=e?.maxRetries??0,n=e?.baseDelay??1e3,r=e?.retryOn??U,i=e?.retryCondition,a=typeof e?.retryDelay==`function`?e.retryDelay:t=>{let r=e?.retryDelay??n*2**t;return typeof r==`number`?r:n*2**t};return{onError(e,n){let o=Number(n.request.metadata.retryCount);return o>=t||!(i?i(e,n):r.includes(n.status))?e:(n.request.metadata.retryCount=o+1,{success:!1,error:{code:`RETRY_PENDING`,message:`请求将在 ${a(o)}ms 后重试 (${o+1}/${t})`},metadata:{retryCount:o+1,retryDelay:a(o)}})}}}function Ye(e,t=1e3){return t*2**e}function W(e){let t=e?.mode??`development`,n=e?.onValidationError??`warn`,r=e?.logger,i=()=>t===!0?!0:t===!1?!1:t===`development`?process.env.NODE_ENV===`development`:!1;return{async onResponse(e,t){if(!i())return e;let a=t.request.route;if(!a||A(a))return e;let o=a.response;return o?Xe(e,o,t,n,r):e}}}function Xe(e,t,n,r,i){if(e.success&&e.data!==void 0){let a=t.safeParse(e.data);if(!a.success){let e=`响应验证失败: ${n.request.url}`;switch(r){case`warn`:i&&i.warn(e,{error:a.error});break;case`throw`:throw Error(`${e}: ${a.error}`,{cause:a.error});case`ignore`:break}}}return e}function G(e,t,n){let r=`[${new Date().toISOString()}] [${e.toUpperCase()}]`;n===void 0?console.log(r,t):console.log(r,t,n)}function K(e){let t=e?.level??`info`,n=e?.logBody??!1,r=e?.logger??G;return{onRequest(e){let i=Date.now();e.metadata.startTime=i;let a={method:e.method,url:e.url};return n&&e.body&&(a.body=e.body),r(t,`请求开始`,a),e},onError(e,t){let n=Date.now()-Number(t.metadata.startTime);return r(`error`,`请求失败`,{method:t.method,url:t.url,duration:`${n}ms`,error:e}),e}}}function q(e){let t=e?.level??`info`,n=e?.logResponse??!1,r=e?.logger??G;return{onResponse(e,i){let a=Date.now()-Number(i.request.metadata.startTime),o={method:i.request.method,url:i.request.url,status:i.status,duration:`${a}ms`,success:e.success};return n&&e.data&&(o.data=e.data),!e.success&&e.error?(o.error=e.error,r(`warn`,`请求完成(失败)`,o)):r(t,`请求完成`,o),e},onError(e,t){let n=Date.now()-Number(t.request.metadata.startTime);return r(`error`,`响应处理失败`,{method:t.request.method,url:t.request.url,status:t.status,duration:`${n}ms`,error:e}),e}}}function Ze(e){return{request:K(e),response:q(e)}}function J(e){let t=[];return e.requestInterceptors&&t.push(...e.requestInterceptors),e.authStrategy?t.push(B(e.authStrategy)):e.tokenProvider&&t.push(z(e.tokenProvider)),e.csrfProvider&&t.push(V(e.csrfProvider,{headerName:e.csrfHeaderName})),t}function Y(e){let t=[];return e.validation!==!1&&t.push(W(e.validation===void 0?void 0:e.validation)),e.responseInterceptors&&t.push(...e.responseInterceptors),e.responseTransformer&&t.push(H(e.responseTransformer)),t}function Qe(e){return e.tokenProvider!==void 0||e.authStrategy!==void 0||e.responseTransformer!==void 0||e.csrfProvider!==void 0}function $e(e){let t=[];e.tokenProvider&&t.push(`tokenProvider (使用 createAuthTokenInterceptor)`),e.authStrategy&&t.push(`authStrategy (使用 createAuthStrategyInterceptor)`),e.responseTransformer&&t.push(`responseTransformer (使用 createResponseTransformerInterceptor)`),e.csrfProvider&&t.push(`csrfProvider (使用 createCsrfInterceptor)`),t.length>0&&console.warn(`[http-utils] 以下配置项已弃用,将在未来版本中移除:
2
2
  `+t.map(e=>` - ${e}`).join(`
3
- `))}function Ze(e,t,n,r,i,a){return{url:`${e}${t}`,method:n,headers:i?.headers??{},body:r,config:i,route:a,metadata:{}}}function Qe(e,t,n){let r=e.path;if(t&&Object.entries(t).forEach(([e,t])=>{r=r.replace(`:${e}`,String(t))}),n){let e=new URLSearchParams;Object.entries(n).forEach(([t,n])=>{n!==void 0&&e.append(t,String(n))});let t=e.toString();t&&(r=`${r}?${t}`)}return r}function $e(e){let{baseUrl:t,timeout:n=3e4,headers:r,onUnauthorized:i}=e;Y(e)&&Xe(e);let a=q(e),o=J(e),s=A({timeout:n}),c=L({requestInterceptors:a,responseInterceptors:o,onUnauthorized:i},s);return{request:async e=>{let{route:n,params:i,query:a,body:o,config:s}=e,l=Ze(t,Qe(n,i,a),n.method,o,{...s,headers:{...r,...s?.headers}},n),u=await c.execute(l);if(b(u))return u;throw Error(`响应类型不匹配`)}}}let X=null;function et(e){X=e}async function tt(e){let t=g.create({baseURL:X?.baseUrl||``,timeout:X?.timeout||3e4,headers:e.headers});return t.interceptors.request.use(async e=>{if(X?.tokenProvider){let t=await X.tokenProvider.getToken();t&&(e.headers.Authorization=`Bearer ${t}`)}return e},e=>Promise.reject(Error(String(e)))),t.interceptors.response.use(e=>e,async e=>(e.response?.status===401&&X?.onUnauthorized&&await X.onUnauthorized(),Promise.reject(e instanceof Error?e:Error(String(e))))),t.request(e)}function nt(e,t){return setTimeout(e,t)}function Z(e){return new Promise(t=>nt(t,e))}function rt(e){return{request:async()=>{if(b(e))return e;throw Error(`模拟响应类型不匹配`)}}}function it(e){return{request:async t=>{let n=`${t.route.method}:${t.route.path}`,r=e.get(n);if(!r){let e={success:!1,error:{code:`MOCK_NOT_FOUND`,message:`未找到模拟响应`}};if(b(e))return e;throw Error(`模拟响应创建失败`)}if(b(r))return r;throw Error(`模拟响应类型不匹配`)}}}function at(e,t){return{request:async()=>{if(await Z(t),b(e))return e;throw Error(`模拟响应类型不匹配`)}}}async function ot(e){throw e}function st(e){return{request:async t=>ot(e)}}function ct(e){return{request:async t=>{let n={route:t.route,params:t.params,query:t.query,body:t.body};for(let r of e){let e=!r.method||t.route.method===r.method,i=!r.path||t.route.path===r.path,a=!r.match||r.match(t.route,t.params,t.query,t.body);if(e&&i&&a){r.delay&&await Z(r.delay);let e=typeof r.response==`function`?r.response(n):r.response;if(b(e))return e;throw Error(`模拟响应类型不匹配`)}}let r={success:!1,error:{code:`MOCK_NOT_FOUND`,message:`未找到路由 ${t.route.method} ${t.route.path} 的模拟响应`}};if(b(r))return r;throw Error(`模拟响应创建失败`)}}}function Q(e,t=``){return e.issues.map(e=>lt(e,t))}function lt(e,t){let n=t+e.path.map(String).join(`.`)||t.slice(0,-1)||`root`;return e.code===`invalid_type`?dt(e,n):{path:n,message:e.message,received:void 0,expected:ft(e.code)}}function ut(e){return typeof e==`object`&&!!e&&`received`in e&&`expected`in e}function dt(e,t){return ut(e)?{path:t,message:e.message,received:e.received,expected:e.expected}:{path:t,message:e.message,received:void 0,expected:`类型不匹配`}}function ft(e){return{invalid_type:`类型不匹配`,invalid_literal:`字面量不匹配`,custom:`自定义验证失败`,invalid_union:`联合类型不匹配`,invalid_union_discriminator:`联合类型判别器无效`,invalid_enum_value:`枚举值无效`,invalid_arguments:`参数无效`,invalid_return_type:`返回类型无效`,invalid_date:`日期无效`,invalid_string:`字符串无效`,too_small:`值过小`,too_big:`值过大`,invalid_intersection_types:`交集类型无效`,not_multiple_of:`不是倍数`,not_finite:`值非有限`}[e]??`验证失败`}function $(e,t,n){if(!e){if(b(t))return{success:!0,data:t};let e={success:!0,data:void 0};if(b(e))return e;throw Error(`Schema 验证结果类型推断失败`)}let r=t??{},i=e.safeParse(r);return i.success?{success:!0,data:i.data}:{success:!1,details:Q(i.error,n)}}function pt(e,t){let n=[],r=$(e.params,t.params,`params.`);r.success||n.push(...r.details);let i=$(e.query,t.query,`query.`);i.success||n.push(...i.details);let a=$(e.body,t.body,`body.`);if(a.success||n.push(...a.details),n.length>0)return{success:!1,error:{code:`VALIDATION_ERROR`,message:`参数验证失败`,details:n}};let o={success:!0,params:r.success?r.data:void 0,query:i.success?i.data:void 0,body:a.success?a.data:void 0};if(b(o))return o;throw Error(`验证结果创建失败`)}function mt(e,t=`参数验证失败`){return{success:!1,error:{code:`VALIDATION_ERROR`,message:t,details:{validationErrors:Q(e)}},message:t}}function ht(e){return{success:!1,error:{code:e.code,message:e.message,details:{validationErrors:e.details}},message:e.message}}export{ie as ApiCompactPaginatedListDataSchema,ge as ApiErrorResponseSchema,_ as ApiErrorSchema,ne as ApiListDataSchema,je as ApiListDataUtil,re as ApiPaginatedListDataSchema,v as ApiResponseSchema,k as ApiResponseUtil,t as CursorPaginationParamsSchema,H as DEFAULT_RETRY_STATUS_CODES,de as DateRangeQuerySchema,C as ERROR_HTTP_STATUS,S as ERROR_MESSAGES,ae as EmptyResponseSchema,x as ErrorCodeSchema,le as FilterQuerySchema,oe as IdParamsSchema,n as OffsetPaginationParamsSchema,i as PaginationParamsSchema,se as PaginationQuerySchema,fe as SearchQuerySchema,ve as buildPath,ye as buildQuery,o as calculateOffset,s as calculateTotalPages,w as concatPath,Ae as createApiClientFactory,z as createAuthStrategyInterceptor,R as createAuthTokenInterceptor,A as createAxiosAdapter,tt as createAxiosInstance,Ve as createBearerAuthStrategy,it as createConfigurableMockHttpClient,He as createCookieAuthStrategy,B as createCsrfInterceptor,Ue as createCustomAuthStrategy,at as createDelayedMockHttpClient,he as createErrorCodeSchema,st as createErrorMockHttpClient,Be as createExecutorConfigFromClientConfig,ue as createFilterQuerySchema,$e as createHttpClient,ce as createHttpPaginationSchema,L as createInterceptorExecutor,Ye as createLoggingInterceptor,G as createLoggingRequestInterceptor,K as createLoggingResponseInterceptor,rt as createMockHttpClient,We as createNoneAuthStrategy,l as createPaginatedResult,q as createRequestInterceptorsFromConfig,J as createResponseInterceptorsFromConfig,V as createResponseTransformerInterceptor,Ke as createRetryInterceptor,ct as createRouteMock,Me as createRouteResponseBuilder,Pe as createTypedEmpty,Ne as createTypedResponse,mt as createValidationErrorResponse,ht as createValidationErrorResponseFromError,U as createValidationInterceptor,W as defaultLogger,_e as defineRoute,we as defineRouteGroup,qe as exponentialBackoff,Q as extractErrorDetails,pe as getErrorMessage,me as getHttpStatus,E as isBlob,T as isFile,O as isFormDataContentType,Y as isLegacyConfig,y as isRecord,b as isType,ee as normalizePagination,D as objectToFormData,et as setHttpClientConfig,Fe as unwrapResult,pt as validateRequest,Xe as warnDeprecatedConfig};
3
+ `))}function et(e,t,n,r,i,a){return{url:`${e}${t}`,method:n,headers:i?.headers??{},body:r,config:i,route:a,metadata:{}}}function tt(e,t,n){let r=e.path;if(t&&Object.entries(t).forEach(([e,t])=>{r=r.replace(`:${e}`,String(t))}),n){let e=new URLSearchParams;Object.entries(n).forEach(([t,n])=>{n!==void 0&&e.append(t,String(n))});let t=e.toString();t&&(r=`${r}?${t}`)}return r}function nt(e){let{baseUrl:t,timeout:n=3e4,headers:r,onUnauthorized:i}=e;Qe(e)&&$e(e);let a=J(e),o=Y(e),s=j({timeout:n}),c=R({requestInterceptors:a,responseInterceptors:o,onUnauthorized:i},s);return{request:async e=>{let{route:n,params:i,query:a,body:o,config:s}=e,l=et(t,tt(n,i,a),n.method,o,{...s,headers:{...r,...s?.headers}},n),u=await c.execute(l);if(b(u))return u;throw Error(`响应类型不匹配`)}}}let X=null;function rt(e){X=e}async function it(e){let t=g.create({baseURL:X?.baseUrl||``,timeout:X?.timeout||3e4,headers:e.headers});return t.interceptors.request.use(async e=>{if(X?.tokenProvider){let t=await X.tokenProvider.getToken();t&&(e.headers.Authorization=`Bearer ${t}`)}return e},e=>Promise.reject(Error(String(e)))),t.interceptors.response.use(e=>e,async e=>(e.response?.status===401&&X?.onUnauthorized&&await X.onUnauthorized(),Promise.reject(e instanceof Error?e:Error(String(e))))),t.request(e)}function at(e,t){return setTimeout(e,t)}function Z(e){return new Promise(t=>at(t,e))}function ot(e){return{request:async()=>{if(b(e))return e;throw Error(`模拟响应类型不匹配`)}}}function st(e){return{request:async t=>{let n=`${t.route.method}:${t.route.path}`,r=e.get(n);if(!r){let e={success:!1,error:{code:`MOCK_NOT_FOUND`,message:`未找到模拟响应`}};if(b(e))return e;throw Error(`模拟响应创建失败`)}if(b(r))return r;throw Error(`模拟响应类型不匹配`)}}}function ct(e,t){return{request:async()=>{if(await Z(t),b(e))return e;throw Error(`模拟响应类型不匹配`)}}}async function lt(e){throw e}function ut(e){return{request:async t=>lt(e)}}function dt(e){return{request:async t=>{let n={route:t.route,params:t.params,query:t.query,body:t.body};for(let r of e){let e=!r.method||t.route.method===r.method,i=!r.path||t.route.path===r.path,a=!r.match||r.match(t.route,t.params,t.query,t.body);if(e&&i&&a){r.delay&&await Z(r.delay);let e=typeof r.response==`function`?r.response(n):r.response;if(b(e))return e;throw Error(`模拟响应类型不匹配`)}}let r={success:!1,error:{code:`MOCK_NOT_FOUND`,message:`未找到路由 ${t.route.method} ${t.route.path} 的模拟响应`}};if(b(r))return r;throw Error(`模拟响应创建失败`)}}}function Q(e,t=``){return e.issues.map(e=>ft(e,t))}function ft(e,t){let n=t+e.path.map(String).join(`.`)||t.slice(0,-1)||`root`;return e.code===`invalid_type`?mt(e,n):{path:n,message:e.message,received:void 0,expected:ht(e.code)}}function pt(e){return typeof e==`object`&&!!e&&`received`in e&&`expected`in e}function mt(e,t){return pt(e)?{path:t,message:e.message,received:e.received,expected:e.expected}:{path:t,message:e.message,received:void 0,expected:`类型不匹配`}}function ht(e){return{invalid_type:`类型不匹配`,invalid_literal:`字面量不匹配`,custom:`自定义验证失败`,invalid_union:`联合类型不匹配`,invalid_union_discriminator:`联合类型判别器无效`,invalid_enum_value:`枚举值无效`,invalid_arguments:`参数无效`,invalid_return_type:`返回类型无效`,invalid_date:`日期无效`,invalid_string:`字符串无效`,too_small:`值过小`,too_big:`值过大`,invalid_intersection_types:`交集类型无效`,not_multiple_of:`不是倍数`,not_finite:`值非有限`}[e]??`验证失败`}function $(e,t,n){if(!e){if(b(t))return{success:!0,data:t};let e={success:!0,data:void 0};if(b(e))return e;throw Error(`Schema 验证结果类型推断失败`)}let r=t??{},i=e.safeParse(r);return i.success?{success:!0,data:i.data}:{success:!1,details:Q(i.error,n)}}function gt(e,t){let n=[],r=$(e.params,t.params,`params.`);r.success||n.push(...r.details);let i=$(e.query,t.query,`query.`);i.success||n.push(...i.details);let a=$(e.body,t.body,`body.`);if(a.success||n.push(...a.details),n.length>0)return{success:!1,error:{code:`VALIDATION_ERROR`,message:`参数验证失败`,details:n}};let o={success:!0,params:r.success?r.data:void 0,query:i.success?i.data:void 0,body:a.success?a.data:void 0};if(b(o))return o;throw Error(`验证结果创建失败`)}function _t(e,t=`参数验证失败`){return{success:!1,error:{code:`VALIDATION_ERROR`,message:t,details:{validationErrors:Q(e)}},message:t}}function vt(e){return{success:!1,error:{code:e.code,message:e.message,details:{validationErrors:e.details}},message:e.message}}export{ie as ApiCompactPaginatedListDataSchema,ge as ApiErrorResponseSchema,_ as ApiErrorSchema,ne as ApiListDataSchema,je as ApiListDataUtil,re as ApiPaginatedListDataSchema,v as ApiResponseSchema,k as ApiResponseUtil,t as CursorPaginationParamsSchema,U as DEFAULT_RETRY_STATUS_CODES,de as DateRangeQuerySchema,C as ERROR_HTTP_STATUS,S as ERROR_MESSAGES,ae as EmptyResponseSchema,x as ErrorCodeSchema,le as FilterQuerySchema,oe as IdParamsSchema,n as OffsetPaginationParamsSchema,i as PaginationParamsSchema,se as PaginationQuerySchema,fe as SearchQuerySchema,ve as buildPath,ye as buildQuery,o as calculateOffset,s as calculateTotalPages,w as concatPath,Ae as createApiClientFactory,B as createAuthStrategyInterceptor,z as createAuthTokenInterceptor,j as createAxiosAdapter,it as createAxiosInstance,Ue as createBearerAuthStrategy,st as createConfigurableMockHttpClient,We as createCookieAuthStrategy,V as createCsrfInterceptor,Ge as createCustomAuthStrategy,ct as createDelayedMockHttpClient,he as createErrorCodeSchema,ut as createErrorMockHttpClient,He as createExecutorConfigFromClientConfig,ue as createFilterQuerySchema,nt as createHttpClient,ce as createHttpPaginationSchema,R as createInterceptorExecutor,Ze as createLoggingInterceptor,K as createLoggingRequestInterceptor,q as createLoggingResponseInterceptor,ot as createMockHttpClient,Ke as createNoneAuthStrategy,l as createPaginatedResult,J as createRequestInterceptorsFromConfig,Y as createResponseInterceptorsFromConfig,H as createResponseTransformerInterceptor,Je as createRetryInterceptor,dt as createRouteMock,Me as createRouteResponseBuilder,Pe as createTypedEmpty,Ne as createTypedResponse,Fe as createTypedStream,_t as createValidationErrorResponse,vt as createValidationErrorResponseFromError,W as createValidationInterceptor,G as defaultLogger,_e as defineRoute,we as defineRouteGroup,Ye as exponentialBackoff,Q as extractErrorDetails,pe as getErrorMessage,me as getHttpStatus,E as isBlob,T as isFile,O as isFormDataContentType,Le as isJsonRoute,Qe as isLegacyConfig,y as isRecord,A as isStreamRoute,b as isType,ee as normalizePagination,D as objectToFormData,rt as setHttpClientConfig,Ie as unwrapResult,gt as validateRequest,$e as warnDeprecatedConfig};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@longzai-intelligence-transport/http-core",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "keywords": [
5
5
  "api",
6
6
  "contract",