@naturalcycles/js-lib 14.126.0 → 14.127.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,152 +1,5 @@
1
1
  /// <reference lib="dom" />
2
- import { CommonLogger } from '../log/commonLogger';
3
- import type { Promisable } from '../typeFest';
4
- import { Reviver } from '../types';
5
- import type { HttpMethod, HttpStatusFamily } from './http.model';
6
- export interface FetcherNormalizedCfg extends Required<FetcherCfg>, FetcherRequest {
7
- logger: CommonLogger;
8
- searchParams: Record<string, any>;
9
- }
10
- export type FetcherBeforeRequestHook = (req: FetcherRequest) => Promisable<void>;
11
- export type FetcherAfterResponseHook = (res: FetcherResponse) => Promisable<void>;
12
- export type FetcherBeforeRetryHook = (res: FetcherResponse) => Promisable<void>;
13
- export interface FetcherCfg {
14
- /**
15
- * Should **not** contain trailing slash.
16
- */
17
- baseUrl?: string;
18
- /**
19
- * Default rule is that you **are allowed** to mutate req, res, res.retryStatus
20
- * properties of hook function arguments.
21
- * If you throw an error from the hook - it will be re-thrown as-is.
22
- */
23
- hooks?: {
24
- /**
25
- * Allows to mutate req.
26
- */
27
- beforeRequest?: FetcherBeforeRequestHook[];
28
- /**
29
- * Allows to mutate res.
30
- * If you set `res.err` - it will be thrown.
31
- */
32
- afterResponse?: FetcherAfterResponseHook[];
33
- /**
34
- * Allows to mutate res.retryStatus to override retry behavior.
35
- */
36
- beforeRetry?: FetcherBeforeRetryHook[];
37
- };
38
- /**
39
- * If true - enables all possible logging.
40
- */
41
- debug?: boolean;
42
- logRequest?: boolean;
43
- logRequestBody?: boolean;
44
- logResponse?: boolean;
45
- logResponseBody?: boolean;
46
- /**
47
- * Default to true.
48
- * Set to false to exclude `prefixUrl` from logs (both success and error)
49
- */
50
- logWithPrefixUrl?: boolean;
51
- /**
52
- * Default to true.
53
- * Set to false to strip searchParams from url when logging (both success and error)
54
- */
55
- logWithSearchParams?: boolean;
56
- /**
57
- * Defaults to `console`.
58
- */
59
- logger?: CommonLogger;
60
- }
61
- export interface FetcherRetryStatus {
62
- retryAttempt: number;
63
- retryTimeout: number;
64
- retryStopped: boolean;
65
- }
66
- export interface FetcherRetryOptions {
67
- count: number;
68
- timeout: number;
69
- timeoutMax: number;
70
- timeoutMultiplier: number;
71
- }
72
- export interface FetcherRequest extends Omit<FetcherOptions, 'method' | 'headers'> {
73
- url: string;
74
- init: RequestInitNormalized;
75
- mode: FetcherMode;
76
- throwHttpErrors: boolean;
77
- timeoutSeconds: number;
78
- retry: FetcherRetryOptions;
79
- retryPost: boolean;
80
- retry4xx: boolean;
81
- retry5xx: boolean;
82
- }
83
- export interface FetcherOptions {
84
- method?: HttpMethod;
85
- throwHttpErrors?: boolean;
86
- /**
87
- * Default: 30.
88
- *
89
- * Timeout applies to both get the response and retrieve the body (e.g `await res.json()`),
90
- * so both should finish within this single timeout (not each).
91
- */
92
- timeoutSeconds?: number;
93
- json?: any;
94
- text?: string;
95
- /**
96
- * Supports all the types that RequestInit.body supports.
97
- *
98
- * Useful when you want to e.g pass FormData.
99
- */
100
- body?: Blob | BufferSource | FormData | URLSearchParams | string;
101
- credentials?: RequestCredentials;
102
- /**
103
- * Default to true.
104
- */
105
- followRedirects?: boolean;
106
- headers?: Record<string, any>;
107
- mode?: FetcherMode;
108
- searchParams?: Record<string, any>;
109
- /**
110
- * Default is 2 retries (3 tries in total).
111
- * Pass `retry: { count: 0 }` to disable retries.
112
- */
113
- retry?: Partial<FetcherRetryOptions>;
114
- /**
115
- * Defaults to false.
116
- * Set to true to allow retrying `post` requests.
117
- */
118
- retryPost?: boolean;
119
- /**
120
- * Defaults to false.
121
- */
122
- retry4xx?: boolean;
123
- /**
124
- * Defaults to true.
125
- */
126
- retry5xx?: boolean;
127
- jsonReviver?: Reviver;
128
- }
129
- export type RequestInitNormalized = Omit<RequestInit, 'method' | 'headers'> & {
130
- method: HttpMethod;
131
- headers: Record<string, any>;
132
- };
133
- export interface FetcherSuccessResponse<BODY = unknown> extends FetcherResponse<BODY> {
134
- err?: undefined;
135
- fetchResponse: Response;
136
- body: BODY;
137
- }
138
- export interface FetcherErrorResponse<BODY = unknown> extends FetcherResponse<BODY> {
139
- err: Error;
140
- }
141
- export interface FetcherResponse<BODY = unknown> {
142
- err?: Error;
143
- req: FetcherRequest;
144
- fetchResponse?: Response;
145
- statusFamily?: HttpStatusFamily;
146
- body?: BODY;
147
- retryStatus: FetcherRetryStatus;
148
- }
149
- export type FetcherMode = 'json' | 'text' | 'void';
2
+ import type { FetcherAfterResponseHook, FetcherBeforeRequestHook, FetcherBeforeRetryHook, FetcherCfg, FetcherNormalizedCfg, FetcherOptions, FetcherResponse } from './fetcher.model';
150
3
  /**
151
4
  * Experimental wrapper around Fetch.
152
5
  * Works in both Browser and Node, using `globalThis.fetch`.
@@ -133,10 +133,12 @@ class Fetcher {
133
133
  }
134
134
  try {
135
135
  res.fetchResponse = await globalThis.fetch(req.url, req.init);
136
+ res.ok = res.fetchResponse.ok;
136
137
  }
137
138
  catch (err) {
138
139
  // For example, CORS error would result in "TypeError: failed to fetch" here
139
140
  res.err = err;
141
+ res.ok = false;
140
142
  }
141
143
  res.statusFamily = this.getStatusFamily(res);
142
144
  if (res.fetchResponse?.ok) {
@@ -148,6 +150,7 @@ class Fetcher {
148
150
  res.body = JSON.parse(text, req.jsonReviver);
149
151
  }
150
152
  catch (err) {
153
+ res.ok = false;
151
154
  res.err = (0, error_util_1._anyToError)(err, http_error_1.HttpError, (0, object_util_1._filterNullishValues)({
152
155
  httpStatusCode: 0,
153
156
  url: req.url,
@@ -0,0 +1,151 @@
1
+ import type { CommonLogger } from '../log/commonLogger';
2
+ import type { Promisable } from '../typeFest';
3
+ import type { Reviver } from '../types';
4
+ import type { HttpMethod, HttpStatusFamily } from './http.model';
5
+ export interface FetcherNormalizedCfg extends Required<FetcherCfg>, FetcherRequest {
6
+ logger: CommonLogger;
7
+ searchParams: Record<string, any>;
8
+ }
9
+ export type FetcherBeforeRequestHook = (req: FetcherRequest) => Promisable<void>;
10
+ export type FetcherAfterResponseHook = (res: FetcherResponse) => Promisable<void>;
11
+ export type FetcherBeforeRetryHook = (res: FetcherResponse) => Promisable<void>;
12
+ export interface FetcherCfg {
13
+ /**
14
+ * Should **not** contain trailing slash.
15
+ */
16
+ baseUrl?: string;
17
+ /**
18
+ * Default rule is that you **are allowed** to mutate req, res, res.retryStatus
19
+ * properties of hook function arguments.
20
+ * If you throw an error from the hook - it will be re-thrown as-is.
21
+ */
22
+ hooks?: {
23
+ /**
24
+ * Allows to mutate req.
25
+ */
26
+ beforeRequest?: FetcherBeforeRequestHook[];
27
+ /**
28
+ * Allows to mutate res.
29
+ * If you set `res.err` - it will be thrown.
30
+ */
31
+ afterResponse?: FetcherAfterResponseHook[];
32
+ /**
33
+ * Allows to mutate res.retryStatus to override retry behavior.
34
+ */
35
+ beforeRetry?: FetcherBeforeRetryHook[];
36
+ };
37
+ /**
38
+ * If true - enables all possible logging.
39
+ */
40
+ debug?: boolean;
41
+ logRequest?: boolean;
42
+ logRequestBody?: boolean;
43
+ logResponse?: boolean;
44
+ logResponseBody?: boolean;
45
+ /**
46
+ * Default to true.
47
+ * Set to false to exclude `prefixUrl` from logs (both success and error)
48
+ */
49
+ logWithPrefixUrl?: boolean;
50
+ /**
51
+ * Default to true.
52
+ * Set to false to strip searchParams from url when logging (both success and error)
53
+ */
54
+ logWithSearchParams?: boolean;
55
+ /**
56
+ * Defaults to `console`.
57
+ */
58
+ logger?: CommonLogger;
59
+ }
60
+ export interface FetcherRetryStatus {
61
+ retryAttempt: number;
62
+ retryTimeout: number;
63
+ retryStopped: boolean;
64
+ }
65
+ export interface FetcherRetryOptions {
66
+ count: number;
67
+ timeout: number;
68
+ timeoutMax: number;
69
+ timeoutMultiplier: number;
70
+ }
71
+ export interface FetcherRequest extends Omit<FetcherOptions, 'method' | 'headers'> {
72
+ url: string;
73
+ init: RequestInitNormalized;
74
+ mode: FetcherMode;
75
+ throwHttpErrors: boolean;
76
+ timeoutSeconds: number;
77
+ retry: FetcherRetryOptions;
78
+ retryPost: boolean;
79
+ retry4xx: boolean;
80
+ retry5xx: boolean;
81
+ }
82
+ export interface FetcherOptions {
83
+ method?: HttpMethod;
84
+ throwHttpErrors?: boolean;
85
+ /**
86
+ * Default: 30.
87
+ *
88
+ * Timeout applies to both get the response and retrieve the body (e.g `await res.json()`),
89
+ * so both should finish within this single timeout (not each).
90
+ */
91
+ timeoutSeconds?: number;
92
+ json?: any;
93
+ text?: string;
94
+ /**
95
+ * Supports all the types that RequestInit.body supports.
96
+ *
97
+ * Useful when you want to e.g pass FormData.
98
+ */
99
+ body?: Blob | BufferSource | FormData | URLSearchParams | string;
100
+ credentials?: RequestCredentials;
101
+ /**
102
+ * Default to true.
103
+ */
104
+ followRedirects?: boolean;
105
+ headers?: Record<string, any>;
106
+ mode?: FetcherMode;
107
+ searchParams?: Record<string, any>;
108
+ /**
109
+ * Default is 2 retries (3 tries in total).
110
+ * Pass `retry: { count: 0 }` to disable retries.
111
+ */
112
+ retry?: Partial<FetcherRetryOptions>;
113
+ /**
114
+ * Defaults to false.
115
+ * Set to true to allow retrying `post` requests.
116
+ */
117
+ retryPost?: boolean;
118
+ /**
119
+ * Defaults to false.
120
+ */
121
+ retry4xx?: boolean;
122
+ /**
123
+ * Defaults to true.
124
+ */
125
+ retry5xx?: boolean;
126
+ jsonReviver?: Reviver;
127
+ }
128
+ export type RequestInitNormalized = Omit<RequestInit, 'method' | 'headers'> & {
129
+ method: HttpMethod;
130
+ headers: Record<string, any>;
131
+ };
132
+ export interface FetcherSuccessResponse<BODY = unknown> {
133
+ ok: true;
134
+ err: undefined;
135
+ fetchResponse: Response;
136
+ body: BODY;
137
+ req: FetcherRequest;
138
+ statusFamily?: HttpStatusFamily;
139
+ retryStatus: FetcherRetryStatus;
140
+ }
141
+ export interface FetcherErrorResponse<BODY = unknown> {
142
+ ok: false;
143
+ err: Error;
144
+ fetchResponse?: Response;
145
+ body?: BODY;
146
+ req: FetcherRequest;
147
+ statusFamily?: HttpStatusFamily;
148
+ retryStatus: FetcherRetryStatus;
149
+ }
150
+ export type FetcherResponse<BODY = unknown> = FetcherSuccessResponse<BODY> | FetcherErrorResponse<BODY>;
151
+ export type FetcherMode = 'json' | 'text' | 'void';
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/dist/index.d.ts CHANGED
@@ -76,4 +76,5 @@ export * from './datetime/dateInterval';
76
76
  export * from './datetime/timeInterval';
77
77
  export * from './http/http.model';
78
78
  export * from './http/fetcher';
79
+ export * from './http/fetcher.model';
79
80
  export { is };
package/dist/index.js CHANGED
@@ -81,3 +81,4 @@ tslib_1.__exportStar(require("./datetime/dateInterval"), exports);
81
81
  tslib_1.__exportStar(require("./datetime/timeInterval"), exports);
82
82
  tslib_1.__exportStar(require("./http/http.model"), exports);
83
83
  tslib_1.__exportStar(require("./http/fetcher"), exports);
84
+ tslib_1.__exportStar(require("./http/fetcher.model"), exports);
@@ -141,10 +141,12 @@ export class Fetcher {
141
141
  }
142
142
  try {
143
143
  res.fetchResponse = await globalThis.fetch(req.url, req.init);
144
+ res.ok = res.fetchResponse.ok;
144
145
  }
145
146
  catch (err) {
146
147
  // For example, CORS error would result in "TypeError: failed to fetch" here
147
148
  res.err = err;
149
+ res.ok = false;
148
150
  }
149
151
  res.statusFamily = this.getStatusFamily(res);
150
152
  if ((_g = res.fetchResponse) === null || _g === void 0 ? void 0 : _g.ok) {
@@ -156,6 +158,7 @@ export class Fetcher {
156
158
  res.body = JSON.parse(text, req.jsonReviver);
157
159
  }
158
160
  catch (err) {
161
+ res.ok = false;
159
162
  res.err = _anyToError(err, HttpError, _filterNullishValues({
160
163
  httpStatusCode: 0,
161
164
  url: req.url,
@@ -0,0 +1 @@
1
+ export {};
package/dist-esm/index.js CHANGED
@@ -76,4 +76,5 @@ export * from './datetime/dateInterval';
76
76
  export * from './datetime/timeInterval';
77
77
  export * from './http/http.model';
78
78
  export * from './http/fetcher';
79
+ export * from './http/fetcher.model';
79
80
  export { is };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/js-lib",
3
- "version": "14.126.0",
3
+ "version": "14.127.0",
4
4
  "scripts": {
5
5
  "prepare": "husky install",
6
6
  "build-prod": "build-prod-esm-cjs",
@@ -0,0 +1,181 @@
1
+ import type { CommonLogger } from '../log/commonLogger'
2
+ import type { Promisable } from '../typeFest'
3
+ import type { Reviver } from '../types'
4
+ import type { HttpMethod, HttpStatusFamily } from './http.model'
5
+
6
+ export interface FetcherNormalizedCfg extends Required<FetcherCfg>, FetcherRequest {
7
+ logger: CommonLogger
8
+ searchParams: Record<string, any>
9
+ }
10
+
11
+ export type FetcherBeforeRequestHook = (req: FetcherRequest) => Promisable<void>
12
+ export type FetcherAfterResponseHook = (res: FetcherResponse) => Promisable<void>
13
+ export type FetcherBeforeRetryHook = (res: FetcherResponse) => Promisable<void>
14
+
15
+ export interface FetcherCfg {
16
+ /**
17
+ * Should **not** contain trailing slash.
18
+ */
19
+ baseUrl?: string
20
+
21
+ /**
22
+ * Default rule is that you **are allowed** to mutate req, res, res.retryStatus
23
+ * properties of hook function arguments.
24
+ * If you throw an error from the hook - it will be re-thrown as-is.
25
+ */
26
+ hooks?: {
27
+ /**
28
+ * Allows to mutate req.
29
+ */
30
+ beforeRequest?: FetcherBeforeRequestHook[]
31
+ /**
32
+ * Allows to mutate res.
33
+ * If you set `res.err` - it will be thrown.
34
+ */
35
+ afterResponse?: FetcherAfterResponseHook[]
36
+ /**
37
+ * Allows to mutate res.retryStatus to override retry behavior.
38
+ */
39
+ beforeRetry?: FetcherBeforeRetryHook[]
40
+ }
41
+
42
+ /**
43
+ * If true - enables all possible logging.
44
+ */
45
+ debug?: boolean
46
+ logRequest?: boolean
47
+ logRequestBody?: boolean
48
+ logResponse?: boolean
49
+ logResponseBody?: boolean
50
+
51
+ /**
52
+ * Default to true.
53
+ * Set to false to exclude `prefixUrl` from logs (both success and error)
54
+ */
55
+ logWithPrefixUrl?: boolean
56
+
57
+ /**
58
+ * Default to true.
59
+ * Set to false to strip searchParams from url when logging (both success and error)
60
+ */
61
+ logWithSearchParams?: boolean
62
+
63
+ /**
64
+ * Defaults to `console`.
65
+ */
66
+ logger?: CommonLogger
67
+ }
68
+
69
+ export interface FetcherRetryStatus {
70
+ retryAttempt: number
71
+ retryTimeout: number
72
+ retryStopped: boolean
73
+ }
74
+
75
+ export interface FetcherRetryOptions {
76
+ count: number
77
+ timeout: number
78
+ timeoutMax: number
79
+ timeoutMultiplier: number
80
+ }
81
+
82
+ export interface FetcherRequest extends Omit<FetcherOptions, 'method' | 'headers'> {
83
+ url: string
84
+ init: RequestInitNormalized
85
+ mode: FetcherMode
86
+ throwHttpErrors: boolean
87
+ timeoutSeconds: number
88
+ retry: FetcherRetryOptions
89
+ retryPost: boolean
90
+ retry4xx: boolean
91
+ retry5xx: boolean
92
+ }
93
+
94
+ export interface FetcherOptions {
95
+ method?: HttpMethod
96
+ throwHttpErrors?: boolean
97
+ /**
98
+ * Default: 30.
99
+ *
100
+ * Timeout applies to both get the response and retrieve the body (e.g `await res.json()`),
101
+ * so both should finish within this single timeout (not each).
102
+ */
103
+ timeoutSeconds?: number
104
+
105
+ json?: any
106
+ text?: string
107
+ /**
108
+ * Supports all the types that RequestInit.body supports.
109
+ *
110
+ * Useful when you want to e.g pass FormData.
111
+ */
112
+ body?: Blob | BufferSource | FormData | URLSearchParams | string
113
+
114
+ credentials?: RequestCredentials
115
+ /**
116
+ * Default to true.
117
+ */
118
+ followRedirects?: boolean
119
+
120
+ // Removing RequestInit from options to simplify FetcherOptions interface.
121
+ // Will instead only add hand-picked useful options, such as `credentials`.
122
+ // init?: Partial<RequestInitNormalized>
123
+
124
+ headers?: Record<string, any>
125
+ mode?: FetcherMode // default to 'void'
126
+
127
+ searchParams?: Record<string, any>
128
+
129
+ /**
130
+ * Default is 2 retries (3 tries in total).
131
+ * Pass `retry: { count: 0 }` to disable retries.
132
+ */
133
+ retry?: Partial<FetcherRetryOptions>
134
+
135
+ /**
136
+ * Defaults to false.
137
+ * Set to true to allow retrying `post` requests.
138
+ */
139
+ retryPost?: boolean
140
+ /**
141
+ * Defaults to false.
142
+ */
143
+ retry4xx?: boolean
144
+ /**
145
+ * Defaults to true.
146
+ */
147
+ retry5xx?: boolean
148
+
149
+ jsonReviver?: Reviver
150
+ }
151
+
152
+ export type RequestInitNormalized = Omit<RequestInit, 'method' | 'headers'> & {
153
+ method: HttpMethod
154
+ headers: Record<string, any>
155
+ }
156
+
157
+ export interface FetcherSuccessResponse<BODY = unknown> {
158
+ ok: true
159
+ err: undefined
160
+ fetchResponse: Response
161
+ body: BODY
162
+ req: FetcherRequest
163
+ statusFamily?: HttpStatusFamily
164
+ retryStatus: FetcherRetryStatus
165
+ }
166
+
167
+ export interface FetcherErrorResponse<BODY = unknown> {
168
+ ok: false
169
+ err: Error
170
+ fetchResponse?: Response
171
+ body?: BODY
172
+ req: FetcherRequest
173
+ statusFamily?: HttpStatusFamily
174
+ retryStatus: FetcherRetryStatus
175
+ }
176
+
177
+ export type FetcherResponse<BODY = unknown> =
178
+ | FetcherSuccessResponse<BODY>
179
+ | FetcherErrorResponse<BODY>
180
+
181
+ export type FetcherMode = 'json' | 'text' | 'void'
@@ -3,7 +3,6 @@
3
3
  import { ErrorObject } from '../error/error.model'
4
4
  import { _anyToError, _anyToErrorObject, _errorToErrorObject } from '../error/error.util'
5
5
  import { HttpError } from '../error/http.error'
6
- import { CommonLogger } from '../log/commonLogger'
7
6
  import { _clamp } from '../number/number.util'
8
7
  import {
9
8
  _filterNullishValues,
@@ -15,182 +14,19 @@ import {
15
14
  import { pDelay } from '../promise/pDelay'
16
15
  import { _jsonParseIfPossible } from '../string/json.util'
17
16
  import { _since } from '../time/time.util'
18
- import type { Promisable } from '../typeFest'
19
- import { Reviver } from '../types'
17
+ import type {
18
+ FetcherAfterResponseHook,
19
+ FetcherBeforeRequestHook,
20
+ FetcherBeforeRetryHook,
21
+ FetcherCfg,
22
+ FetcherNormalizedCfg,
23
+ FetcherOptions,
24
+ FetcherRequest,
25
+ FetcherResponse,
26
+ FetcherRetryOptions,
27
+ } from './fetcher.model'
20
28
  import { HTTP_METHODS } from './http.model'
21
- import type { HttpMethod, HttpStatusFamily } from './http.model'
22
-
23
- export interface FetcherNormalizedCfg extends Required<FetcherCfg>, FetcherRequest {
24
- logger: CommonLogger
25
- searchParams: Record<string, any>
26
- }
27
-
28
- export type FetcherBeforeRequestHook = (req: FetcherRequest) => Promisable<void>
29
- export type FetcherAfterResponseHook = (res: FetcherResponse) => Promisable<void>
30
- export type FetcherBeforeRetryHook = (res: FetcherResponse) => Promisable<void>
31
-
32
- export interface FetcherCfg {
33
- /**
34
- * Should **not** contain trailing slash.
35
- */
36
- baseUrl?: string
37
-
38
- /**
39
- * Default rule is that you **are allowed** to mutate req, res, res.retryStatus
40
- * properties of hook function arguments.
41
- * If you throw an error from the hook - it will be re-thrown as-is.
42
- */
43
- hooks?: {
44
- /**
45
- * Allows to mutate req.
46
- */
47
- beforeRequest?: FetcherBeforeRequestHook[]
48
- /**
49
- * Allows to mutate res.
50
- * If you set `res.err` - it will be thrown.
51
- */
52
- afterResponse?: FetcherAfterResponseHook[]
53
- /**
54
- * Allows to mutate res.retryStatus to override retry behavior.
55
- */
56
- beforeRetry?: FetcherBeforeRetryHook[]
57
- }
58
-
59
- /**
60
- * If true - enables all possible logging.
61
- */
62
- debug?: boolean
63
- logRequest?: boolean
64
- logRequestBody?: boolean
65
- logResponse?: boolean
66
- logResponseBody?: boolean
67
-
68
- /**
69
- * Default to true.
70
- * Set to false to exclude `prefixUrl` from logs (both success and error)
71
- */
72
- logWithPrefixUrl?: boolean
73
-
74
- /**
75
- * Default to true.
76
- * Set to false to strip searchParams from url when logging (both success and error)
77
- */
78
- logWithSearchParams?: boolean
79
-
80
- /**
81
- * Defaults to `console`.
82
- */
83
- logger?: CommonLogger
84
- }
85
-
86
- export interface FetcherRetryStatus {
87
- retryAttempt: number
88
- retryTimeout: number
89
- retryStopped: boolean
90
- }
91
-
92
- export interface FetcherRetryOptions {
93
- count: number
94
- timeout: number
95
- timeoutMax: number
96
- timeoutMultiplier: number
97
- }
98
-
99
- export interface FetcherRequest extends Omit<FetcherOptions, 'method' | 'headers'> {
100
- url: string
101
- init: RequestInitNormalized
102
- mode: FetcherMode
103
- throwHttpErrors: boolean
104
- timeoutSeconds: number
105
- retry: FetcherRetryOptions
106
- retryPost: boolean
107
- retry4xx: boolean
108
- retry5xx: boolean
109
- }
110
-
111
- export interface FetcherOptions {
112
- method?: HttpMethod
113
- throwHttpErrors?: boolean
114
- /**
115
- * Default: 30.
116
- *
117
- * Timeout applies to both get the response and retrieve the body (e.g `await res.json()`),
118
- * so both should finish within this single timeout (not each).
119
- */
120
- timeoutSeconds?: number
121
-
122
- json?: any
123
- text?: string
124
- /**
125
- * Supports all the types that RequestInit.body supports.
126
- *
127
- * Useful when you want to e.g pass FormData.
128
- */
129
- body?: Blob | BufferSource | FormData | URLSearchParams | string
130
-
131
- credentials?: RequestCredentials
132
- /**
133
- * Default to true.
134
- */
135
- followRedirects?: boolean
136
-
137
- // Removing RequestInit from options to simplify FetcherOptions interface.
138
- // Will instead only add hand-picked useful options, such as `credentials`.
139
- // init?: Partial<RequestInitNormalized>
140
-
141
- headers?: Record<string, any>
142
- mode?: FetcherMode // default to 'void'
143
-
144
- searchParams?: Record<string, any>
145
-
146
- /**
147
- * Default is 2 retries (3 tries in total).
148
- * Pass `retry: { count: 0 }` to disable retries.
149
- */
150
- retry?: Partial<FetcherRetryOptions>
151
-
152
- /**
153
- * Defaults to false.
154
- * Set to true to allow retrying `post` requests.
155
- */
156
- retryPost?: boolean
157
- /**
158
- * Defaults to false.
159
- */
160
- retry4xx?: boolean
161
- /**
162
- * Defaults to true.
163
- */
164
- retry5xx?: boolean
165
-
166
- jsonReviver?: Reviver
167
- }
168
-
169
- export type RequestInitNormalized = Omit<RequestInit, 'method' | 'headers'> & {
170
- method: HttpMethod
171
- headers: Record<string, any>
172
- }
173
-
174
- export interface FetcherSuccessResponse<BODY = unknown> extends FetcherResponse<BODY> {
175
- err?: undefined
176
- fetchResponse: Response
177
- body: BODY
178
- }
179
-
180
- export interface FetcherErrorResponse<BODY = unknown> extends FetcherResponse<BODY> {
181
- err: Error
182
- }
183
-
184
- export interface FetcherResponse<BODY = unknown> {
185
- err?: Error
186
- req: FetcherRequest
187
- fetchResponse?: Response
188
- statusFamily?: HttpStatusFamily
189
- body?: BODY
190
- retryStatus: FetcherRetryStatus
191
- }
192
-
193
- export type FetcherMode = 'json' | 'text' | 'void'
29
+ import type { HttpStatusFamily } from './http.model'
194
30
 
195
31
  const defRetryOptions: FetcherRetryOptions = {
196
32
  count: 2,
@@ -300,7 +136,7 @@ export class Fetcher {
300
136
  if (res.req.throwHttpErrors) throw res.err
301
137
  return res as any
302
138
  }
303
- return res.body!
139
+ return res.body
304
140
  }
305
141
 
306
142
  /**
@@ -334,14 +170,14 @@ export class Fetcher {
334
170
  await hook(req)
335
171
  }
336
172
 
337
- const res: FetcherResponse<any> = {
173
+ const res = {
338
174
  req,
339
175
  retryStatus: {
340
176
  retryAttempt: 0,
341
177
  retryStopped: false,
342
178
  retryTimeout: req.retry.timeout,
343
179
  },
344
- }
180
+ } as FetcherResponse<any>
345
181
 
346
182
  const fullUrl = new URL(req.url)
347
183
  const shortUrl = this.getShortUrl(fullUrl)
@@ -365,9 +201,11 @@ export class Fetcher {
365
201
 
366
202
  try {
367
203
  res.fetchResponse = await globalThis.fetch(req.url, req.init)
204
+ res.ok = res.fetchResponse.ok
368
205
  } catch (err) {
369
206
  // For example, CORS error would result in "TypeError: failed to fetch" here
370
207
  res.err = err as Error
208
+ res.ok = false
371
209
  }
372
210
  res.statusFamily = this.getStatusFamily(res)
373
211
 
@@ -380,6 +218,7 @@ export class Fetcher {
380
218
  try {
381
219
  res.body = JSON.parse(text, req.jsonReviver)
382
220
  } catch (err) {
221
+ res.ok = false
383
222
  res.err = _anyToError(
384
223
  err,
385
224
  HttpError,
package/src/index.ts CHANGED
@@ -76,5 +76,6 @@ export * from './datetime/dateInterval'
76
76
  export * from './datetime/timeInterval'
77
77
  export * from './http/http.model'
78
78
  export * from './http/fetcher'
79
+ export * from './http/fetcher.model'
79
80
 
80
81
  export { is }