@zwa73/utils 1.0.232 → 1.0.234

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.
@@ -2,7 +2,6 @@ import { AnyString, JToken, MPromise, PartialOption, StatusVerifyFn } from "./Ut
2
2
  import http from 'http';
3
3
  import { PromiseRetries } from "./UtilFunctions";
4
4
  import FormData from "form-data";
5
- import { RequiredOnly } from "@zwa73/js-utils";
6
5
  /**网络请求返回值 */
7
6
  export type RequestResult<T> = {
8
7
  /**响应头 */
@@ -39,34 +38,41 @@ export type RequestOption = {
39
38
  /**getquery请求所允许的数据 */
40
39
  export type QueryRequestData = NodeJS.Dict<string | number | boolean | readonly string[] | readonly number[] | readonly boolean[] | null>;
41
40
  /**请求处理函数 需调用req.end() */
42
- export type RequestProcFn = ((req: http.ClientRequest) => MPromise<void>);
41
+ export type RequestProcFn = (req: http.ClientRequest) => MPromise<void>;
42
+ /**结果处理函数 */
43
+ export type RequestParseFn<D, R> = (result: RequestResult<D> | undefined) => MPromise<R>;
43
44
  /**数据处理函数 */
44
45
  export type RequestReduceFn<T> = (acc: T, data: string) => MPromise<T>;
45
- declare const AcceptTypeList: readonly ["json", "string"];
46
- /**可用的接受类型 */
47
- type AcceptType = typeof AcceptTypeList[number];
48
- declare const SendTypeList: readonly ["json", "query", "formData", "none"];
49
- /**可用的发送类型 */
50
- type SendType = typeof SendTypeList[number];
51
- /**accept处理数据 */
52
- type AcceptProc<D, T> = {
53
- init: D;
54
- reduce: RequestReduceFn<D>;
55
- parse: (result: RequestResult<D> | undefined) => MPromise<T>;
46
+ /**数据初始化函数 */
47
+ export type RequestInitFn<T> = (res: http.IncomingMessage) => MPromise<T>;
48
+ /**accept处理数据
49
+ * @template D - 接受时转换的数据类型
50
+ * @template R - 完成处理的数据类型
51
+ */
52
+ type AcceptProcCtor<D, R, T extends {}> = AcceptProcData<D, R> | ((arg: T) => MPromise<AcceptProcData<D, R>>);
53
+ type AcceptProcData<D, R> = {
54
+ init: RequestInitFn<D>;
55
+ reduce?: RequestReduceFn<D>;
56
+ parse: RequestParseFn<D, R>;
56
57
  };
57
58
  /**send处理数据 */
58
- type SendProc<T extends any[]> = {
59
- proc: (opt: RequestOption, ...args: T) => MPromise<RequestProcFn>;
59
+ type SendProcCtor<T extends {}> = SendProcData | ((opt: RequestOption, arg: T) => MPromise<SendProcData>);
60
+ type SendProcData = {
61
+ proc: RequestProcFn;
60
62
  };
61
- declare const SendNoneProc: SendProc<[]>;
62
- declare const AcceptStringProc: AcceptProc<string, RequestResult<string> | undefined>;
63
- declare const AcceptNoneProc: AcceptProc<undefined, undefined>;
63
+ declare const SendNoneProc: SendProcCtor<{}>;
64
+ declare const AcceptStringProc: AcceptProcCtor<string, RequestResult<string> | undefined, {}>;
65
+ declare const AcceptNoneProc: AcceptProcCtor<undefined, RequestResult<undefined> | undefined, {}>;
64
66
  /**send处理的参数 */
65
- type SendParams<P extends SendProc<any>> = P extends SendProc<infer T> ? T : never;
67
+ type SendParams<S extends SendProcCtor<any>> = S extends SendProcCtor<infer P> ? P : never;
68
+ /**send处理的参数 */
69
+ type AcceptParams<A extends AcceptProcCtor<any, any, any>> = A extends AcceptProcCtor<any, any, infer P> ? P : never;
70
+ type HasConflict<A, B> = keyof A & keyof B extends never ? false : true;
71
+ type ConflictCheck<A, B, C> = HasConflict<A, B> extends true ? A & B & C & Error & "❌ A 与 B 有字段冲突" : HasConflict<A, C> extends true ? A & B & C & Error & "❌ A 与 C 有字段冲突" : HasConflict<B, C> extends true ? A & B & C & Error & "❌ B 与 C 有字段冲突" : A & B & C;
66
72
  /**accept处理的结果 */
67
- type ParseResult<P extends AcceptProc<any, any>> = P extends AcceptProc<any, infer T> ? Awaited<T> : never;
73
+ type ParseResult<P extends AcceptProcCtor<any, any, any>> = P extends AcceptProcCtor<any, infer T, any> ? Awaited<T> : never;
68
74
  /**http请求工具 */
69
- export declare class UtilHttp<D extends Partial<RequestOption> & Required<Pick<RequestOption, 'protocol'>>, S extends SendProc<any>, A extends AcceptProc<any, any>> {
75
+ export declare class UtilHttp<D extends Partial<RequestOption> & Required<Pick<RequestOption, 'protocol'>>, S extends SendProcCtor<any>, A extends AcceptProcCtor<any, any, any>> {
70
76
  private _data;
71
77
  private _send;
72
78
  private _accept;
@@ -74,11 +80,11 @@ export declare class UtilHttp<D extends Partial<RequestOption> & Required<Pick<R
74
80
  /**设为https请求 */
75
81
  static https(): UtilHttp<{
76
82
  readonly protocol: "https:";
77
- }, SendProc<[]>, AcceptProc<string, RequestResult<string> | undefined>>;
83
+ }, SendProcCtor<{}>, AcceptProcCtor<string, RequestResult<string> | undefined, {}>>;
78
84
  /**设为http请求 */
79
85
  static http(): UtilHttp<{
80
86
  readonly protocol: "http:";
81
- }, SendProc<[]>, AcceptProc<string, RequestResult<string> | undefined>>;
87
+ }, SendProcCtor<{}>, AcceptProcCtor<string, RequestResult<string> | undefined, {}>>;
82
88
  /**从url创建 */
83
89
  static url(urlStr: `${'http:' | 'https:'}//${string}`): UtilHttp<{
84
90
  protocol: "http:" | "https:";
@@ -86,7 +92,7 @@ export declare class UtilHttp<D extends Partial<RequestOption> & Required<Pick<R
86
92
  hostname: string;
87
93
  path: string;
88
94
  port: number | undefined;
89
- }, SendProc<[]>, AcceptProc<string, RequestResult<string> | undefined>>;
95
+ }, SendProcCtor<{}>, AcceptProcCtor<string, RequestResult<string> | undefined, {}>>;
90
96
  /**设为get方式的请求 */
91
97
  get(): UtilHttp<D & {
92
98
  method: "GET";
@@ -100,11 +106,6 @@ export declare class UtilHttp<D extends Partial<RequestOption> & Required<Pick<R
100
106
  * 将会替换对应字段, 修改headers请用header函数
101
107
  */
102
108
  option<OPT extends Partial<RequestOption>>(option: OPT): UtilHttp<D & OPT, S, A>;
103
- /**完成参数
104
- * 会检查必要参数完整性
105
- * 将会替换对应字段, 修改headers请用header函数
106
- */
107
- finalize<OPT extends PartialOption<RequestOption, D>>(option: OPT): UtilHttp<D & OPT, S, A>;
108
109
  /**补充header */
109
110
  header<HAD extends http.OutgoingHttpHeaders>(headers: HAD): UtilHttp<D & {
110
111
  headers: HAD;
@@ -120,7 +121,10 @@ export declare class UtilHttp<D extends Partial<RequestOption> & Required<Pick<R
120
121
  headers: {
121
122
  "Content-Type": "application/json";
122
123
  };
123
- }, SendProc<[JToken]>, AcceptProc<string, RequestResult<JToken> | undefined>>;
124
+ }, (opt: RequestOption, arg: {
125
+ /**发送的json */
126
+ json: JToken;
127
+ }) => MPromise<SendProcData>, AcceptProcData<string, RequestResult<JToken> | undefined>>;
124
128
  /**收发皆为json的post预设 */
125
129
  postJson(): UtilHttp<D & {
126
130
  method: "POST";
@@ -128,15 +132,21 @@ export declare class UtilHttp<D extends Partial<RequestOption> & Required<Pick<R
128
132
  headers: {
129
133
  'Content-Type': "application/json";
130
134
  };
131
- }, SendProc<[JToken]>, AcceptProc<string, RequestResult<JToken> | undefined>>;
135
+ }, (opt: RequestOption, arg: {
136
+ /**发送的json */
137
+ json: JToken;
138
+ }) => MPromise<SendProcData>, AcceptProcData<string, RequestResult<JToken> | undefined>>;
132
139
  /**无查询参数获取json的get预设 */
133
140
  getJson(): UtilHttp<D & {
134
141
  method: "GET";
135
- }, SendProc<[]>, AcceptProc<string, RequestResult<JToken> | undefined>>;
142
+ }, SendProcCtor<{}>, AcceptProcData<string, RequestResult<JToken> | undefined>>;
136
143
  /**有查询参数获取json的get预设 */
137
144
  queryJson(): UtilHttp<D & {
138
145
  method: "GET";
139
- }, SendProc<[QueryRequestData]>, AcceptProc<string, RequestResult<JToken> | undefined>>;
146
+ }, (opt: RequestOption, arg: {
147
+ /**附加的查询表单数据 */
148
+ query: QueryRequestData;
149
+ }) => MPromise<SendProcData>, AcceptProcData<string, RequestResult<JToken> | undefined>>;
140
150
  /**收发皆为json的https-post预设 */
141
151
  static httpsPostJson(): UtilHttp<{
142
152
  readonly protocol: "https:";
@@ -146,7 +156,10 @@ export declare class UtilHttp<D extends Partial<RequestOption> & Required<Pick<R
146
156
  headers: {
147
157
  'Content-Type': "application/json";
148
158
  };
149
- }, SendProc<[JToken]>, AcceptProc<string, RequestResult<JToken> | undefined>>;
159
+ }, (opt: RequestOption, arg: {
160
+ /**发送的json */
161
+ json: JToken;
162
+ }) => MPromise<SendProcData>, AcceptProcData<string, RequestResult<JToken> | undefined>>;
150
163
  /**收发皆为json的http-post预设 */
151
164
  static httpPostJson(): UtilHttp<{
152
165
  readonly protocol: "http:";
@@ -156,67 +169,57 @@ export declare class UtilHttp<D extends Partial<RequestOption> & Required<Pick<R
156
169
  headers: {
157
170
  'Content-Type': "application/json";
158
171
  };
159
- }, SendProc<[JToken]>, AcceptProc<string, RequestResult<JToken> | undefined>>;
172
+ }, (opt: RequestOption, arg: {
173
+ /**发送的json */
174
+ json: JToken;
175
+ }) => MPromise<SendProcData>, AcceptProcData<string, RequestResult<JToken> | undefined>>;
160
176
  /**无查询参数获取json的https-get预设 */
161
177
  static httpsGetJson(): UtilHttp<{
162
178
  readonly protocol: "https:";
163
179
  } & {
164
180
  method: "GET";
165
- }, SendProc<[]>, AcceptProc<string, RequestResult<JToken> | undefined>>;
181
+ }, SendProcCtor<{}>, AcceptProcData<string, RequestResult<JToken> | undefined>>;
166
182
  /**有查询参数获取json的https-get预设 */
167
183
  static httpsQueryJson(): UtilHttp<{
168
184
  readonly protocol: "http:";
169
185
  } & {
170
186
  method: "GET";
171
- }, SendProc<[QueryRequestData]>, AcceptProc<string, RequestResult<JToken> | undefined>>;
187
+ }, (opt: RequestOption, arg: {
188
+ /**附加的查询表单数据 */
189
+ query: QueryRequestData;
190
+ }) => MPromise<SendProcData>, AcceptProcData<string, RequestResult<JToken> | undefined>>;
172
191
  /**无查询参数获取json的http-get预设 */
173
192
  static httpGetJson(): UtilHttp<{
174
193
  readonly protocol: "http:";
175
194
  } & {
176
195
  method: "GET";
177
- }, SendProc<[]>, AcceptProc<string, RequestResult<JToken> | undefined>>;
196
+ }, SendProcCtor<{}>, AcceptProcData<string, RequestResult<JToken> | undefined>>;
178
197
  /**有查询参数获取json的http-get预设 */
179
198
  static httpQueryJson(): UtilHttp<{
180
199
  readonly protocol: "http:";
181
200
  } & {
182
201
  method: "GET";
183
- }, SendProc<[QueryRequestData]>, AcceptProc<string, RequestResult<JToken> | undefined>>;
184
- /**预设的接收数据类型*/
185
- accept<T extends AcceptType>(t: T): {
186
- readonly json: UtilHttp<D, S, AcceptProc<string, RequestResult<JToken> | undefined>>;
187
- readonly string: UtilHttp<D, S, AcceptProc<string, RequestResult<string> | undefined>>;
188
- readonly none: UtilHttp<D, S, AcceptProc<undefined, undefined>>;
189
- }[T];
190
- acceptJson(): UtilHttp<D, S, AcceptProc<string, RequestResult<JToken> | undefined>>;
202
+ }, (opt: RequestOption, arg: {
203
+ /**附加的查询表单数据 */
204
+ query: QueryRequestData;
205
+ }) => MPromise<SendProcData>, AcceptProcData<string, RequestResult<JToken> | undefined>>;
206
+ acceptJson(): UtilHttp<D, S, AcceptProcData<string, RequestResult<JToken> | undefined>>;
191
207
  acceptString(): UtilHttp<D, S, typeof AcceptStringProc>;
192
208
  acceptNone(): UtilHttp<D, S, typeof AcceptNoneProc>;
209
+ acceptFile(): UtilHttp<D, S, (arg: {
210
+ acceptFilepath: string;
211
+ }) => MPromise<AcceptProcData<{
212
+ promise: Promise<boolean>;
213
+ }, {
214
+ /**响应头 */
215
+ headers: http.IncomingHttpHeaders;
216
+ /**响应状态码 */
217
+ statusCode?: number;
218
+ /**保存文件路径 */
219
+ filepath: string;
220
+ } | undefined>>>;
193
221
  /**自定的接收数据类型*/
194
- acceptRaw<AD, AT>(proc: AcceptProc<AD, AT>): UtilHttp<D, S, typeof proc>;
195
- /**预设的发送数据类型 */
196
- send<T extends SendType>(t: T): {
197
- readonly json: UtilHttp<D & {
198
- headers: {
199
- "Content-Type": "application/json";
200
- };
201
- }, SendProc<[JToken]>, A>;
202
- readonly query: UtilHttp<D, SendProc<[QueryRequestData]>, A>;
203
- readonly formData: UtilHttp<D & {
204
- headers: {
205
- "Content-Type": "multipart/form-data";
206
- };
207
- }, SendProc<[FormData]>, A>;
208
- readonly form: UtilHttp<D & {
209
- headers: {
210
- "Content-Type": "application/x-www-form-urlencoded";
211
- };
212
- }, SendProc<[QueryRequestData]>, A>;
213
- readonly file: UtilHttp<D & {
214
- headers: {
215
- "Content-Type": "multipart/form-data";
216
- };
217
- }, SendProc<[string, (string | undefined)?]>, A>;
218
- readonly none: UtilHttp<D, SendProc<[]>, A>;
219
- }[T];
222
+ acceptRaw<AD, AR, AT extends {}>(proc: AcceptProcCtor<AD, AR, AT>): UtilHttp<D, S, typeof proc>;
220
223
  /**发送json
221
224
  * 请求参数为 (token:JToken)
222
225
  */
@@ -224,58 +227,74 @@ export declare class UtilHttp<D extends Partial<RequestOption> & Required<Pick<R
224
227
  headers: {
225
228
  "Content-Type": "application/json";
226
229
  };
227
- }, SendProc<[JToken]>, A>;
228
- /**利用 appendQuery 直接将数据附加在path上发送请求
229
- * 请求参数为 (form:QueryRequestData)
230
- */
231
- sendQuery(): UtilHttp<D, SendProc<[QueryRequestData]>, A>;
232
- /**发送表单数据
233
- * 请求参数为 (formData: FormData)
234
- */
230
+ }, (opt: RequestOption, arg: {
231
+ /**发送的json */
232
+ json: JToken;
233
+ }) => MPromise<SendProcData>, A>;
234
+ /**利用 appendQuery 直接将表单附加在path上发送请求 */
235
+ sendQuery(): UtilHttp<D, (opt: RequestOption, arg: {
236
+ /**附加的查询表单数据 */
237
+ query: QueryRequestData;
238
+ }) => MPromise<SendProcData>, A>;
239
+ /**发送form-data包提供的表单数据 */
235
240
  sendFormData(): UtilHttp<D & {
236
241
  headers: {
237
242
  "Content-Type": "multipart/form-data";
238
243
  };
239
- }, SendProc<[FormData]>, A>;
240
- /**发送表单
241
- * 请求参数为 (form:QueryRequestData)
242
- */
244
+ }, (opt: RequestOption, arg: {
245
+ /**form-data包提供的FormData表单数据 */
246
+ formdata: FormData;
247
+ }) => MPromise<SendProcData>, A>;
248
+ /**发送表单 */
243
249
  sendForm(): UtilHttp<D & {
244
250
  headers: {
245
251
  "Content-Type": "application/x-www-form-urlencoded";
246
252
  };
247
- }, SendProc<[QueryRequestData]>, A>;
248
- /**发送文件
249
- * 请求参数为 (filepath:string, filename?: string)
250
- */
253
+ }, (opt: RequestOption, arg: {
254
+ /**表单 */
255
+ form: QueryRequestData;
256
+ }) => MPromise<SendProcData>, A>;
257
+ /**发送文件 */
251
258
  sendFile(): UtilHttp<D & {
252
259
  headers: {
253
260
  "Content-Type": "multipart/form-data";
254
261
  };
255
- }, SendProc<[string, (string | undefined)?]>, A>;
262
+ }, (opt: RequestOption, arg: {
263
+ /**文件路径 */
264
+ filepath: string;
265
+ /**文件名 */
266
+ filename?: string;
267
+ }) => MPromise<SendProcData>, A>;
256
268
  sendNone(): UtilHttp<D, typeof SendNoneProc, A>;
257
269
  /**自定的发送数据类型 */
258
- sendRaw<T extends any[]>(proc: SendProc<T>): UtilHttp<D, typeof proc, A>;
270
+ sendRaw<T extends any[]>(proc: SendProcCtor<T>): UtilHttp<D, typeof proc, A>;
259
271
  /**发送请求
260
272
  * @param datas - 数据对象
261
273
  */
262
- once(...datas: {} extends RequiredOnly<PartialOption<RequestOption, D>> ? SendParams<S> : [Error & "RequestOption不完整, 请使用 finalize 完成必要项"]): Promise<ParseResult<A>>;
274
+ once<OPT extends PartialOption<RequestOption, D>>(arg: ConflictCheck<SendParams<S>, AcceptParams<A>, ({} extends OPT ? {
275
+ option?: OPT;
276
+ } : {
277
+ option: OPT;
278
+ })>): Promise<ParseResult<A>>;
263
279
  /**重复发送网络请求
264
280
  * @param verify - 有效性验证函数
265
281
  * @param retries - 重试选项 默认 延迟:1000ms 间隔:180_000ms 重试:3次
266
282
  * @param datas - 数据对象
267
283
  */
268
- retry(opt: {
284
+ retry<OPT extends PartialOption<RequestOption, D>>(arg: ConflictCheck<SendParams<S>, AcceptParams<A>, {
269
285
  verify?: StatusVerifyFn<ParseResult<A>>;
270
286
  retries?: PromiseRetries;
271
- }, ...datas: {} extends RequiredOnly<PartialOption<RequestOption, D>> ? SendParams<S> : [Error & "RequestOption不完整, 请使用 finalize 完成必要项"]): Promise<import("@zwa73/js-utils").PromiseRetryResult<ParseResult<A>>>;
287
+ } & ({} extends OPT ? {
288
+ option?: OPT;
289
+ } : {
290
+ option: OPT;
291
+ })>): Promise<import("@zwa73/js-utils").PromiseRetryResult<ParseResult<A>>>;
272
292
  /**发送网络请求
273
- * @param option - 网络请求选项
274
- * @param proc - 请求处理函数 需调用req.end()
275
- * @param reduce - 数据处理函数
276
- * @param init - 初始数据
293
+ * @param option - 网络请求选项
294
+ * @param reqProc - 请求处理函数 需调用req.end()
295
+ * @param acceptProc - 响应处理数据
277
296
  */
278
- static request<T>(option: RequestOption, proc: RequestProcFn, reduce: RequestReduceFn<T>, init: T): Promise<RequestResult<T> | undefined>;
297
+ static request<T>(option: RequestOption, sendProc: SendProcData, acceptProc: Omit<AcceptProcData<T, unknown>, 'parse'>): Promise<RequestResult<T> | undefined>;
279
298
  /**构建query */
280
299
  static buildQuery(base: string, data: QueryRequestData): string;
281
300
  }
package/dist/UtilHttp.js CHANGED
@@ -16,20 +16,29 @@ const https_proxy_agent_1 = __importDefault(require("https-proxy-agent"));
16
16
  const js_utils_1 = require("@zwa73/js-utils");
17
17
  const fs_1 = __importDefault(require("fs"));
18
18
  const pathe_1 = __importDefault(require("pathe"));
19
- const AcceptTypeList = ["json", "string"];
20
- const SendTypeList = ["json", "query", "formData", "none"];
21
19
  const SendNoneProc = {
22
- proc: (opt) => (req) => void req.end()
20
+ proc: req => void req.end()
23
21
  };
24
22
  const AcceptStringProc = {
25
- init: '',
23
+ init: () => '',
26
24
  reduce: (acc, dat) => acc + dat,
27
- parse: (result) => result
25
+ parse: result => {
26
+ if (result == undefined) {
27
+ UtilLogger_1.SLogger.warn(`accept json 接收反馈错误: 响应结果无效`);
28
+ return undefined;
29
+ }
30
+ return result;
31
+ }
28
32
  };
29
33
  const AcceptNoneProc = {
30
- init: undefined,
31
- reduce: () => undefined,
32
- parse: () => undefined
34
+ init: () => undefined,
35
+ parse: result => {
36
+ if (result == undefined) {
37
+ UtilLogger_1.SLogger.warn(`accept none 接收反馈错误: 响应结果无效`);
38
+ return undefined;
39
+ }
40
+ return result;
41
+ }
33
42
  };
34
43
  /**http请求工具 */
35
44
  class UtilHttp {
@@ -80,14 +89,6 @@ class UtilHttp {
80
89
  this._data = { ...this._data, ...option };
81
90
  return this;
82
91
  }
83
- /**完成参数
84
- * 会检查必要参数完整性
85
- * 将会替换对应字段, 修改headers请用header函数
86
- */
87
- finalize(option) {
88
- this._data = { ...this._data, ...option };
89
- return this;
90
- }
91
92
  /**补充header */
92
93
  header(headers) {
93
94
  this._data.headers = {
@@ -157,41 +158,32 @@ class UtilHttp {
157
158
  }
158
159
  //#endregion
159
160
  //#region 接收数据类型
160
- /**预设的接收数据类型*/
161
- accept(t) {
162
- const map = {
163
- 'json': this.acceptJson(),
164
- 'string': this.acceptString(),
165
- 'none': this.acceptNone(),
166
- };
167
- return map[t];
168
- }
169
161
  acceptJson() {
170
- const proc = {
171
- init: '',
162
+ const acceptProc = {
163
+ init: () => '',
172
164
  reduce: (acc, curr) => acc + curr,
173
- parse: (result) => {
165
+ parse: result => {
174
166
  if (result == undefined) {
175
- UtilLogger_1.SLogger.warn(`json accept 接收反馈错误: 响应结果无效`);
167
+ UtilLogger_1.SLogger.warn(`accept json 接收反馈错误: 响应结果无效`);
176
168
  return undefined;
177
169
  }
178
170
  const { data, ...rest } = result;
179
171
  if (data.trim() == "") {
180
- UtilLogger_1.SLogger.warn(`json accept 接收反馈错误: 原始字符串为空`, UtilFunctions_1.UtilFunc.stringifyJToken(result, { compress: true, space: 2 }));
172
+ UtilLogger_1.SLogger.warn(`accept json 接收反馈错误: 原始字符串为空`, UtilFunctions_1.UtilFunc.stringifyJToken(result, { compress: true, space: 2 }));
181
173
  return { ...result, raw: "", data: null };
182
174
  }
183
175
  try {
184
176
  const obj = JSON.parse(data.trim());
185
- UtilLogger_1.SLogger.http(`json accept 接受信息 data:`, UtilFunctions_1.UtilFunc.stringifyJToken(obj, { compress: true, space: 2 }), `result:`, UtilFunctions_1.UtilFunc.stringifyJToken(rest, { compress: true, space: 2 }));
177
+ UtilLogger_1.SLogger.http(`accept json 接受信息 data:`, UtilFunctions_1.UtilFunc.stringifyJToken(obj, { compress: true, space: 2 }), `result:`, UtilFunctions_1.UtilFunc.stringifyJToken(rest, { compress: true, space: 2 }));
186
178
  return { ...rest, data: obj };
187
179
  }
188
180
  catch (err) {
189
- UtilLogger_1.SLogger.warn(`json accept 接收反馈错误:`, err, UtilFunctions_1.UtilFunc.stringifyJToken(result, { compress: true, space: 2 }));
181
+ UtilLogger_1.SLogger.warn(`accept json 接收反馈错误:`, err, UtilFunctions_1.UtilFunc.stringifyJToken(result, { compress: true, space: 2 }));
190
182
  return { ...result, raw: data, data: null };
191
183
  }
192
184
  }
193
185
  };
194
- this._accept = proc;
186
+ this._accept = acceptProc;
195
187
  return this;
196
188
  }
197
189
  acceptString() {
@@ -202,6 +194,36 @@ class UtilHttp {
202
194
  this._accept = AcceptNoneProc;
203
195
  return this;
204
196
  }
197
+ acceptFile() {
198
+ const acceptProc = (arg) => ({
199
+ init: res => {
200
+ const fileStream = fs_1.default.createWriteStream(arg.acceptFilepath);
201
+ const fileWritePromise = new Promise((resolve) => {
202
+ fileStream.on('error', err => {
203
+ UtilLogger_1.SLogger.warn(`accept file 文件流写入错误:`, err);
204
+ resolve(false); // 标记写入已结束, 但失败
205
+ });
206
+ fileStream.on('finish', () => {
207
+ resolve(true); // 标记写入成功
208
+ });
209
+ });
210
+ res.pipe(fileStream);
211
+ return { promise: fileWritePromise };
212
+ },
213
+ parse: async (result) => {
214
+ if (result == undefined) {
215
+ UtilLogger_1.SLogger.warn(`accept file 接收反馈错误: 响应结果无效`);
216
+ return undefined;
217
+ }
218
+ const success = await result.data.promise;
219
+ if (!success)
220
+ return undefined;
221
+ return { ...result, filepath: arg.acceptFilepath };
222
+ }
223
+ });
224
+ this._accept = acceptProc;
225
+ return this;
226
+ }
205
227
  /**自定的接收数据类型*/
206
228
  acceptRaw(proc) {
207
229
  this._accept = proc;
@@ -209,113 +231,99 @@ class UtilHttp {
209
231
  }
210
232
  //#endregion
211
233
  //#region 发送数据类型
212
- /**预设的发送数据类型 */
213
- send(t) {
214
- const map = {
215
- 'json': this.sendJson(),
216
- 'query': this.sendQuery(),
217
- 'formData': this.sendFormData(),
218
- 'form': this.sendForm(),
219
- 'file': this.sendFile(),
220
- 'none': this.sendNone(),
221
- };
222
- return map[t];
223
- }
224
234
  /**发送json
225
235
  * 请求参数为 (token:JToken)
226
236
  */
227
237
  sendJson() {
228
- const proc = {
229
- proc: (opt, token) => {
230
- const { method } = opt;
231
- const isPost = (method == "POST");
232
- const data = JSON.stringify(token);
233
- this._data.headers ??= {};
234
- this._data.headers['Content-Length'] = Buffer.byteLength(data);
235
- const procReq = (req) => {
238
+ const sendProc = (opt, arg) => {
239
+ const { method } = opt;
240
+ const isPost = (method == "POST");
241
+ const data = JSON.stringify(arg.json);
242
+ this._data.headers ??= {};
243
+ this._data.headers['Content-Length'] = Buffer.byteLength(data);
244
+ return {
245
+ proc: req => {
236
246
  if (isPost)
237
247
  req.write(data);
238
248
  req.end();
239
- };
240
- return procReq;
241
- }
249
+ }
250
+ };
242
251
  };
243
- this._send = proc;
252
+ this._send = sendProc;
244
253
  this._data.headers ??= {};
245
254
  this._data.headers['Content-Type'] = 'application/json';
246
255
  return this;
247
256
  }
248
- /**利用 appendQuery 直接将数据附加在path上发送请求
249
- * 请求参数为 (form:QueryRequestData)
250
- */
257
+ /**利用 appendQuery 直接将表单附加在path上发送请求 */
251
258
  sendQuery() {
252
- const proc = {
253
- proc: (opt, form) => {
254
- opt.path = UtilHttp.buildQuery(opt.path ?? '', form);
255
- const procReq = (req) => void req.end();
256
- return procReq;
257
- }
259
+ const sendProc = (opt, arg) => {
260
+ opt.path = UtilHttp.buildQuery(opt.path ?? '', arg.query);
261
+ return {
262
+ proc: req => void req.end()
263
+ };
258
264
  };
259
- this._send = proc;
265
+ this._send = sendProc;
260
266
  return this;
261
267
  }
262
- /**发送表单数据
263
- * 请求参数为 (formData: FormData)
264
- */
268
+ /**发送form-data包提供的表单数据 */
265
269
  sendFormData() {
266
- const proc = {
267
- proc: (opt, formData) => {
268
- opt.headers = formData.getHeaders();
269
- const procReq = (req) => {
270
- formData.pipe(req);
271
- };
272
- return procReq;
273
- },
270
+ const sendProc = (opt, arg) => {
271
+ const { method } = opt;
272
+ const isPost = (method == "POST");
273
+ opt.headers = arg.formdata.getHeaders();
274
+ return {
275
+ proc: (req) => {
276
+ if (isPost)
277
+ arg.formdata.pipe(req);
278
+ else
279
+ req.end();
280
+ }
281
+ };
274
282
  };
275
- this._send = proc;
283
+ this._send = sendProc;
276
284
  this._data.headers ??= {};
277
285
  this._data.headers['Content-Type'] = 'multipart/form-data';
278
286
  return this;
279
287
  }
280
- /**发送表单
281
- * 请求参数为 (form:QueryRequestData)
282
- */
288
+ /**发送表单 */
283
289
  sendForm() {
284
- const proc = {
285
- proc: (opt, form) => {
286
- const { method } = opt;
287
- const isPost = (method == "POST");
288
- const data = querystring_1.default.stringify(form);
289
- this._data.headers ??= {};
290
- this._data.headers['Content-Length'] = Buffer.byteLength(data);
291
- const procReq = (req) => {
290
+ const snedProc = (opt, arg) => {
291
+ const { method } = opt;
292
+ const isPost = (method == "POST");
293
+ const data = querystring_1.default.stringify(arg.form);
294
+ this._data.headers ??= {};
295
+ this._data.headers['Content-Length'] = Buffer.byteLength(data);
296
+ return {
297
+ proc: req => {
292
298
  if (isPost)
293
299
  req.write(data);
294
300
  req.end();
295
- };
296
- return procReq;
297
- }
301
+ }
302
+ };
298
303
  };
299
- this._send = proc;
304
+ this._send = snedProc;
300
305
  this._data.headers ??= {};
301
306
  this._data.headers['Content-Type'] = 'application/x-www-form-urlencoded';
302
307
  return this;
303
308
  }
304
- /**发送文件
305
- * 请求参数为 (filepath:string, filename?: string)
306
- */
309
+ /**发送文件 */
307
310
  sendFile() {
308
- const proc = {
309
- proc: (opt, filepath, filename) => {
310
- const formData = new form_data_1.default();
311
- filename = filename ?? pathe_1.default.basename(filepath);
312
- formData.append(filename, fs_1.default.createReadStream(filepath));
313
- opt.headers = formData.getHeaders();
314
- const procReq = (req) => {
315
- formData.pipe(req);
316
- };
317
- return procReq;
318
- },
311
+ const proc = (opt, arg) => {
312
+ const { method } = opt;
313
+ const isPost = (method == "POST");
314
+ let { filepath, filename } = arg;
315
+ const formData = new form_data_1.default();
316
+ filename = filename ?? pathe_1.default.basename(filepath);
317
+ formData.append(filename, fs_1.default.createReadStream(filepath));
318
+ opt.headers = formData.getHeaders();
319
+ return {
320
+ proc: req => {
321
+ if (isPost)
322
+ formData.pipe(req);
323
+ else
324
+ req.end();
325
+ }
326
+ };
319
327
  };
320
328
  this._send = proc;
321
329
  this._data.headers ??= {};
@@ -335,11 +343,15 @@ class UtilHttp {
335
343
  /**发送请求
336
344
  * @param datas - 数据对象
337
345
  */
338
- async once(...datas) {
339
- const fullopt = this._data;
340
- const proc = await this._send.proc(fullopt, ...datas);
341
- const { reduce, init, parse } = this._accept;
342
- const res = await UtilHttp.request(fullopt, proc, reduce, init);
346
+ async once(arg) {
347
+ const fullopt = { ...this._data, ...arg.option ?? {} };
348
+ const sendProc = typeof this._send === 'function'
349
+ ? await this._send(fullopt, arg)
350
+ : this._send;
351
+ const { parse, ...acceptProc } = typeof this._accept === 'function'
352
+ ? await this._accept(arg)
353
+ : this._accept;
354
+ const res = await UtilHttp.request(fullopt, sendProc, acceptProc);
343
355
  return parse(res);
344
356
  }
345
357
  /**重复发送网络请求
@@ -347,20 +359,21 @@ class UtilHttp {
347
359
  * @param retries - 重试选项 默认 延迟:1000ms 间隔:180_000ms 重试:3次
348
360
  * @param datas - 数据对象
349
361
  */
350
- async retry(opt, ...datas) {
351
- let { retries, verify } = opt;
362
+ async retry(arg) {
363
+ let { retries, verify } = arg;
352
364
  retries ??= {};
353
365
  retries.tryDelay = retries.tryDelay ?? 1000;
354
- const procFn = async () => this.once(...datas);
366
+ const procFn = async () => this.once(arg);
355
367
  return UtilFunctions_1.UtilFunc.retryPromise(procFn, verify, retries);
356
368
  }
357
369
  /**发送网络请求
358
- * @param option - 网络请求选项
359
- * @param proc - 请求处理函数 需调用req.end()
360
- * @param reduce - 数据处理函数
361
- * @param init - 初始数据
370
+ * @param option - 网络请求选项
371
+ * @param reqProc - 请求处理函数 需调用req.end()
372
+ * @param acceptProc - 响应处理数据
362
373
  */
363
- static async request(option, proc, reduce, init) {
374
+ static async request(option, sendProc, acceptProc) {
375
+ const { reduce: reqReduce, init: reqInit } = acceptProc;
376
+ const { proc: reqProc } = sendProc;
364
377
  const { protocol, timeout, ...baseReqOpt } = option;
365
378
  const plusTimeout = (timeout ?? 0) + 1000;
366
379
  const hasTimeLimit = (timeout ? timeout >= 10_000 : false);
@@ -379,7 +392,7 @@ class UtilHttp {
379
392
  clearTimeout(finallyTimeout);
380
393
  resolve(t);
381
394
  };
382
- const resFunc = (res) => {
395
+ const resFunc = async (res) => {
383
396
  try {
384
397
  //请求超时
385
398
  if (hasTimeLimit) {
@@ -387,16 +400,30 @@ class UtilHttp {
387
400
  UtilLogger_1.SLogger.warn(`${flagName} http.response 触发 ${timeout} ms 超时, 继续挂起等待`);
388
401
  });
389
402
  }
390
- let mergedata = init;
403
+ let mergedata;
404
+ try {
405
+ mergedata = await reqInit(res);
406
+ }
407
+ catch (err) {
408
+ UtilLogger_1.SLogger.error(`${flagName} init函数错误:`, err);
409
+ finallyResolve(undefined);
410
+ return;
411
+ }
391
412
  res.setEncoding(option.responseEncode ?? 'utf8');
392
- res.on('data', chunk => {
393
- dataPromise = reduceQueue
394
- .enqueue(async () => mergedata = await reduce(mergedata, chunk))
395
- .catch(err => {
396
- UtilLogger_1.SLogger.error(`${flagName} reduce函数错误:`, err, `chunk:${chunk}\nmergedata:`, mergedata);
397
- finallyResolve(undefined);
413
+ if (reqReduce) {
414
+ res.on('data', chunk => {
415
+ dataPromise = reduceQueue
416
+ .enqueue(async () => {
417
+ try {
418
+ mergedata = await reqReduce(mergedata, chunk);
419
+ }
420
+ catch (err) {
421
+ UtilLogger_1.SLogger.error(`${flagName} reduce函数错误:`, err, `chunk:${chunk}\nmergedata:`, mergedata);
422
+ finallyResolve(undefined);
423
+ }
424
+ });
398
425
  });
399
- });
426
+ }
400
427
  res.on('error', err => {
401
428
  UtilLogger_1.SLogger.warn(`${flagName} 接收反馈错误:`, err);
402
429
  finallyResolve(undefined);
@@ -431,7 +458,7 @@ class UtilHttp {
431
458
  finallyResolve(undefined);
432
459
  });
433
460
  try {
434
- await proc(req);
461
+ await reqProc(req);
435
462
  }
436
463
  catch (err) {
437
464
  UtilLogger_1.SLogger.error(`${flagName} proc函数错误:`, err);
@@ -456,24 +483,30 @@ if (false)
456
483
  const tool = UtilHttp
457
484
  .url('https://httpbin.org/post')
458
485
  .post()
459
- .finalize({ timeout: 10000 });
486
+ .option({ timeout: 20000 });
460
487
  //json
461
488
  const sj = await tool.clone()
462
489
  .sendJson()
463
490
  .acceptJson()
464
- .once({ test: 1 });
491
+ .once({
492
+ json: { test: 1 },
493
+ });
465
494
  console.log(sj);
466
495
  //form
467
496
  const sf = await tool.clone()
468
497
  .sendForm()
469
498
  .acceptJson()
470
- .once({ test: 1 });
499
+ .once({
500
+ form: { test: 1 }
501
+ });
471
502
  console.log(sf);
472
503
  //query
473
504
  const sq = await tool.clone()
474
505
  .sendQuery()
475
506
  .acceptJson()
476
- .once({ test: 1 });
507
+ .once({
508
+ query: { test: 1 }
509
+ });
477
510
  console.log(sq);
478
511
  const filepath = pathe_1.default.join(__dirname, '..', 'input.wav');
479
512
  //formData
@@ -487,6 +520,8 @@ if (false)
487
520
  const sfile = await tool.clone()
488
521
  .sendFile()
489
522
  .acceptJson()
490
- .once(filepath);
523
+ .once({
524
+ filepath: filepath
525
+ });
491
526
  console.log(sfile);
492
527
  })());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zwa73/utils",
3
- "version": "1.0.232",
3
+ "version": "1.0.234",
4
4
  "description": "my utils",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {