@zwa73/utils 1.0.232 → 1.0.233

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