floppy-disk 2.9.0 → 2.10.0-beta.2
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/esm/index.d.ts +1 -0
- package/esm/index.js +1 -0
- package/esm/react/create-query.js +31 -22
- package/esm/utils/fetcher.d.ts +25 -0
- package/esm/utils/fetcher.js +74 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/react/create-query.js +31 -22
- package/lib/utils/fetcher.d.ts +25 -0
- package/lib/utils/fetcher.js +78 -0
- package/package.json +1 -1
package/esm/index.d.ts
CHANGED
package/esm/index.js
CHANGED
|
@@ -67,7 +67,7 @@ export const createQuery = (queryFn, options = {}) => {
|
|
|
67
67
|
set({ isWaiting: true });
|
|
68
68
|
else
|
|
69
69
|
set({ isWaiting: true, isRefetching: true });
|
|
70
|
-
const callQuery = () => {
|
|
70
|
+
const callQuery = (innerResolve = resolve) => {
|
|
71
71
|
if (get().isGoingToRetry) {
|
|
72
72
|
if (isLoading)
|
|
73
73
|
set({ isGoingToRetry: false, isWaiting: true });
|
|
@@ -81,7 +81,7 @@ export const createQuery = (queryFn, options = {}) => {
|
|
|
81
81
|
.then((response) => {
|
|
82
82
|
if (preventReplaceResponse.get(keyHash)) {
|
|
83
83
|
set({ isWaiting: false, isRefetching: false });
|
|
84
|
-
return
|
|
84
|
+
return innerResolve(get());
|
|
85
85
|
}
|
|
86
86
|
responseAllPages.push(response);
|
|
87
87
|
const newPageParam = getNextPageParam(response, responseAllPages.length, stateBeforeCallQuery);
|
|
@@ -121,11 +121,26 @@ export const createQuery = (queryFn, options = {}) => {
|
|
|
121
121
|
}
|
|
122
122
|
set(nextState);
|
|
123
123
|
onSuccess(response, stateBeforeCallQuery);
|
|
124
|
+
onSettled(stateBeforeCallQuery);
|
|
125
|
+
innerResolve(get());
|
|
124
126
|
})
|
|
125
127
|
.catch((error) => {
|
|
126
128
|
const prevState = get();
|
|
127
129
|
const errorUpdatedAt = Date.now();
|
|
128
130
|
const { shouldRetry, delay } = getRetryProps(error, prevState.retryCount);
|
|
131
|
+
if (shouldRetry) {
|
|
132
|
+
set({
|
|
133
|
+
isWaiting: false,
|
|
134
|
+
isGoingToRetry: true,
|
|
135
|
+
});
|
|
136
|
+
if (isClient) {
|
|
137
|
+
retryTimeoutId.set(keyHash, window.setTimeout(() => {
|
|
138
|
+
set({ retryCount: prevState.retryCount + 1 });
|
|
139
|
+
callQuery(innerResolve);
|
|
140
|
+
}, delay));
|
|
141
|
+
}
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
129
144
|
set(prevState.isSuccess && !prevState.isPreviousData
|
|
130
145
|
? {
|
|
131
146
|
isWaiting: false,
|
|
@@ -138,7 +153,6 @@ export const createQuery = (queryFn, options = {}) => {
|
|
|
138
153
|
: prevState.data,
|
|
139
154
|
error,
|
|
140
155
|
errorUpdatedAt,
|
|
141
|
-
isGoingToRetry: shouldRetry,
|
|
142
156
|
pageParam,
|
|
143
157
|
hasNextPage: hasValue(pageParam),
|
|
144
158
|
}
|
|
@@ -150,21 +164,12 @@ export const createQuery = (queryFn, options = {}) => {
|
|
|
150
164
|
data: undefined,
|
|
151
165
|
error,
|
|
152
166
|
errorUpdatedAt,
|
|
153
|
-
isGoingToRetry: shouldRetry,
|
|
154
167
|
pageParam,
|
|
155
168
|
hasNextPage: hasValue(pageParam),
|
|
156
169
|
});
|
|
157
|
-
if (shouldRetry && isClient) {
|
|
158
|
-
retryTimeoutId.set(keyHash, window.setTimeout(() => {
|
|
159
|
-
set({ retryCount: prevState.retryCount + 1 });
|
|
160
|
-
callQuery();
|
|
161
|
-
}, delay));
|
|
162
|
-
}
|
|
163
170
|
onError(error, stateBeforeCallQuery);
|
|
164
|
-
})
|
|
165
|
-
.finally(() => {
|
|
166
171
|
onSettled(stateBeforeCallQuery);
|
|
167
|
-
|
|
172
|
+
innerResolve(get());
|
|
168
173
|
});
|
|
169
174
|
};
|
|
170
175
|
callQuery();
|
|
@@ -207,26 +212,30 @@ export const createQuery = (queryFn, options = {}) => {
|
|
|
207
212
|
hasNextPage: hasValue(newPageParam),
|
|
208
213
|
});
|
|
209
214
|
onSuccess(response, stateBeforeCallQuery);
|
|
215
|
+
onSettled(stateBeforeCallQuery);
|
|
216
|
+
resolve(get());
|
|
210
217
|
})
|
|
211
218
|
.catch((error) => {
|
|
212
219
|
const prevState = get();
|
|
213
220
|
const { shouldRetry, delay } = getRetryProps(error, prevState.retryNextPageCount);
|
|
221
|
+
if (shouldRetry) {
|
|
222
|
+
set({
|
|
223
|
+
isWaitingNextPage: false,
|
|
224
|
+
isGoingToRetryNextPage: true,
|
|
225
|
+
});
|
|
226
|
+
retryNextPageTimeoutId.set(keyHash, window.setTimeout(() => {
|
|
227
|
+
set({ retryNextPageCount: prevState.retryNextPageCount + 1 });
|
|
228
|
+
resolve(fetchNextPage());
|
|
229
|
+
}, delay));
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
214
232
|
set({
|
|
215
233
|
isWaitingNextPage: false,
|
|
216
234
|
isError: true,
|
|
217
235
|
error,
|
|
218
236
|
errorUpdatedAt: Date.now(),
|
|
219
|
-
isGoingToRetryNextPage: shouldRetry,
|
|
220
237
|
});
|
|
221
|
-
if (shouldRetry) {
|
|
222
|
-
retryNextPageTimeoutId.set(keyHash, window.setTimeout(() => {
|
|
223
|
-
set({ retryNextPageCount: prevState.retryNextPageCount + 1 });
|
|
224
|
-
fetchNextPage();
|
|
225
|
-
}, delay));
|
|
226
|
-
}
|
|
227
238
|
onError(error, stateBeforeCallQuery);
|
|
228
|
-
})
|
|
229
|
-
.finally(() => {
|
|
230
239
|
onSettled(stateBeforeCallQuery);
|
|
231
240
|
resolve(get());
|
|
232
241
|
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
type FetcherOptions<TResponse = any> = {
|
|
2
|
+
url: string;
|
|
3
|
+
query?: string;
|
|
4
|
+
params?: Record<string, string | number | boolean> | null;
|
|
5
|
+
payload?: any;
|
|
6
|
+
interceptRequest?: (requestOptions: RequestInit & {
|
|
7
|
+
url: string;
|
|
8
|
+
}) => (RequestInit & {
|
|
9
|
+
url: string;
|
|
10
|
+
}) | Promise<RequestInit & {
|
|
11
|
+
url: string;
|
|
12
|
+
}>;
|
|
13
|
+
interceptResponse?: (response: TResponse) => TResponse | Promise<TResponse>;
|
|
14
|
+
} & RequestInit;
|
|
15
|
+
/**
|
|
16
|
+
* Experimental fetcher - abstraction layer for query/mutation function creator.
|
|
17
|
+
*
|
|
18
|
+
* Can be used for REST or GraphQL.
|
|
19
|
+
*
|
|
20
|
+
* @see https://floppy-disk.vercel.app/docs/experimental
|
|
21
|
+
*
|
|
22
|
+
* @returns A function to fetch data
|
|
23
|
+
*/
|
|
24
|
+
export declare const fetcher: <TResponse = any, TInput extends any[] = any[]>(options: FetcherOptions<TResponse> | ((...args: TInput) => FetcherOptions<TResponse>)) => (...args: TInput) => Promise<TResponse>;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/* eslint-disable no-throw-literal */
|
|
2
|
+
import { getValueOrComputedValue, identityFn } from '.';
|
|
3
|
+
const encodeParams = (params) => Object.entries(params)
|
|
4
|
+
.map((kv) => kv.map(encodeURIComponent).join('='))
|
|
5
|
+
.join('&');
|
|
6
|
+
/**
|
|
7
|
+
* Experimental fetcher - abstraction layer for query/mutation function creator.
|
|
8
|
+
*
|
|
9
|
+
* Can be used for REST or GraphQL.
|
|
10
|
+
*
|
|
11
|
+
* @see https://floppy-disk.vercel.app/docs/experimental
|
|
12
|
+
*
|
|
13
|
+
* @returns A function to fetch data
|
|
14
|
+
*/
|
|
15
|
+
export const fetcher = (options) => async (...args) => {
|
|
16
|
+
const { url, query, params, payload, headers, interceptRequest = identityFn, interceptResponse, ...rest } = getValueOrComputedValue(options, ...args);
|
|
17
|
+
let autoOptions = {};
|
|
18
|
+
let searchParams = params;
|
|
19
|
+
if (query) {
|
|
20
|
+
// GraphQL
|
|
21
|
+
autoOptions = {
|
|
22
|
+
method: 'POST',
|
|
23
|
+
body: JSON.stringify({ query, variables: payload || args[0] }),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
else if (rest.method && rest.method.toLowerCase() !== 'get') {
|
|
27
|
+
// REST - Mutation
|
|
28
|
+
autoOptions = {
|
|
29
|
+
body: JSON.stringify(payload === undefined ? args[0] : payload),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
// REST - Query
|
|
34
|
+
if (typeof options === 'object' && params === undefined)
|
|
35
|
+
searchParams = args[0];
|
|
36
|
+
}
|
|
37
|
+
const interceptedOptions = await interceptRequest({
|
|
38
|
+
url: searchParams ? [url, encodeParams(searchParams)].join('?') : url,
|
|
39
|
+
headers: { 'Content-Type': 'application/json', ...headers },
|
|
40
|
+
...autoOptions,
|
|
41
|
+
...rest,
|
|
42
|
+
});
|
|
43
|
+
const { url: finalUrl, ...finalOptions } = interceptedOptions;
|
|
44
|
+
const res = await fetch(finalUrl, finalOptions);
|
|
45
|
+
const contentType = res.headers.get('content-type');
|
|
46
|
+
if (contentType && contentType.includes('application/json')) {
|
|
47
|
+
const resJson = await res.json().catch(() => undefined);
|
|
48
|
+
if (resJson !== undefined) {
|
|
49
|
+
if (query && resJson.errors) {
|
|
50
|
+
throw { status: res.status, statusText: res.statusText, response: resJson };
|
|
51
|
+
}
|
|
52
|
+
if (res.ok) {
|
|
53
|
+
if (interceptResponse) {
|
|
54
|
+
try {
|
|
55
|
+
const finalResponse = await interceptResponse(resJson);
|
|
56
|
+
return finalResponse;
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
throw {
|
|
60
|
+
status: res.status,
|
|
61
|
+
statusText: res.statusText,
|
|
62
|
+
response: resJson,
|
|
63
|
+
error,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return resJson;
|
|
68
|
+
}
|
|
69
|
+
throw { status: res.status, statusText: res.statusText, response: resJson };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const resText = await res.text().catch(() => undefined);
|
|
73
|
+
throw { status: res.status, statusText: res.statusText, response: resText };
|
|
74
|
+
};
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -4,5 +4,6 @@ exports.hashStoreKey = void 0;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
var utils_1 = require("./utils");
|
|
6
6
|
Object.defineProperty(exports, "hashStoreKey", { enumerable: true, get: function () { return utils_1.hashStoreKey; } });
|
|
7
|
+
tslib_1.__exportStar(require("./utils/fetcher"), exports);
|
|
7
8
|
tslib_1.__exportStar(require("./vanilla"), exports);
|
|
8
9
|
tslib_1.__exportStar(require("./react"), exports);
|
|
@@ -70,7 +70,7 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
70
70
|
set({ isWaiting: true });
|
|
71
71
|
else
|
|
72
72
|
set({ isWaiting: true, isRefetching: true });
|
|
73
|
-
const callQuery = () => {
|
|
73
|
+
const callQuery = (innerResolve = resolve) => {
|
|
74
74
|
if (get().isGoingToRetry) {
|
|
75
75
|
if (isLoading)
|
|
76
76
|
set({ isGoingToRetry: false, isWaiting: true });
|
|
@@ -84,7 +84,7 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
84
84
|
.then((response) => {
|
|
85
85
|
if (preventReplaceResponse.get(keyHash)) {
|
|
86
86
|
set({ isWaiting: false, isRefetching: false });
|
|
87
|
-
return
|
|
87
|
+
return innerResolve(get());
|
|
88
88
|
}
|
|
89
89
|
responseAllPages.push(response);
|
|
90
90
|
const newPageParam = getNextPageParam(response, responseAllPages.length, stateBeforeCallQuery);
|
|
@@ -124,11 +124,26 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
124
124
|
}
|
|
125
125
|
set(nextState);
|
|
126
126
|
onSuccess(response, stateBeforeCallQuery);
|
|
127
|
+
onSettled(stateBeforeCallQuery);
|
|
128
|
+
innerResolve(get());
|
|
127
129
|
})
|
|
128
130
|
.catch((error) => {
|
|
129
131
|
const prevState = get();
|
|
130
132
|
const errorUpdatedAt = Date.now();
|
|
131
133
|
const { shouldRetry, delay } = getRetryProps(error, prevState.retryCount);
|
|
134
|
+
if (shouldRetry) {
|
|
135
|
+
set({
|
|
136
|
+
isWaiting: false,
|
|
137
|
+
isGoingToRetry: true,
|
|
138
|
+
});
|
|
139
|
+
if (utils_1.isClient) {
|
|
140
|
+
retryTimeoutId.set(keyHash, window.setTimeout(() => {
|
|
141
|
+
set({ retryCount: prevState.retryCount + 1 });
|
|
142
|
+
callQuery(innerResolve);
|
|
143
|
+
}, delay));
|
|
144
|
+
}
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
132
147
|
set(prevState.isSuccess && !prevState.isPreviousData
|
|
133
148
|
? {
|
|
134
149
|
isWaiting: false,
|
|
@@ -141,7 +156,6 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
141
156
|
: prevState.data,
|
|
142
157
|
error,
|
|
143
158
|
errorUpdatedAt,
|
|
144
|
-
isGoingToRetry: shouldRetry,
|
|
145
159
|
pageParam,
|
|
146
160
|
hasNextPage: (0, utils_1.hasValue)(pageParam),
|
|
147
161
|
}
|
|
@@ -153,21 +167,12 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
153
167
|
data: undefined,
|
|
154
168
|
error,
|
|
155
169
|
errorUpdatedAt,
|
|
156
|
-
isGoingToRetry: shouldRetry,
|
|
157
170
|
pageParam,
|
|
158
171
|
hasNextPage: (0, utils_1.hasValue)(pageParam),
|
|
159
172
|
});
|
|
160
|
-
if (shouldRetry && utils_1.isClient) {
|
|
161
|
-
retryTimeoutId.set(keyHash, window.setTimeout(() => {
|
|
162
|
-
set({ retryCount: prevState.retryCount + 1 });
|
|
163
|
-
callQuery();
|
|
164
|
-
}, delay));
|
|
165
|
-
}
|
|
166
173
|
onError(error, stateBeforeCallQuery);
|
|
167
|
-
})
|
|
168
|
-
.finally(() => {
|
|
169
174
|
onSettled(stateBeforeCallQuery);
|
|
170
|
-
|
|
175
|
+
innerResolve(get());
|
|
171
176
|
});
|
|
172
177
|
};
|
|
173
178
|
callQuery();
|
|
@@ -210,26 +215,30 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
210
215
|
hasNextPage: (0, utils_1.hasValue)(newPageParam),
|
|
211
216
|
});
|
|
212
217
|
onSuccess(response, stateBeforeCallQuery);
|
|
218
|
+
onSettled(stateBeforeCallQuery);
|
|
219
|
+
resolve(get());
|
|
213
220
|
})
|
|
214
221
|
.catch((error) => {
|
|
215
222
|
const prevState = get();
|
|
216
223
|
const { shouldRetry, delay } = getRetryProps(error, prevState.retryNextPageCount);
|
|
224
|
+
if (shouldRetry) {
|
|
225
|
+
set({
|
|
226
|
+
isWaitingNextPage: false,
|
|
227
|
+
isGoingToRetryNextPage: true,
|
|
228
|
+
});
|
|
229
|
+
retryNextPageTimeoutId.set(keyHash, window.setTimeout(() => {
|
|
230
|
+
set({ retryNextPageCount: prevState.retryNextPageCount + 1 });
|
|
231
|
+
resolve(fetchNextPage());
|
|
232
|
+
}, delay));
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
217
235
|
set({
|
|
218
236
|
isWaitingNextPage: false,
|
|
219
237
|
isError: true,
|
|
220
238
|
error,
|
|
221
239
|
errorUpdatedAt: Date.now(),
|
|
222
|
-
isGoingToRetryNextPage: shouldRetry,
|
|
223
240
|
});
|
|
224
|
-
if (shouldRetry) {
|
|
225
|
-
retryNextPageTimeoutId.set(keyHash, window.setTimeout(() => {
|
|
226
|
-
set({ retryNextPageCount: prevState.retryNextPageCount + 1 });
|
|
227
|
-
fetchNextPage();
|
|
228
|
-
}, delay));
|
|
229
|
-
}
|
|
230
241
|
onError(error, stateBeforeCallQuery);
|
|
231
|
-
})
|
|
232
|
-
.finally(() => {
|
|
233
242
|
onSettled(stateBeforeCallQuery);
|
|
234
243
|
resolve(get());
|
|
235
244
|
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
type FetcherOptions<TResponse = any> = {
|
|
2
|
+
url: string;
|
|
3
|
+
query?: string;
|
|
4
|
+
params?: Record<string, string | number | boolean> | null;
|
|
5
|
+
payload?: any;
|
|
6
|
+
interceptRequest?: (requestOptions: RequestInit & {
|
|
7
|
+
url: string;
|
|
8
|
+
}) => (RequestInit & {
|
|
9
|
+
url: string;
|
|
10
|
+
}) | Promise<RequestInit & {
|
|
11
|
+
url: string;
|
|
12
|
+
}>;
|
|
13
|
+
interceptResponse?: (response: TResponse) => TResponse | Promise<TResponse>;
|
|
14
|
+
} & RequestInit;
|
|
15
|
+
/**
|
|
16
|
+
* Experimental fetcher - abstraction layer for query/mutation function creator.
|
|
17
|
+
*
|
|
18
|
+
* Can be used for REST or GraphQL.
|
|
19
|
+
*
|
|
20
|
+
* @see https://floppy-disk.vercel.app/docs/experimental
|
|
21
|
+
*
|
|
22
|
+
* @returns A function to fetch data
|
|
23
|
+
*/
|
|
24
|
+
export declare const fetcher: <TResponse = any, TInput extends any[] = any[]>(options: FetcherOptions<TResponse> | ((...args: TInput) => FetcherOptions<TResponse>)) => (...args: TInput) => Promise<TResponse>;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fetcher = void 0;
|
|
4
|
+
/* eslint-disable no-throw-literal */
|
|
5
|
+
const _1 = require(".");
|
|
6
|
+
const encodeParams = (params) => Object.entries(params)
|
|
7
|
+
.map((kv) => kv.map(encodeURIComponent).join('='))
|
|
8
|
+
.join('&');
|
|
9
|
+
/**
|
|
10
|
+
* Experimental fetcher - abstraction layer for query/mutation function creator.
|
|
11
|
+
*
|
|
12
|
+
* Can be used for REST or GraphQL.
|
|
13
|
+
*
|
|
14
|
+
* @see https://floppy-disk.vercel.app/docs/experimental
|
|
15
|
+
*
|
|
16
|
+
* @returns A function to fetch data
|
|
17
|
+
*/
|
|
18
|
+
const fetcher = (options) => async (...args) => {
|
|
19
|
+
const { url, query, params, payload, headers, interceptRequest = _1.identityFn, interceptResponse, ...rest } = (0, _1.getValueOrComputedValue)(options, ...args);
|
|
20
|
+
let autoOptions = {};
|
|
21
|
+
let searchParams = params;
|
|
22
|
+
if (query) {
|
|
23
|
+
// GraphQL
|
|
24
|
+
autoOptions = {
|
|
25
|
+
method: 'POST',
|
|
26
|
+
body: JSON.stringify({ query, variables: payload || args[0] }),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
else if (rest.method && rest.method.toLowerCase() !== 'get') {
|
|
30
|
+
// REST - Mutation
|
|
31
|
+
autoOptions = {
|
|
32
|
+
body: JSON.stringify(payload === undefined ? args[0] : payload),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
// REST - Query
|
|
37
|
+
if (typeof options === 'object' && params === undefined)
|
|
38
|
+
searchParams = args[0];
|
|
39
|
+
}
|
|
40
|
+
const interceptedOptions = await interceptRequest({
|
|
41
|
+
url: searchParams ? [url, encodeParams(searchParams)].join('?') : url,
|
|
42
|
+
headers: { 'Content-Type': 'application/json', ...headers },
|
|
43
|
+
...autoOptions,
|
|
44
|
+
...rest,
|
|
45
|
+
});
|
|
46
|
+
const { url: finalUrl, ...finalOptions } = interceptedOptions;
|
|
47
|
+
const res = await fetch(finalUrl, finalOptions);
|
|
48
|
+
const contentType = res.headers.get('content-type');
|
|
49
|
+
if (contentType && contentType.includes('application/json')) {
|
|
50
|
+
const resJson = await res.json().catch(() => undefined);
|
|
51
|
+
if (resJson !== undefined) {
|
|
52
|
+
if (query && resJson.errors) {
|
|
53
|
+
throw { status: res.status, statusText: res.statusText, response: resJson };
|
|
54
|
+
}
|
|
55
|
+
if (res.ok) {
|
|
56
|
+
if (interceptResponse) {
|
|
57
|
+
try {
|
|
58
|
+
const finalResponse = await interceptResponse(resJson);
|
|
59
|
+
return finalResponse;
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
throw {
|
|
63
|
+
status: res.status,
|
|
64
|
+
statusText: res.statusText,
|
|
65
|
+
response: resJson,
|
|
66
|
+
error,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return resJson;
|
|
71
|
+
}
|
|
72
|
+
throw { status: res.status, statusText: res.statusText, response: resJson };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const resText = await res.text().catch(() => undefined);
|
|
76
|
+
throw { status: res.status, statusText: res.statusText, response: resText };
|
|
77
|
+
};
|
|
78
|
+
exports.fetcher = fetcher;
|