@naturalcycles/js-lib 14.155.1 → 14.157.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import type { Inclusiveness, LocalDateConfig, LocalDateUnit } from './localDate';
1
+ import type { Inclusiveness, LocalDateInput, LocalDateUnit } from './localDate';
2
2
  import { LocalDate } from './localDate';
3
3
  export type DateIntervalConfig = DateInterval | DateIntervalString;
4
4
  export type DateIntervalString = string;
@@ -11,7 +11,7 @@ export declare class DateInterval {
11
11
  start: LocalDate;
12
12
  end: LocalDate;
13
13
  private constructor();
14
- static of(start: LocalDateConfig, end: LocalDateConfig): DateInterval;
14
+ static of(start: LocalDateInput, end: LocalDateInput): DateInterval;
15
15
  /**
16
16
  * Parses string like `2022-02-24/2023-03-30` into a DateInterval.
17
17
  */
@@ -24,7 +24,7 @@ export declare class DateInterval {
24
24
  /**
25
25
  * Ranges of DateInterval (start, end) are INCLUSIVE.
26
26
  */
27
- includes(d: LocalDateConfig, incl?: Inclusiveness): boolean;
27
+ includes(d: LocalDateInput, incl?: Inclusiveness): boolean;
28
28
  intersects(int: DateIntervalConfig, inclusive?: boolean): boolean;
29
29
  /**
30
30
  * DateIntervals compare by start date.
@@ -3,7 +3,7 @@ import { LocalTime } from './localTime';
3
3
  export type LocalDateUnit = LocalDateUnitStrict | 'week';
4
4
  export type LocalDateUnitStrict = 'year' | 'month' | 'day';
5
5
  export type Inclusiveness = '()' | '[]' | '[)' | '(]';
6
- export type LocalDateConfig = LocalDate | Date | IsoDateString;
6
+ export type LocalDateInput = LocalDate | Date | IsoDateString;
7
7
  export type LocalDateFormatter = (ld: LocalDate) => string;
8
8
  /**
9
9
  * @experimental
@@ -18,23 +18,23 @@ export declare class LocalDate {
18
18
  * Parses input String into LocalDate.
19
19
  * Input can already be a LocalDate - it is returned as-is in that case.
20
20
  */
21
- static of(d: LocalDateConfig): LocalDate;
21
+ static of(d: LocalDateInput): LocalDate;
22
22
  static parseCompact(d: string): LocalDate;
23
23
  static fromDate(d: Date): LocalDate;
24
24
  static fromDateUTC(d: Date): LocalDate;
25
25
  /**
26
26
  * Returns null if invalid.
27
27
  */
28
- static parseOrNull(d: LocalDateConfig | undefined | null): LocalDate | null;
28
+ static parseOrNull(d: LocalDateInput | undefined | null): LocalDate | null;
29
29
  static isValid(iso: string | undefined | null): boolean;
30
30
  static today(): LocalDate;
31
31
  static todayUTC(): LocalDate;
32
32
  static sort(items: LocalDate[], mutate?: boolean, descending?: boolean): LocalDate[];
33
- static earliestOrUndefined(items: LocalDateConfig[]): LocalDate | undefined;
34
- static earliest(items: LocalDateConfig[]): LocalDate;
35
- static latestOrUndefined(items: LocalDateConfig[]): LocalDate | undefined;
36
- static latest(items: LocalDateConfig[]): LocalDate;
37
- static range(min: LocalDateConfig, max: LocalDateConfig, incl?: Inclusiveness, step?: number, stepUnit?: LocalDateUnit): LocalDate[];
33
+ static earliestOrUndefined(items: LocalDateInput[]): LocalDate | undefined;
34
+ static earliest(items: LocalDateInput[]): LocalDate;
35
+ static latestOrUndefined(items: LocalDateInput[]): LocalDate | undefined;
36
+ static latest(items: LocalDateInput[]): LocalDate;
37
+ static range(min: LocalDateInput, max: LocalDateInput, incl?: Inclusiveness, step?: number, stepUnit?: LocalDateUnit): LocalDate[];
38
38
  get(unit: LocalDateUnitStrict): number;
39
39
  set(unit: LocalDateUnitStrict, v: number, mutate?: boolean): LocalDate;
40
40
  year(): number;
@@ -43,28 +43,28 @@ export declare class LocalDate {
43
43
  month(v: number): LocalDate;
44
44
  day(): number;
45
45
  day(v: number): LocalDate;
46
- isSame(d: LocalDateConfig): boolean;
47
- isBefore(d: LocalDateConfig, inclusive?: boolean): boolean;
48
- isSameOrBefore(d: LocalDateConfig): boolean;
49
- isAfter(d: LocalDateConfig, inclusive?: boolean): boolean;
50
- isSameOrAfter(d: LocalDateConfig): boolean;
51
- isBetween(min: LocalDateConfig, max: LocalDateConfig, incl?: Inclusiveness): boolean;
46
+ isSame(d: LocalDateInput): boolean;
47
+ isBefore(d: LocalDateInput, inclusive?: boolean): boolean;
48
+ isSameOrBefore(d: LocalDateInput): boolean;
49
+ isAfter(d: LocalDateInput, inclusive?: boolean): boolean;
50
+ isSameOrAfter(d: LocalDateInput): boolean;
51
+ isBetween(min: LocalDateInput, max: LocalDateInput, incl?: Inclusiveness): boolean;
52
52
  /**
53
53
  * Returns 1 if this > d
54
54
  * returns 0 if they are equal
55
55
  * returns -1 if this < d
56
56
  */
57
- cmp(d: LocalDateConfig): -1 | 0 | 1;
57
+ cmp(d: LocalDateInput): -1 | 0 | 1;
58
58
  /**
59
59
  * Same as Math.abs( diff )
60
60
  */
61
- absDiff(d: LocalDateConfig, unit: LocalDateUnit): number;
61
+ absDiff(d: LocalDateInput, unit: LocalDateUnit): number;
62
62
  /**
63
63
  * Returns the number of **full** units difference (aka `Math.floor`).
64
64
  *
65
65
  * a.diff(b) means "a minus b"
66
66
  */
67
- diff(d: LocalDateConfig, unit: LocalDateUnit): number;
67
+ diff(d: LocalDateInput, unit: LocalDateUnit): number;
68
68
  add(num: number, unit: LocalDateUnit, mutate?: boolean): LocalDate;
69
69
  subtract(num: number, unit: LocalDateUnit, mutate?: boolean): LocalDate;
70
70
  startOf(unit: LocalDateUnitStrict): LocalDate;
@@ -96,4 +96,4 @@ export declare class LocalDate {
96
96
  /**
97
97
  * Shortcut wrapper around `LocalDate.parse` / `LocalDate.today`
98
98
  */
99
- export declare function localDate(d?: LocalDateConfig): LocalDate;
99
+ export declare function localDate(d?: LocalDateInput): LocalDate;
@@ -11,7 +11,7 @@ export declare enum ISODayOfWeek {
11
11
  SATURDAY = 6,
12
12
  SUNDAY = 7
13
13
  }
14
- export type LocalTimeConfig = LocalTime | Date | IsoDateTimeString | UnixTimestampNumber;
14
+ export type LocalTimeInput = LocalTime | Date | IsoDateTimeString | UnixTimestampNumber;
15
15
  export type LocalTimeFormatter = (ld: LocalTime) => string;
16
16
  export interface LocalTimeComponents {
17
17
  year: number;
@@ -31,7 +31,7 @@ export declare class LocalTime {
31
31
  * Parses input String into LocalDate.
32
32
  * Input can already be a LocalDate - it is returned as-is in that case.
33
33
  */
34
- static of(d: LocalTimeConfig): LocalTime;
34
+ static of(d: LocalTimeInput): LocalTime;
35
35
  /**
36
36
  * Create LocalTime from unixTimestamp in milliseconds (not in seconds).
37
37
  */
@@ -39,10 +39,10 @@ export declare class LocalTime {
39
39
  /**
40
40
  * Returns null if invalid
41
41
  */
42
- static parseOrNull(d: LocalTimeConfig | undefined | null): LocalTime | null;
43
- static parseToDate(d: LocalTimeConfig): Date;
44
- static parseToUnixTimestamp(d: LocalTimeConfig): UnixTimestampNumber;
45
- static isValid(d: LocalTimeConfig | undefined | null): boolean;
42
+ static parseOrNull(d: LocalTimeInput | undefined | null): LocalTime | null;
43
+ static parseToDate(d: LocalTimeInput): Date;
44
+ static parseToUnixTimestamp(d: LocalTimeInput): UnixTimestampNumber;
45
+ static isValid(d: LocalTimeInput | undefined | null): boolean;
46
46
  static now(): LocalTime;
47
47
  static fromComponents(c: {
48
48
  year: number;
@@ -72,29 +72,29 @@ export declare class LocalTime {
72
72
  setComponents(c: Partial<LocalTimeComponents>, mutate?: boolean): LocalTime;
73
73
  add(num: number, unit: LocalTimeUnit, mutate?: boolean): LocalTime;
74
74
  subtract(num: number, unit: LocalTimeUnit, mutate?: boolean): LocalTime;
75
- absDiff(other: LocalTimeConfig, unit: LocalTimeUnit): number;
76
- diff(other: LocalTimeConfig, unit: LocalTimeUnit): number;
75
+ absDiff(other: LocalTimeInput, unit: LocalTimeUnit): number;
76
+ diff(other: LocalTimeInput, unit: LocalTimeUnit): number;
77
77
  startOf(unit: LocalTimeUnit, mutate?: boolean): LocalTime;
78
78
  endOf(unit: LocalTimeUnit, mutate?: boolean): LocalTime;
79
79
  static sort(items: LocalTime[], mutate?: boolean, descending?: boolean): LocalTime[];
80
- static earliestOrUndefined(items: LocalTimeConfig[]): LocalTime | undefined;
81
- static earliest(items: LocalTimeConfig[]): LocalTime;
82
- static latestOrUndefined(items: LocalTimeConfig[]): LocalTime | undefined;
83
- static latest(items: LocalTimeConfig[]): LocalTime;
84
- isSame(d: LocalTimeConfig): boolean;
85
- isBefore(d: LocalTimeConfig, inclusive?: boolean): boolean;
86
- isSameOrBefore(d: LocalTimeConfig): boolean;
87
- isAfter(d: LocalTimeConfig, inclusive?: boolean): boolean;
88
- isSameOrAfter(d: LocalTimeConfig): boolean;
89
- isBetween(min: LocalTimeConfig, max: LocalTimeConfig, incl?: Inclusiveness): boolean;
80
+ static earliestOrUndefined(items: LocalTimeInput[]): LocalTime | undefined;
81
+ static earliest(items: LocalTimeInput[]): LocalTime;
82
+ static latestOrUndefined(items: LocalTimeInput[]): LocalTime | undefined;
83
+ static latest(items: LocalTimeInput[]): LocalTime;
84
+ isSame(d: LocalTimeInput): boolean;
85
+ isBefore(d: LocalTimeInput, inclusive?: boolean): boolean;
86
+ isSameOrBefore(d: LocalTimeInput): boolean;
87
+ isAfter(d: LocalTimeInput, inclusive?: boolean): boolean;
88
+ isSameOrAfter(d: LocalTimeInput): boolean;
89
+ isBetween(min: LocalTimeInput, max: LocalTimeInput, incl?: Inclusiveness): boolean;
90
90
  /**
91
91
  * Returns 1 if this > d
92
92
  * returns 0 if they are equal
93
93
  * returns -1 if this < d
94
94
  */
95
- cmp(d: LocalTimeConfig): -1 | 0 | 1;
95
+ cmp(d: LocalTimeInput): -1 | 0 | 1;
96
96
  components(): LocalTimeComponents;
97
- fromNow(now?: LocalTimeConfig): string;
97
+ fromNow(now?: LocalTimeInput): string;
98
98
  getDate(): Date;
99
99
  clone(): LocalTime;
100
100
  unix(): UnixTimestampNumber;
@@ -125,4 +125,4 @@ export declare class LocalTime {
125
125
  /**
126
126
  * Shortcut wrapper around `LocalDate.parse` / `LocalDate.today`
127
127
  */
128
- export declare function localTime(d?: LocalTimeConfig): LocalTime;
128
+ export declare function localTime(d?: LocalTimeInput): LocalTime;
@@ -1,6 +1,6 @@
1
1
  import type { UnixTimestampNumber } from '../types';
2
2
  import type { Inclusiveness } from './localDate';
3
- import type { LocalTimeConfig } from './localTime';
3
+ import type { LocalTimeInput } from './localTime';
4
4
  import { LocalTime } from './localTime';
5
5
  export type TimeIntervalConfig = TimeInterval | TimeIntervalString;
6
6
  export type TimeIntervalString = string;
@@ -14,7 +14,7 @@ export declare class TimeInterval {
14
14
  private $start;
15
15
  private $end;
16
16
  private constructor();
17
- static of(start: LocalTimeConfig, end: LocalTimeConfig): TimeInterval;
17
+ static of(start: LocalTimeInput, end: LocalTimeInput): TimeInterval;
18
18
  get start(): UnixTimestampNumber;
19
19
  get end(): UnixTimestampNumber;
20
20
  get startTime(): LocalTime;
@@ -28,7 +28,7 @@ export declare class TimeInterval {
28
28
  isSameOrBefore(d: TimeIntervalConfig): boolean;
29
29
  isAfter(d: TimeIntervalConfig, inclusive?: boolean): boolean;
30
30
  isSameOrAfter(d: TimeIntervalConfig): boolean;
31
- includes(d: LocalTimeConfig, incl?: Inclusiveness): boolean;
31
+ includes(d: LocalTimeInput, incl?: Inclusiveness): boolean;
32
32
  /**
33
33
  * TimeIntervals compare by start date.
34
34
  * If it's the same - then by end date.
@@ -0,0 +1,9 @@
1
+ import type { AnyObject } from './types';
2
+ /**
3
+ * Convert any object to FormData.
4
+ * Please note that every key and value of FormData is `string`.
5
+ * Even if you pass a number - it'll be converted to string.
6
+ * Think URLSearchParams.
7
+ */
8
+ export declare function objectToFormData(obj?: AnyObject): FormData;
9
+ export declare function formDataToObject<T extends AnyObject>(formData: FormData): T;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formDataToObject = exports.objectToFormData = void 0;
4
+ /**
5
+ * Convert any object to FormData.
6
+ * Please note that every key and value of FormData is `string`.
7
+ * Even if you pass a number - it'll be converted to string.
8
+ * Think URLSearchParams.
9
+ */
10
+ function objectToFormData(obj = {}) {
11
+ const fd = new FormData();
12
+ Object.entries(obj).forEach(([k, v]) => fd.append(k, v));
13
+ return fd;
14
+ }
15
+ exports.objectToFormData = objectToFormData;
16
+ function formDataToObject(formData) {
17
+ return Object.fromEntries(formData);
18
+ }
19
+ exports.formDataToObject = formDataToObject;
@@ -1,4 +1,5 @@
1
1
  /// <reference lib="dom" />
2
+ /// <reference lib="dom.iterable" />
2
3
  import type { FetcherAfterResponseHook, FetcherBeforeRequestHook, FetcherBeforeRetryHook, FetcherCfg, FetcherNormalizedCfg, FetcherOptions, FetcherResponse } from './fetcher.model';
3
4
  /**
4
5
  * Experimental wrapper around Fetch.
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  /// <reference lib="dom"/>
3
+ /// <reference lib="dom.iterable"/>
3
4
  Object.defineProperty(exports, "__esModule", { value: true });
4
5
  exports.getFetcher = exports.Fetcher = void 0;
5
6
  const env_1 = require("../env");
@@ -13,6 +14,14 @@ const json_util_1 = require("../string/json.util");
13
14
  const stringifyAny_1 = require("../string/stringifyAny");
14
15
  const time_util_1 = require("../time/time.util");
15
16
  const http_model_1 = require("./http.model");
17
+ const acceptByResponseType = {
18
+ text: 'text/plain',
19
+ json: 'application/json',
20
+ void: '*/*',
21
+ readableStream: 'application/octet-stream',
22
+ arrayBuffer: 'application/octet-stream',
23
+ blob: 'application/octet-stream',
24
+ };
16
25
  const defRetryOptions = {
17
26
  count: 2,
18
27
  timeout: 1000,
@@ -36,18 +45,18 @@ class Fetcher {
36
45
  return await this.fetch({
37
46
  url,
38
47
  method,
39
- mode: 'void',
48
+ responseType: 'void',
40
49
  ...opt,
41
50
  });
42
51
  };
43
52
  if (method === 'HEAD')
44
- return // mode=text
53
+ return // responseType=text
45
54
  ;
46
55
  this[`${m}Text`] = async (url, opt) => {
47
56
  return await this.fetch({
48
57
  url,
49
58
  method,
50
- mode: 'text',
59
+ responseType: 'text',
51
60
  ...opt,
52
61
  });
53
62
  };
@@ -55,7 +64,7 @@ class Fetcher {
55
64
  return await this.fetch({
56
65
  url,
57
66
  method,
58
- mode: 'json',
67
+ responseType: 'json',
59
68
  ...opt,
60
69
  });
61
70
  };
@@ -82,7 +91,7 @@ class Fetcher {
82
91
  static create(cfg = {}) {
83
92
  return new Fetcher(cfg);
84
93
  }
85
- // mode=readableStream
94
+ // responseType=readableStream
86
95
  /**
87
96
  * Returns raw fetchResponse.body, which is a ReadableStream<Uint8Array>
88
97
  *
@@ -92,7 +101,7 @@ class Fetcher {
92
101
  async getReadableStream(url, opt) {
93
102
  return await this.fetch({
94
103
  url,
95
- mode: 'readableStream',
104
+ responseType: 'readableStream',
96
105
  ...opt,
97
106
  });
98
107
  }
@@ -183,8 +192,8 @@ class Fetcher {
183
192
  }
184
193
  async onOkResponse(res, timeout) {
185
194
  const { req } = res;
186
- const { mode } = res.req;
187
- if (mode === 'json') {
195
+ const { responseType } = res.req;
196
+ if (responseType === 'json') {
188
197
  if (res.fetchResponse.body) {
189
198
  const text = await res.fetchResponse.text();
190
199
  if (text) {
@@ -218,16 +227,16 @@ class Fetcher {
218
227
  res.body = {};
219
228
  }
220
229
  }
221
- else if (mode === 'text') {
230
+ else if (responseType === 'text') {
222
231
  res.body = res.fetchResponse.body ? await res.fetchResponse.text() : '';
223
232
  }
224
- else if (mode === 'arrayBuffer') {
233
+ else if (responseType === 'arrayBuffer') {
225
234
  res.body = res.fetchResponse.body ? await res.fetchResponse.arrayBuffer() : {};
226
235
  }
227
- else if (mode === 'blob') {
236
+ else if (responseType === 'blob') {
228
237
  res.body = res.fetchResponse.body ? await res.fetchResponse.blob() : {};
229
238
  }
230
- else if (mode === 'readableStream') {
239
+ else if (responseType === 'readableStream') {
231
240
  res.body = res.fetchResponse.body;
232
241
  if (res.body === null) {
233
242
  res.err = new Error(`fetchResponse.body is null`);
@@ -429,7 +438,7 @@ class Fetcher {
429
438
  const norm = (0, object_util_1._merge)({
430
439
  baseUrl: '',
431
440
  inputUrl: '',
432
- mode: 'void',
441
+ responseType: 'void',
433
442
  searchParams: {},
434
443
  timeoutSeconds: 30,
435
444
  retryPost: false,
@@ -448,7 +457,10 @@ class Fetcher {
448
457
  retry: { ...defRetryOptions },
449
458
  init: {
450
459
  method: cfg.method || 'GET',
451
- headers: cfg.headers || {},
460
+ headers: {
461
+ 'user-agent': 'fetcher',
462
+ ...cfg.headers,
463
+ },
452
464
  credentials: cfg.credentials,
453
465
  redirect: cfg.redirect,
454
466
  },
@@ -464,7 +476,7 @@ class Fetcher {
464
476
  'retryPost',
465
477
  'retry4xx',
466
478
  'retry5xx',
467
- 'mode',
479
+ 'responseType',
468
480
  'jsonReviver',
469
481
  'logRequest',
470
482
  'logRequestBody',
@@ -514,9 +526,20 @@ class Fetcher {
514
526
  req.init.body = opt.text;
515
527
  req.init.headers['content-type'] = 'text/plain';
516
528
  }
529
+ else if (opt.form) {
530
+ if (opt.form instanceof URLSearchParams || opt.form instanceof FormData) {
531
+ req.init.body = opt.form;
532
+ }
533
+ else {
534
+ req.init.body = new URLSearchParams(opt.form);
535
+ }
536
+ req.init.headers['content-type'] = 'application/x-www-form-urlencoded';
537
+ }
517
538
  else if (opt.body !== undefined) {
518
539
  req.init.body = opt.body;
519
540
  }
541
+ // Unless `accept` header was already set - set it based on responseType
542
+ req.init.headers['accept'] ||= acceptByResponseType[req.responseType];
520
543
  return req;
521
544
  }
522
545
  }
@@ -1,6 +1,6 @@
1
1
  import type { CommonLogger } from '../log/commonLogger';
2
2
  import type { Promisable } from '../typeFest';
3
- import type { Reviver, UnixTimestampMillisNumber } from '../types';
3
+ import type { AnyObject, Reviver, UnixTimestampMillisNumber } from '../types';
4
4
  import type { HttpMethod, HttpStatusFamily } from './http.model';
5
5
  export interface FetcherNormalizedCfg extends Required<FetcherCfg>, Omit<FetcherRequest, 'started' | 'fullUrl' | 'logRequest' | 'logRequestBody' | 'logResponse' | 'logResponseBody' | 'redirect' | 'credentials'> {
6
6
  logger: CommonLogger;
@@ -88,7 +88,7 @@ export interface FetcherRequest extends Omit<FetcherOptions, 'method' | 'headers
88
88
  */
89
89
  fullUrl: string;
90
90
  init: RequestInitNormalized;
91
- mode: FetcherMode;
91
+ responseType: FetcherResponseType;
92
92
  timeoutSeconds: number;
93
93
  retry: FetcherRetryOptions;
94
94
  retryPost: boolean;
@@ -112,14 +112,29 @@ export interface FetcherOptions {
112
112
  * so both should finish within this single timeout (not each).
113
113
  */
114
114
  timeoutSeconds?: number;
115
- json?: any;
116
- text?: string;
117
115
  /**
118
116
  * Supports all the types that RequestInit.body supports.
119
117
  *
120
118
  * Useful when you want to e.g pass FormData.
121
119
  */
122
120
  body?: Blob | BufferSource | FormData | URLSearchParams | string;
121
+ /**
122
+ * Same as `body`, but also conveniently sets the
123
+ * Content-Type header to `text/plain`
124
+ */
125
+ text?: string;
126
+ /**
127
+ * Same as `body`, but:
128
+ * 1. JSON.stringifies the passed variable
129
+ * 2. Conveniently sets the Content-Type header to `application/json`
130
+ */
131
+ json?: any;
132
+ /**
133
+ * Same as `body`, but:
134
+ * 1. Transforms the passed plain js object into URLSearchParams and passes it to `body`
135
+ * 2. Conveniently sets the Content-Type header to `application/x-www-form-urlencoded`
136
+ */
137
+ form?: FormData | URLSearchParams | AnyObject;
123
138
  credentials?: RequestCredentials;
124
139
  /**
125
140
  * Default to 'follow'.
@@ -128,7 +143,7 @@ export interface FetcherOptions {
128
143
  */
129
144
  redirect?: RequestRedirect;
130
145
  headers?: Record<string, any>;
131
- mode?: FetcherMode;
146
+ responseType?: FetcherResponseType;
132
147
  searchParams?: Record<string, any>;
133
148
  /**
134
149
  * Default is 2 retries (3 tries in total).
@@ -185,4 +200,4 @@ export interface FetcherErrorResponse<BODY = unknown> {
185
200
  signature: string;
186
201
  }
187
202
  export type FetcherResponse<BODY = unknown> = FetcherSuccessResponse<BODY> | FetcherErrorResponse<BODY>;
188
- export type FetcherMode = 'json' | 'text' | 'void' | 'arrayBuffer' | 'blob' | 'readableStream';
203
+ export type FetcherResponseType = 'json' | 'text' | 'void' | 'arrayBuffer' | 'blob' | 'readableStream';
package/dist/index.d.ts CHANGED
@@ -80,6 +80,7 @@ export * from './http/fetcher';
80
80
  export * from './http/fetcher.model';
81
81
  export * from './string/hash.util';
82
82
  export * from './env/buildInfo';
83
+ export * from './form.util';
83
84
  export * from './zod/zod.util';
84
85
  export * from './zod/zod.shared.schemas';
85
86
  import { z, ZodSchema, ZodError, ZodIssue } from 'zod';
package/dist/index.js CHANGED
@@ -84,6 +84,7 @@ tslib_1.__exportStar(require("./http/fetcher"), exports);
84
84
  tslib_1.__exportStar(require("./http/fetcher.model"), exports);
85
85
  tslib_1.__exportStar(require("./string/hash.util"), exports);
86
86
  tslib_1.__exportStar(require("./env/buildInfo"), exports);
87
+ tslib_1.__exportStar(require("./form.util"), exports);
87
88
  tslib_1.__exportStar(require("./zod/zod.util"), exports);
88
89
  tslib_1.__exportStar(require("./zod/zod.shared.schemas"), exports);
89
90
  const zod_1 = require("zod");
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Convert any object to FormData.
3
+ * Please note that every key and value of FormData is `string`.
4
+ * Even if you pass a number - it'll be converted to string.
5
+ * Think URLSearchParams.
6
+ */
7
+ export function objectToFormData(obj = {}) {
8
+ const fd = new FormData();
9
+ Object.entries(obj).forEach(([k, v]) => fd.append(k, v));
10
+ return fd;
11
+ }
12
+ export function formDataToObject(formData) {
13
+ return Object.fromEntries(formData);
14
+ }
@@ -1,4 +1,5 @@
1
1
  /// <reference lib="dom"/>
2
+ /// <reference lib="dom.iterable"/>
2
3
  import { isServerSide } from '../env';
3
4
  import { _anyToError, _anyToErrorObject, _errorLikeToErrorObject } from '../error/error.util';
4
5
  import { HttpRequestError } from '../error/httpRequestError';
@@ -10,6 +11,14 @@ import { _jsonParse, _jsonParseIfPossible } from '../string/json.util';
10
11
  import { _stringifyAny } from '../string/stringifyAny';
11
12
  import { _since } from '../time/time.util';
12
13
  import { HTTP_METHODS } from './http.model';
14
+ const acceptByResponseType = {
15
+ text: 'text/plain',
16
+ json: 'application/json',
17
+ void: '*/*',
18
+ readableStream: 'application/octet-stream',
19
+ arrayBuffer: 'application/octet-stream',
20
+ blob: 'application/octet-stream',
21
+ };
13
22
  const defRetryOptions = {
14
23
  count: 2,
15
24
  timeout: 1000,
@@ -31,18 +40,18 @@ export class Fetcher {
31
40
  const m = method.toLowerCase();
32
41
  this[`${m}Void`] = async (url, opt) => {
33
42
  return await this.fetch(Object.assign({ url,
34
- method, mode: 'void' }, opt));
43
+ method, responseType: 'void' }, opt));
35
44
  };
36
45
  if (method === 'HEAD')
37
- return // mode=text
46
+ return // responseType=text
38
47
  ;
39
48
  this[`${m}Text`] = async (url, opt) => {
40
49
  return await this.fetch(Object.assign({ url,
41
- method, mode: 'text' }, opt));
50
+ method, responseType: 'text' }, opt));
42
51
  };
43
52
  this[m] = async (url, opt) => {
44
53
  return await this.fetch(Object.assign({ url,
45
- method, mode: 'json' }, opt));
54
+ method, responseType: 'json' }, opt));
46
55
  };
47
56
  });
48
57
  }
@@ -70,7 +79,7 @@ export class Fetcher {
70
79
  static create(cfg = {}) {
71
80
  return new Fetcher(cfg);
72
81
  }
73
- // mode=readableStream
82
+ // responseType=readableStream
74
83
  /**
75
84
  * Returns raw fetchResponse.body, which is a ReadableStream<Uint8Array>
76
85
  *
@@ -78,7 +87,7 @@ export class Fetcher {
78
87
  * https://css-tricks.com/web-streams-everywhere-and-fetch-for-node-js/
79
88
  */
80
89
  async getReadableStream(url, opt) {
81
- return await this.fetch(Object.assign({ url, mode: 'readableStream' }, opt));
90
+ return await this.fetch(Object.assign({ url, responseType: 'readableStream' }, opt));
82
91
  }
83
92
  async fetch(opt) {
84
93
  const res = await this.doFetch(opt);
@@ -168,8 +177,8 @@ export class Fetcher {
168
177
  }
169
178
  async onOkResponse(res, timeout) {
170
179
  const { req } = res;
171
- const { mode } = res.req;
172
- if (mode === 'json') {
180
+ const { responseType } = res.req;
181
+ if (responseType === 'json') {
173
182
  if (res.fetchResponse.body) {
174
183
  const text = await res.fetchResponse.text();
175
184
  if (text) {
@@ -203,16 +212,16 @@ export class Fetcher {
203
212
  res.body = {};
204
213
  }
205
214
  }
206
- else if (mode === 'text') {
215
+ else if (responseType === 'text') {
207
216
  res.body = res.fetchResponse.body ? await res.fetchResponse.text() : '';
208
217
  }
209
- else if (mode === 'arrayBuffer') {
218
+ else if (responseType === 'arrayBuffer') {
210
219
  res.body = res.fetchResponse.body ? await res.fetchResponse.arrayBuffer() : {};
211
220
  }
212
- else if (mode === 'blob') {
221
+ else if (responseType === 'blob') {
213
222
  res.body = res.fetchResponse.body ? await res.fetchResponse.blob() : {};
214
223
  }
215
- else if (mode === 'readableStream') {
224
+ else if (responseType === 'readableStream') {
216
225
  res.body = res.fetchResponse.body;
217
226
  if (res.body === null) {
218
227
  res.err = new Error(`fetchResponse.body is null`);
@@ -419,7 +428,7 @@ export class Fetcher {
419
428
  const norm = _merge({
420
429
  baseUrl: '',
421
430
  inputUrl: '',
422
- mode: 'void',
431
+ responseType: 'void',
423
432
  searchParams: {},
424
433
  timeoutSeconds: 30,
425
434
  retryPost: false,
@@ -438,7 +447,7 @@ export class Fetcher {
438
447
  retry: Object.assign({}, defRetryOptions),
439
448
  init: {
440
449
  method: cfg.method || 'GET',
441
- headers: cfg.headers || {},
450
+ headers: Object.assign({ 'user-agent': 'fetcher' }, cfg.headers),
442
451
  credentials: cfg.credentials,
443
452
  redirect: cfg.redirect,
444
453
  },
@@ -448,12 +457,13 @@ export class Fetcher {
448
457
  return norm;
449
458
  }
450
459
  normalizeOptions(opt) {
460
+ var _a;
451
461
  const req = Object.assign(Object.assign(Object.assign(Object.assign({}, _pick(this.cfg, [
452
462
  'timeoutSeconds',
453
463
  'retryPost',
454
464
  'retry4xx',
455
465
  'retry5xx',
456
- 'mode',
466
+ 'responseType',
457
467
  'jsonReviver',
458
468
  'logRequest',
459
469
  'logRequestBody',
@@ -485,9 +495,20 @@ export class Fetcher {
485
495
  req.init.body = opt.text;
486
496
  req.init.headers['content-type'] = 'text/plain';
487
497
  }
498
+ else if (opt.form) {
499
+ if (opt.form instanceof URLSearchParams || opt.form instanceof FormData) {
500
+ req.init.body = opt.form;
501
+ }
502
+ else {
503
+ req.init.body = new URLSearchParams(opt.form);
504
+ }
505
+ req.init.headers['content-type'] = 'application/x-www-form-urlencoded';
506
+ }
488
507
  else if (opt.body !== undefined) {
489
508
  req.init.body = opt.body;
490
509
  }
510
+ // Unless `accept` header was already set - set it based on responseType
511
+ (_a = req.init.headers)['accept'] || (_a['accept'] = acceptByResponseType[req.responseType]);
491
512
  return req;
492
513
  }
493
514
  }
package/dist-esm/index.js CHANGED
@@ -80,6 +80,7 @@ export * from './http/fetcher';
80
80
  export * from './http/fetcher.model';
81
81
  export * from './string/hash.util';
82
82
  export * from './env/buildInfo';
83
+ export * from './form.util';
83
84
  export * from './zod/zod.util';
84
85
  export * from './zod/zod.shared.schemas';
85
86
  import { z, ZodSchema, ZodError } from 'zod';