@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.
- package/dist/datetime/dateInterval.d.ts +3 -3
- package/dist/datetime/localDate.d.ts +18 -18
- package/dist/datetime/localTime.d.ts +21 -21
- package/dist/datetime/timeInterval.d.ts +3 -3
- package/dist/form.util.d.ts +9 -0
- package/dist/form.util.js +19 -0
- package/dist/http/fetcher.d.ts +1 -0
- package/dist/http/fetcher.js +38 -15
- package/dist/http/fetcher.model.d.ts +21 -6
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist-esm/form.util.js +14 -0
- package/dist-esm/http/fetcher.js +36 -15
- package/dist-esm/index.js +1 -0
- package/package.json +1 -2
- package/src/datetime/dateInterval.ts +3 -3
- package/src/datetime/localDate.ts +19 -19
- package/src/datetime/localTime.ts +21 -21
- package/src/datetime/timeInterval.ts +3 -3
- package/src/form.util.ts +17 -0
- package/src/http/fetcher.model.ts +30 -6
- package/src/http/fetcher.ts +46 -21
- package/src/index.ts +1 -0
- package/src/__exclude/lazyLocalDate.ts +0 -73
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Inclusiveness,
|
|
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:
|
|
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:
|
|
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
|
|
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:
|
|
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:
|
|
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:
|
|
34
|
-
static earliest(items:
|
|
35
|
-
static latestOrUndefined(items:
|
|
36
|
-
static latest(items:
|
|
37
|
-
static range(min:
|
|
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:
|
|
47
|
-
isBefore(d:
|
|
48
|
-
isSameOrBefore(d:
|
|
49
|
-
isAfter(d:
|
|
50
|
-
isSameOrAfter(d:
|
|
51
|
-
isBetween(min:
|
|
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:
|
|
57
|
+
cmp(d: LocalDateInput): -1 | 0 | 1;
|
|
58
58
|
/**
|
|
59
59
|
* Same as Math.abs( diff )
|
|
60
60
|
*/
|
|
61
|
-
absDiff(d:
|
|
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:
|
|
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?:
|
|
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
|
|
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:
|
|
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:
|
|
43
|
-
static parseToDate(d:
|
|
44
|
-
static parseToUnixTimestamp(d:
|
|
45
|
-
static isValid(d:
|
|
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:
|
|
76
|
-
diff(other:
|
|
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:
|
|
81
|
-
static earliest(items:
|
|
82
|
-
static latestOrUndefined(items:
|
|
83
|
-
static latest(items:
|
|
84
|
-
isSame(d:
|
|
85
|
-
isBefore(d:
|
|
86
|
-
isSameOrBefore(d:
|
|
87
|
-
isAfter(d:
|
|
88
|
-
isSameOrAfter(d:
|
|
89
|
-
isBetween(min:
|
|
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:
|
|
95
|
+
cmp(d: LocalTimeInput): -1 | 0 | 1;
|
|
96
96
|
components(): LocalTimeComponents;
|
|
97
|
-
fromNow(now?:
|
|
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?:
|
|
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 {
|
|
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:
|
|
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:
|
|
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;
|
package/dist/http/fetcher.d.ts
CHANGED
|
@@ -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.
|
package/dist/http/fetcher.js
CHANGED
|
@@ -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
|
-
|
|
48
|
+
responseType: 'void',
|
|
40
49
|
...opt,
|
|
41
50
|
});
|
|
42
51
|
};
|
|
43
52
|
if (method === 'HEAD')
|
|
44
|
-
return //
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
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 {
|
|
187
|
-
if (
|
|
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 (
|
|
230
|
+
else if (responseType === 'text') {
|
|
222
231
|
res.body = res.fetchResponse.body ? await res.fetchResponse.text() : '';
|
|
223
232
|
}
|
|
224
|
-
else if (
|
|
233
|
+
else if (responseType === 'arrayBuffer') {
|
|
225
234
|
res.body = res.fetchResponse.body ? await res.fetchResponse.arrayBuffer() : {};
|
|
226
235
|
}
|
|
227
|
-
else if (
|
|
236
|
+
else if (responseType === 'blob') {
|
|
228
237
|
res.body = res.fetchResponse.body ? await res.fetchResponse.blob() : {};
|
|
229
238
|
}
|
|
230
|
-
else if (
|
|
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
|
-
|
|
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:
|
|
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
|
-
'
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
+
}
|
package/dist-esm/http/fetcher.js
CHANGED
|
@@ -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,
|
|
43
|
+
method, responseType: 'void' }, opt));
|
|
35
44
|
};
|
|
36
45
|
if (method === 'HEAD')
|
|
37
|
-
return //
|
|
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,
|
|
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,
|
|
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
|
-
//
|
|
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,
|
|
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 {
|
|
172
|
-
if (
|
|
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 (
|
|
215
|
+
else if (responseType === 'text') {
|
|
207
216
|
res.body = res.fetchResponse.body ? await res.fetchResponse.text() : '';
|
|
208
217
|
}
|
|
209
|
-
else if (
|
|
218
|
+
else if (responseType === 'arrayBuffer') {
|
|
210
219
|
res.body = res.fetchResponse.body ? await res.fetchResponse.arrayBuffer() : {};
|
|
211
220
|
}
|
|
212
|
-
else if (
|
|
221
|
+
else if (responseType === 'blob') {
|
|
213
222
|
res.body = res.fetchResponse.body ? await res.fetchResponse.blob() : {};
|
|
214
223
|
}
|
|
215
|
-
else if (
|
|
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
|
-
|
|
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:
|
|
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
|
-
'
|
|
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';
|