@zayne-labs/callapi 1.7.18 → 1.8.1
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/esm/common-B_Me8xq2.d.ts +909 -0
- package/dist/esm/index.d.ts +10 -7
- package/dist/esm/index.js +699 -690
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/utils/index.d.ts +12 -6
- package/dist/esm/utils/index.js +3 -3
- package/dist/esm/utils-D6Sax78G.js +393 -0
- package/dist/esm/utils-D6Sax78G.js.map +1 -0
- package/package.json +10 -9
- package/dist/esm/chunk-F56CKRKR.js +0 -278
- package/dist/esm/chunk-F56CKRKR.js.map +0 -1
- package/dist/esm/common-C3q7szew.d.ts +0 -774
- package/dist/esm/utils/index.js.map +0 -1
package/dist/esm/index.js
CHANGED
@@ -1,729 +1,738 @@
|
|
1
|
-
import {
|
2
|
-
export { HTTPError } from './chunk-F56CKRKR.js';
|
1
|
+
import { HTTPError, ValidationError, commonDefaults, createCombinedSignal, createTimeoutSignal, dedupeDefaults, defineSchema, getBody, getFetchImpl, getHeaders, handleOptionsValidation, handleValidation, hookDefaults, isArray, isFunction, isHTTPError, isHTTPErrorInstance, isObject, isPlainObject, isReadableStream, isString, isValidationErrorInstance, requestOptionDefaults, responseDefaults, retryDefaults, routeKeyMethods, splitBaseConfig, splitConfig, toQueryString, waitFor } from "./utils-D6Sax78G.js";
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
3
|
+
//#region src/result.ts
|
4
|
+
const getResponseType = (response, parser) => ({
|
5
|
+
arrayBuffer: () => response.arrayBuffer(),
|
6
|
+
blob: () => response.blob(),
|
7
|
+
formData: () => response.formData(),
|
8
|
+
json: async () => {
|
9
|
+
const text = await response.text();
|
10
|
+
return parser(text);
|
11
|
+
},
|
12
|
+
stream: () => response.body,
|
13
|
+
text: () => response.text()
|
15
14
|
});
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
}
|
23
|
-
return RESPONSE_TYPE_LOOKUP[selectedResponseType]();
|
15
|
+
const resolveResponseData = (response, responseType, parser) => {
|
16
|
+
const selectedParser = parser ?? responseDefaults.responseParser;
|
17
|
+
const selectedResponseType = responseType ?? responseDefaults.responseType;
|
18
|
+
const RESPONSE_TYPE_LOOKUP = getResponseType(response, selectedParser);
|
19
|
+
if (!Object.hasOwn(RESPONSE_TYPE_LOOKUP, selectedResponseType)) throw new Error(`Invalid response type: ${responseType}`);
|
20
|
+
return RESPONSE_TYPE_LOOKUP[selectedResponseType]();
|
24
21
|
};
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
22
|
+
const getResultModeMap = (details) => {
|
23
|
+
const resultModeMap = {
|
24
|
+
all: () => details,
|
25
|
+
allWithException: () => resultModeMap.all(),
|
26
|
+
onlySuccess: () => details.data,
|
27
|
+
onlySuccessWithException: () => resultModeMap.onlySuccess()
|
28
|
+
};
|
29
|
+
return resultModeMap;
|
33
30
|
};
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
31
|
+
const resolveSuccessResult = (data, info) => {
|
32
|
+
const { response, resultMode } = info;
|
33
|
+
const details = {
|
34
|
+
data,
|
35
|
+
error: null,
|
36
|
+
response
|
37
|
+
};
|
38
|
+
const resultModeMap = getResultModeMap(details);
|
39
|
+
const successResult = resultModeMap[resultMode ?? "all"]();
|
40
|
+
return successResult;
|
44
41
|
};
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
42
|
+
const resolveErrorResult = (error, info) => {
|
43
|
+
const { cloneResponse, defaultErrorMessage, message: customErrorMessage, resultMode } = info;
|
44
|
+
let details = {
|
45
|
+
data: null,
|
46
|
+
error: {
|
47
|
+
errorData: error,
|
48
|
+
message: customErrorMessage ?? error.message,
|
49
|
+
name: error.name,
|
50
|
+
originalError: error
|
51
|
+
},
|
52
|
+
response: null
|
53
|
+
};
|
54
|
+
if (isValidationErrorInstance(error)) {
|
55
|
+
const { errorData, message, response } = error;
|
56
|
+
details = {
|
57
|
+
data: null,
|
58
|
+
error: {
|
59
|
+
errorData,
|
60
|
+
message,
|
61
|
+
name: "ValidationError",
|
62
|
+
originalError: error
|
63
|
+
},
|
64
|
+
response
|
65
|
+
};
|
66
|
+
}
|
67
|
+
if (isHTTPErrorInstance(error)) {
|
68
|
+
const selectedDefaultErrorMessage = defaultErrorMessage ?? commonDefaults.defaultErrorMessage;
|
69
|
+
const { errorData, message = selectedDefaultErrorMessage, name, response } = error;
|
70
|
+
details = {
|
71
|
+
data: null,
|
72
|
+
error: {
|
73
|
+
errorData,
|
74
|
+
message,
|
75
|
+
name,
|
76
|
+
originalError: error
|
77
|
+
},
|
78
|
+
response: cloneResponse ? response.clone() : response
|
79
|
+
};
|
80
|
+
}
|
81
|
+
const resultModeMap = getResultModeMap(details);
|
82
|
+
const errorResult = resultModeMap[resultMode ?? "all"]();
|
83
|
+
return errorResult;
|
74
84
|
};
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
}
|
86
|
-
};
|
85
|
+
const getCustomizedErrorResult = (errorResult, customErrorInfo) => {
|
86
|
+
if (!errorResult) return null;
|
87
|
+
const { message = errorResult.error.message } = customErrorInfo;
|
88
|
+
return {
|
89
|
+
...errorResult,
|
90
|
+
error: {
|
91
|
+
...errorResult.error,
|
92
|
+
message
|
93
|
+
}
|
94
|
+
};
|
87
95
|
};
|
88
96
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
97
|
+
//#endregion
|
98
|
+
//#region src/hooks.ts
|
99
|
+
const hookRegistries = {
|
100
|
+
onError: /* @__PURE__ */ new Set(),
|
101
|
+
onRequest: /* @__PURE__ */ new Set(),
|
102
|
+
onRequestError: /* @__PURE__ */ new Set(),
|
103
|
+
onRequestStream: /* @__PURE__ */ new Set(),
|
104
|
+
onResponse: /* @__PURE__ */ new Set(),
|
105
|
+
onResponseError: /* @__PURE__ */ new Set(),
|
106
|
+
onResponseStream: /* @__PURE__ */ new Set(),
|
107
|
+
onRetry: /* @__PURE__ */ new Set(),
|
108
|
+
onSuccess: /* @__PURE__ */ new Set(),
|
109
|
+
onValidationError: /* @__PURE__ */ new Set()
|
100
110
|
};
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
};
|
115
|
-
return mergedHook;
|
111
|
+
const composeTwoHooks = (hooks, mergedHooksExecutionMode) => {
|
112
|
+
if (hooks.length === 0) return;
|
113
|
+
const mergedHook = async (ctx) => {
|
114
|
+
if (mergedHooksExecutionMode === "sequential") {
|
115
|
+
for (const hook of hooks) await hook?.(ctx);
|
116
|
+
return;
|
117
|
+
}
|
118
|
+
if (mergedHooksExecutionMode === "parallel") {
|
119
|
+
const hookArray = [...hooks];
|
120
|
+
await Promise.all(hookArray.map((uniqueHook) => uniqueHook?.(ctx)));
|
121
|
+
}
|
122
|
+
};
|
123
|
+
return mergedHook;
|
116
124
|
};
|
117
|
-
|
118
|
-
|
125
|
+
const executeHooksInTryBlock = async (...hookResultsOrPromise) => {
|
126
|
+
await Promise.all(hookResultsOrPromise);
|
119
127
|
};
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
return hookErrorResult;
|
131
|
-
}
|
128
|
+
const executeHooksInCatchBlock = async (hookResultsOrPromise, hookInfo) => {
|
129
|
+
const { errorInfo, shouldThrowOnError } = hookInfo;
|
130
|
+
try {
|
131
|
+
await Promise.all(hookResultsOrPromise);
|
132
|
+
return null;
|
133
|
+
} catch (hookError) {
|
134
|
+
const hookErrorResult = resolveErrorResult(hookError, errorInfo);
|
135
|
+
if (shouldThrowOnError) throw hookError;
|
136
|
+
return hookErrorResult;
|
137
|
+
}
|
132
138
|
};
|
133
139
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
140
|
+
//#endregion
|
141
|
+
//#region src/stream.ts
|
142
|
+
const createProgressEvent = (options) => {
|
143
|
+
const { chunk, totalBytes, transferredBytes } = options;
|
144
|
+
return {
|
145
|
+
chunk,
|
146
|
+
progress: Math.round(transferredBytes / totalBytes * 100) || 0,
|
147
|
+
totalBytes,
|
148
|
+
transferredBytes
|
149
|
+
};
|
143
150
|
};
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
for await (const chunk of requestBody) {
|
150
|
-
totalBytes += chunk.byteLength;
|
151
|
-
}
|
152
|
-
return totalBytes;
|
151
|
+
const calculateTotalBytesFromBody = async (requestBody, existingTotalBytes) => {
|
152
|
+
let totalBytes = existingTotalBytes;
|
153
|
+
if (!requestBody) return totalBytes;
|
154
|
+
for await (const chunk of requestBody) totalBytes += chunk.byteLength;
|
155
|
+
return totalBytes;
|
153
156
|
};
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
157
|
+
const toStreamableRequest = async (context) => {
|
158
|
+
const { baseConfig, config, options, request, requestInstance } = context;
|
159
|
+
if (!options.onRequestStream || !requestInstance.body) return;
|
160
|
+
const contentLength = requestInstance.headers.get("content-length") ?? new Headers(request.headers).get("content-length") ?? request.body?.size;
|
161
|
+
let totalBytes = Number(contentLength ?? 0);
|
162
|
+
const shouldForceContentLengthCalc = isObject(options.forceCalculateStreamSize) ? options.forceCalculateStreamSize.request : options.forceCalculateStreamSize;
|
163
|
+
if (!contentLength && shouldForceContentLengthCalc) totalBytes = await calculateTotalBytesFromBody(requestInstance.clone().body, totalBytes);
|
164
|
+
let transferredBytes = 0;
|
165
|
+
await executeHooksInTryBlock(options.onRequestStream({
|
166
|
+
baseConfig,
|
167
|
+
config,
|
168
|
+
event: createProgressEvent({
|
169
|
+
chunk: new Uint8Array(),
|
170
|
+
totalBytes,
|
171
|
+
transferredBytes
|
172
|
+
}),
|
173
|
+
options,
|
174
|
+
request,
|
175
|
+
requestInstance
|
176
|
+
}));
|
177
|
+
const body = requestInstance.body;
|
178
|
+
new ReadableStream({ start: async (controller) => {
|
179
|
+
if (!body) return;
|
180
|
+
for await (const chunk of body) {
|
181
|
+
transferredBytes += chunk.byteLength;
|
182
|
+
totalBytes = Math.max(totalBytes, transferredBytes);
|
183
|
+
await executeHooksInTryBlock(options.onRequestStream?.({
|
184
|
+
baseConfig,
|
185
|
+
config,
|
186
|
+
event: createProgressEvent({
|
187
|
+
chunk,
|
188
|
+
totalBytes,
|
189
|
+
transferredBytes
|
190
|
+
}),
|
191
|
+
options,
|
192
|
+
request,
|
193
|
+
requestInstance
|
194
|
+
}));
|
195
|
+
controller.enqueue(chunk);
|
196
|
+
}
|
197
|
+
controller.close();
|
198
|
+
} });
|
196
199
|
};
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
});
|
241
|
-
return new Response(stream, response);
|
200
|
+
const toStreamableResponse = async (context) => {
|
201
|
+
const { baseConfig, config, options, request, response } = context;
|
202
|
+
if (!options.onResponseStream || !response.body) return response;
|
203
|
+
const contentLength = response.headers.get("content-length");
|
204
|
+
let totalBytes = Number(contentLength ?? 0);
|
205
|
+
const shouldForceContentLengthCalc = isObject(options.forceCalculateStreamSize) ? options.forceCalculateStreamSize.response : options.forceCalculateStreamSize;
|
206
|
+
if (!contentLength && shouldForceContentLengthCalc) totalBytes = await calculateTotalBytesFromBody(response.clone().body, totalBytes);
|
207
|
+
let transferredBytes = 0;
|
208
|
+
await executeHooksInTryBlock(options.onResponseStream({
|
209
|
+
baseConfig,
|
210
|
+
config,
|
211
|
+
event: createProgressEvent({
|
212
|
+
chunk: new Uint8Array(),
|
213
|
+
totalBytes,
|
214
|
+
transferredBytes
|
215
|
+
}),
|
216
|
+
options,
|
217
|
+
request,
|
218
|
+
response
|
219
|
+
}));
|
220
|
+
const body = response.body;
|
221
|
+
const stream = new ReadableStream({ start: async (controller) => {
|
222
|
+
if (!body) return;
|
223
|
+
for await (const chunk of body) {
|
224
|
+
transferredBytes += chunk.byteLength;
|
225
|
+
totalBytes = Math.max(totalBytes, transferredBytes);
|
226
|
+
await executeHooksInTryBlock(options.onResponseStream?.({
|
227
|
+
baseConfig,
|
228
|
+
config,
|
229
|
+
event: createProgressEvent({
|
230
|
+
chunk,
|
231
|
+
totalBytes,
|
232
|
+
transferredBytes
|
233
|
+
}),
|
234
|
+
options,
|
235
|
+
request,
|
236
|
+
response
|
237
|
+
}));
|
238
|
+
controller.enqueue(chunk);
|
239
|
+
}
|
240
|
+
controller.close();
|
241
|
+
} });
|
242
|
+
return new Response(stream, response);
|
242
243
|
};
|
243
244
|
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
245
|
+
//#endregion
|
246
|
+
//#region src/dedupe.ts
|
247
|
+
const getAbortErrorMessage = (dedupeKey, fullURL) => {
|
248
|
+
return dedupeKey ? `Duplicate request detected - Aborting previous request with key '${dedupeKey}' as a new request was initiated` : `Duplicate request detected - Aborting previous request to '${fullURL}' as a new request with identical options was initiated`;
|
249
|
+
};
|
250
|
+
const createDedupeStrategy = async (context) => {
|
251
|
+
const { $RequestInfoCache, baseConfig, config, newFetchController, options: globalOptions, request: globalRequest } = context;
|
252
|
+
const dedupeStrategy = globalOptions.dedupeStrategy ?? dedupeDefaults.dedupeStrategy;
|
253
|
+
const generateDedupeKey = () => {
|
254
|
+
const shouldHaveDedupeKey = dedupeStrategy === "cancel" || dedupeStrategy === "defer";
|
255
|
+
if (!shouldHaveDedupeKey) return null;
|
256
|
+
return `${globalOptions.fullURL}-${JSON.stringify({
|
257
|
+
options: globalOptions,
|
258
|
+
request: globalRequest
|
259
|
+
})}`;
|
260
|
+
};
|
261
|
+
const dedupeKey = globalOptions.dedupeKey ?? generateDedupeKey();
|
262
|
+
const $RequestInfoCacheOrNull = dedupeKey !== null ? $RequestInfoCache : null;
|
263
|
+
/******
|
264
|
+
* == Add a small delay to the execution to ensure proper request deduplication when multiple requests with the same key start simultaneously.
|
265
|
+
* == This gives time for the cache to be updated with the previous request info before the next request checks it.
|
266
|
+
******/
|
267
|
+
if (dedupeKey !== null) await waitFor(.1);
|
268
|
+
const prevRequestInfo = $RequestInfoCacheOrNull?.get(dedupeKey);
|
269
|
+
const handleRequestCancelStrategy = () => {
|
270
|
+
const shouldCancelRequest = prevRequestInfo && dedupeStrategy === "cancel";
|
271
|
+
if (!shouldCancelRequest) return;
|
272
|
+
const message = getAbortErrorMessage(globalOptions.dedupeKey, globalOptions.fullURL);
|
273
|
+
const reason = new DOMException(message, "AbortError");
|
274
|
+
prevRequestInfo.controller.abort(reason);
|
275
|
+
return Promise.resolve();
|
276
|
+
};
|
277
|
+
const handleRequestDeferStrategy = async (options, request) => {
|
278
|
+
const fetchApi = getFetchImpl(options.customFetchImpl);
|
279
|
+
const shouldUsePromiseFromCache = prevRequestInfo && dedupeStrategy === "defer";
|
280
|
+
const requestObjectForStream = isReadableStream(request.body) ? {
|
281
|
+
...request,
|
282
|
+
duplex: request.duplex ?? "half"
|
283
|
+
} : request;
|
284
|
+
const requestInstance = new Request(options.fullURL, requestObjectForStream);
|
285
|
+
await toStreamableRequest({
|
286
|
+
baseConfig,
|
287
|
+
config,
|
288
|
+
options,
|
289
|
+
request,
|
290
|
+
requestInstance: requestInstance.clone()
|
291
|
+
});
|
292
|
+
const getFetchApiPromise = () => {
|
293
|
+
if (isReadableStream(request.body)) return fetchApi(requestInstance.clone());
|
294
|
+
return fetchApi(options.fullURL, request);
|
295
|
+
};
|
296
|
+
const responsePromise = shouldUsePromiseFromCache ? prevRequestInfo.responsePromise : getFetchApiPromise();
|
297
|
+
$RequestInfoCacheOrNull?.set(dedupeKey, {
|
298
|
+
controller: newFetchController,
|
299
|
+
responsePromise
|
300
|
+
});
|
301
|
+
const streamableResponse = toStreamableResponse({
|
302
|
+
baseConfig,
|
303
|
+
config,
|
304
|
+
options,
|
305
|
+
request,
|
306
|
+
response: await responsePromise
|
307
|
+
});
|
308
|
+
return streamableResponse;
|
309
|
+
};
|
310
|
+
const removeDedupeKeyFromCache = () => {
|
311
|
+
$RequestInfoCacheOrNull?.delete(dedupeKey);
|
312
|
+
};
|
313
|
+
return {
|
314
|
+
dedupeStrategy,
|
315
|
+
handleRequestCancelStrategy,
|
316
|
+
handleRequestDeferStrategy,
|
317
|
+
removeDedupeKeyFromCache
|
318
|
+
};
|
311
319
|
};
|
312
320
|
|
313
|
-
|
314
|
-
|
315
|
-
|
321
|
+
//#endregion
|
322
|
+
//#region src/plugins.ts
|
323
|
+
const definePlugin = (plugin) => {
|
324
|
+
return plugin;
|
316
325
|
};
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
if (isFunction(plugins)) {
|
322
|
-
return plugins({ basePlugins: basePlugins ?? [] });
|
323
|
-
}
|
324
|
-
return plugins;
|
326
|
+
const resolvePluginArray = (plugins, basePlugins) => {
|
327
|
+
if (!plugins) return [];
|
328
|
+
if (isFunction(plugins)) return plugins({ basePlugins: basePlugins ?? [] });
|
329
|
+
return plugins;
|
325
330
|
};
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
const composedHook = composeTwoHooks(flattenedHookArray, mergedHooksExecutionMode);
|
387
|
-
composedHook && (resolvedHooks[key] = composedHook);
|
388
|
-
}
|
389
|
-
return {
|
390
|
-
resolvedHooks,
|
391
|
-
resolvedOptions,
|
392
|
-
resolvedRequestOptions,
|
393
|
-
url: resolvedUrl?.toString()
|
394
|
-
};
|
331
|
+
const initializePlugins = async (context) => {
|
332
|
+
const { baseConfig, config, initURL, options, request } = context;
|
333
|
+
const clonedHookRegistries = structuredClone(hookRegistries);
|
334
|
+
const addMainHooks = () => {
|
335
|
+
for (const key of Object.keys(clonedHookRegistries)) {
|
336
|
+
const baseHook = baseConfig[key];
|
337
|
+
const instanceHook = config[key];
|
338
|
+
const overriddenHook = options[key];
|
339
|
+
const mainHook = isArray(baseHook) && Boolean(instanceHook) ? [baseHook, instanceHook].flat() : overriddenHook;
|
340
|
+
if (!mainHook) continue;
|
341
|
+
clonedHookRegistries[key].add(mainHook);
|
342
|
+
}
|
343
|
+
};
|
344
|
+
const addPluginHooks = (pluginHooks) => {
|
345
|
+
for (const key of Object.keys(clonedHookRegistries)) {
|
346
|
+
const pluginHook = pluginHooks[key];
|
347
|
+
if (!pluginHook) continue;
|
348
|
+
clonedHookRegistries[key].add(pluginHook);
|
349
|
+
}
|
350
|
+
};
|
351
|
+
const mergedHooksExecutionOrder = options.mergedHooksExecutionOrder ?? hookDefaults.mergedHooksExecutionOrder;
|
352
|
+
if (mergedHooksExecutionOrder === "mainHooksBeforePlugins") addMainHooks();
|
353
|
+
const resolvedPlugins = resolvePluginArray(options.plugins, baseConfig.plugins);
|
354
|
+
let resolvedInitURL = initURL;
|
355
|
+
let resolvedOptions = options;
|
356
|
+
let resolvedRequestOptions = request;
|
357
|
+
const executePluginInit = async (pluginInit) => {
|
358
|
+
if (!pluginInit) return;
|
359
|
+
const initResult = await pluginInit({
|
360
|
+
baseConfig,
|
361
|
+
config,
|
362
|
+
initURL,
|
363
|
+
options,
|
364
|
+
request
|
365
|
+
});
|
366
|
+
if (!isPlainObject(initResult)) return;
|
367
|
+
const urlString = initResult.initURL?.toString();
|
368
|
+
if (isString(urlString)) resolvedInitURL = urlString;
|
369
|
+
if (isPlainObject(initResult.request)) resolvedRequestOptions = initResult.request;
|
370
|
+
if (isPlainObject(initResult.options)) resolvedOptions = initResult.options;
|
371
|
+
};
|
372
|
+
for (const plugin of resolvedPlugins) {
|
373
|
+
await executePluginInit(plugin.init);
|
374
|
+
if (!plugin.hooks) continue;
|
375
|
+
addPluginHooks(plugin.hooks);
|
376
|
+
}
|
377
|
+
if (mergedHooksExecutionOrder === "mainHooksAfterPlugins") addMainHooks();
|
378
|
+
const resolvedHooks = {};
|
379
|
+
for (const [key, hookRegistry] of Object.entries(clonedHookRegistries)) {
|
380
|
+
const flattenedHookArray = [...hookRegistry].flat();
|
381
|
+
const mergedHooksExecutionMode = options.mergedHooksExecutionMode ?? hookDefaults.mergedHooksExecutionMode;
|
382
|
+
const composedHook = composeTwoHooks(flattenedHookArray, mergedHooksExecutionMode);
|
383
|
+
composedHook && (resolvedHooks[key] = composedHook);
|
384
|
+
}
|
385
|
+
return {
|
386
|
+
resolvedHooks,
|
387
|
+
resolvedInitURL: resolvedInitURL.toString(),
|
388
|
+
resolvedOptions,
|
389
|
+
resolvedRequestOptions
|
390
|
+
};
|
395
391
|
};
|
396
392
|
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
393
|
+
//#endregion
|
394
|
+
//#region src/retry.ts
|
395
|
+
const getLinearDelay = (currentAttemptCount, options) => {
|
396
|
+
const retryDelay = options.retryDelay ?? options.retry?.delay;
|
397
|
+
const resolveRetryDelay = (isFunction(retryDelay) ? retryDelay(currentAttemptCount) : retryDelay) ?? retryDefaults.delay;
|
398
|
+
return resolveRetryDelay;
|
402
399
|
};
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
const exponentialDelay = resolvedRetryDelay * 2 ** currentAttemptCount;
|
410
|
-
return Math.min(exponentialDelay, maxDelay);
|
400
|
+
const getExponentialDelay = (currentAttemptCount, options) => {
|
401
|
+
const retryDelay = options.retryDelay ?? options.retry?.delay ?? retryDefaults.delay;
|
402
|
+
const resolvedRetryDelay = Number(isFunction(retryDelay) ? retryDelay(currentAttemptCount) : retryDelay);
|
403
|
+
const maxDelay = Number(options.retryMaxDelay ?? options.retry?.maxDelay ?? retryDefaults.maxDelay);
|
404
|
+
const exponentialDelay = resolvedRetryDelay * 2 ** currentAttemptCount;
|
405
|
+
return Math.min(exponentialDelay, maxDelay);
|
411
406
|
};
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
const retryStatusCodes = selectedStatusCodeArray ? new Set(selectedStatusCodeArray) : null;
|
446
|
-
const includesStatusCodes = Boolean(ctx.response?.status) && (retryStatusCodes?.has(ctx.response.status) ?? true);
|
447
|
-
const shouldRetry = includesMethod && includesStatusCodes;
|
448
|
-
return shouldRetry;
|
449
|
-
};
|
450
|
-
return {
|
451
|
-
currentAttemptCount,
|
452
|
-
getDelay,
|
453
|
-
shouldAttemptRetry
|
454
|
-
};
|
407
|
+
const createRetryStrategy = (ctx) => {
|
408
|
+
const { options } = ctx;
|
409
|
+
const currentAttemptCount = options["~retryAttemptCount"] ?? 1;
|
410
|
+
const retryStrategy = options.retryStrategy ?? options.retry?.strategy ?? retryDefaults.strategy;
|
411
|
+
const getDelay = () => {
|
412
|
+
switch (retryStrategy) {
|
413
|
+
case "exponential": return getExponentialDelay(currentAttemptCount, options);
|
414
|
+
case "linear": return getLinearDelay(currentAttemptCount, options);
|
415
|
+
default: throw new Error(`Invalid retry strategy: ${String(retryStrategy)}`);
|
416
|
+
}
|
417
|
+
};
|
418
|
+
const shouldAttemptRetry = async () => {
|
419
|
+
const retryCondition = options.retryCondition ?? options.retry?.condition ?? retryDefaults.condition;
|
420
|
+
const maximumRetryAttempts = options.retryAttempts ?? options.retry?.attempts ?? retryDefaults.attempts;
|
421
|
+
const customRetryCondition = await retryCondition(ctx);
|
422
|
+
const baseShouldRetry = maximumRetryAttempts >= currentAttemptCount && customRetryCondition;
|
423
|
+
if (!baseShouldRetry) return false;
|
424
|
+
if (!isHTTPError(ctx.error)) return true;
|
425
|
+
const selectedMethodArray = options.retryMethods ?? options.retry?.methods ?? retryDefaults.methods;
|
426
|
+
const retryMethods = new Set(selectedMethodArray);
|
427
|
+
const method = ctx.request.method ?? requestOptionDefaults.method;
|
428
|
+
const includesMethod = Boolean(method) && retryMethods.has(method);
|
429
|
+
const selectedStatusCodeArray = options.retryStatusCodes ?? options.retry?.statusCodes;
|
430
|
+
const retryStatusCodes = selectedStatusCodeArray ? new Set(selectedStatusCodeArray) : null;
|
431
|
+
const includesStatusCodes = Boolean(ctx.response?.status) && (retryStatusCodes?.has(ctx.response.status) ?? true);
|
432
|
+
const shouldRetry = includesMethod && includesStatusCodes;
|
433
|
+
return shouldRetry;
|
434
|
+
};
|
435
|
+
return {
|
436
|
+
currentAttemptCount,
|
437
|
+
getDelay,
|
438
|
+
shouldAttemptRetry
|
439
|
+
};
|
455
440
|
};
|
456
441
|
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
newUrl = newUrl.replace(`${column}${key}`, String(value));
|
475
|
-
}
|
476
|
-
return newUrl;
|
442
|
+
//#endregion
|
443
|
+
//#region src/url.ts
|
444
|
+
const slash = "/";
|
445
|
+
const column = ":";
|
446
|
+
const mergeUrlWithParams = (url, params) => {
|
447
|
+
if (!params) return url;
|
448
|
+
let newUrl = url;
|
449
|
+
if (isArray(params)) {
|
450
|
+
const matchedParamArray = newUrl.split(slash).filter((param) => param.startsWith(column));
|
451
|
+
for (const [index, matchedParam] of matchedParamArray.entries()) {
|
452
|
+
const realParam = params[index];
|
453
|
+
newUrl = newUrl.replace(matchedParam, realParam);
|
454
|
+
}
|
455
|
+
return newUrl;
|
456
|
+
}
|
457
|
+
for (const [key, value] of Object.entries(params)) newUrl = newUrl.replace(`${column}${key}`, String(value));
|
458
|
+
return newUrl;
|
477
459
|
};
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
}
|
488
|
-
if (url.endsWith(questionMark)) {
|
489
|
-
return `${url}${queryString}`;
|
490
|
-
}
|
491
|
-
if (url.includes(questionMark)) {
|
492
|
-
return `${url}${ampersand}${queryString}`;
|
493
|
-
}
|
494
|
-
return `${url}${questionMark}${queryString}`;
|
460
|
+
const questionMark = "?";
|
461
|
+
const ampersand = "&";
|
462
|
+
const mergeUrlWithQuery = (url, query) => {
|
463
|
+
if (!query) return url;
|
464
|
+
const queryString = toQueryString(query);
|
465
|
+
if (queryString?.length === 0) return url;
|
466
|
+
if (url.endsWith(questionMark)) return `${url}${queryString}`;
|
467
|
+
if (url.includes(questionMark)) return `${url}${ampersand}${queryString}`;
|
468
|
+
return `${url}${questionMark}${queryString}`;
|
495
469
|
};
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
470
|
+
const getCurrentRouteKey = (url, schemaConfig) => {
|
471
|
+
let currentRouteKey = url;
|
472
|
+
if (schemaConfig?.baseURL && currentRouteKey.startsWith(schemaConfig.baseURL)) currentRouteKey = currentRouteKey.replace(schemaConfig.baseURL, "");
|
473
|
+
return currentRouteKey;
|
500
474
|
};
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
475
|
+
/**
|
476
|
+
* @description
|
477
|
+
* Extracts the method from the URL if it is a schema modifier.
|
478
|
+
*
|
479
|
+
* @param initURL - The URL to extract the method from.
|
480
|
+
* @returns The method if it is a schema modifier, otherwise undefined.
|
481
|
+
*/
|
482
|
+
const extractMethodFromURL = (initURL) => {
|
483
|
+
if (!initURL?.startsWith("@")) return;
|
484
|
+
const method = initURL.split("@")[1]?.split("/")[0];
|
485
|
+
if (!method || !routeKeyMethods.includes(method)) return;
|
486
|
+
return method;
|
487
|
+
};
|
488
|
+
const getMethod = (options) => {
|
489
|
+
const { initURL, method, schemaConfig } = options;
|
490
|
+
if (schemaConfig?.requireHttpMethodProvision === true) return method?.toUpperCase() ?? requestOptionDefaults.method;
|
491
|
+
return method?.toUpperCase() ?? extractMethodFromURL(initURL)?.toUpperCase() ?? requestOptionDefaults.method;
|
492
|
+
};
|
493
|
+
const normalizeURL = (initURL) => {
|
494
|
+
const methodFromURL = extractMethodFromURL(initURL);
|
495
|
+
if (!methodFromURL) return initURL;
|
496
|
+
const normalizedURL = initURL.replace(`@${methodFromURL}/`, "/");
|
497
|
+
return normalizedURL;
|
509
498
|
};
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
499
|
+
const getFullURL = (options) => {
|
500
|
+
const { baseURL, initURL, params, query } = options;
|
501
|
+
const normalizedURL = normalizeURL(initURL);
|
502
|
+
const urlWithMergedParams = mergeUrlWithParams(normalizedURL, params);
|
503
|
+
const urlWithMergedQueryAndParams = mergeUrlWithQuery(urlWithMergedParams, query);
|
504
|
+
if (urlWithMergedQueryAndParams.startsWith("http") || !baseURL) return urlWithMergedQueryAndParams;
|
505
|
+
return `${baseURL}${urlWithMergedQueryAndParams}`;
|
514
506
|
};
|
515
507
|
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
508
|
+
//#endregion
|
509
|
+
//#region src/createFetchClient.ts
|
510
|
+
const createFetchClient = (initBaseConfig = {}) => {
|
511
|
+
const $RequestInfoCache = /* @__PURE__ */ new Map();
|
512
|
+
const callApi$1 = async (...parameters) => {
|
513
|
+
const [initURLOrURLObject, initConfig = {}] = parameters;
|
514
|
+
const [fetchOptions, extraOptions] = splitConfig(initConfig);
|
515
|
+
const resolvedBaseConfig = isFunction(initBaseConfig) ? initBaseConfig({
|
516
|
+
initURL: initURLOrURLObject.toString(),
|
517
|
+
options: extraOptions,
|
518
|
+
request: fetchOptions
|
519
|
+
}) : initBaseConfig;
|
520
|
+
const [baseFetchOptions, baseExtraOptions] = splitBaseConfig(resolvedBaseConfig);
|
521
|
+
const mergedExtraOptions = {
|
522
|
+
...baseExtraOptions,
|
523
|
+
...baseExtraOptions.skipAutoMergeFor !== "all" && baseExtraOptions.skipAutoMergeFor !== "options" && extraOptions
|
524
|
+
};
|
525
|
+
const mergedRequestOptions = {
|
526
|
+
...baseFetchOptions,
|
527
|
+
...baseExtraOptions.skipAutoMergeFor !== "all" && baseExtraOptions.skipAutoMergeFor !== "request" && fetchOptions
|
528
|
+
};
|
529
|
+
const baseConfig = resolvedBaseConfig;
|
530
|
+
const config = initConfig;
|
531
|
+
const { resolvedHooks, resolvedInitURL, resolvedOptions, resolvedRequestOptions } = await initializePlugins({
|
532
|
+
baseConfig,
|
533
|
+
config,
|
534
|
+
initURL: initURLOrURLObject.toString(),
|
535
|
+
options: mergedExtraOptions,
|
536
|
+
request: mergedRequestOptions
|
537
|
+
});
|
538
|
+
const fullURL = getFullURL({
|
539
|
+
baseURL: resolvedOptions.baseURL,
|
540
|
+
initURL: resolvedInitURL,
|
541
|
+
params: resolvedOptions.params,
|
542
|
+
query: resolvedOptions.query
|
543
|
+
});
|
544
|
+
const resolvedSchemaConfig = isFunction(extraOptions.schemaConfig) ? extraOptions.schemaConfig({ baseSchemaConfig: baseExtraOptions.schemaConfig ?? {} }) : extraOptions.schemaConfig ?? baseExtraOptions.schemaConfig;
|
545
|
+
const currentRouteKey = getCurrentRouteKey(resolvedInitURL, resolvedSchemaConfig);
|
546
|
+
const routeSchema = baseExtraOptions.schema?.[currentRouteKey];
|
547
|
+
const resolvedSchema = isFunction(extraOptions.schema) ? extraOptions.schema({
|
548
|
+
baseSchema: baseExtraOptions.schema ?? {},
|
549
|
+
currentRouteSchema: routeSchema ?? {}
|
550
|
+
}) : extraOptions.schema ?? routeSchema;
|
551
|
+
let options = {
|
552
|
+
...resolvedOptions,
|
553
|
+
...resolvedHooks,
|
554
|
+
fullURL,
|
555
|
+
initURL: resolvedInitURL,
|
556
|
+
initURLNormalized: normalizeURL(resolvedInitURL)
|
557
|
+
};
|
558
|
+
const newFetchController = new AbortController();
|
559
|
+
const timeoutSignal = options.timeout != null ? createTimeoutSignal(options.timeout) : null;
|
560
|
+
const combinedSignal = createCombinedSignal(resolvedRequestOptions.signal, timeoutSignal, newFetchController.signal);
|
561
|
+
let request = {
|
562
|
+
...resolvedRequestOptions,
|
563
|
+
signal: combinedSignal
|
564
|
+
};
|
565
|
+
const { dedupeStrategy, handleRequestCancelStrategy, handleRequestDeferStrategy, removeDedupeKeyFromCache } = await createDedupeStrategy({
|
566
|
+
$RequestInfoCache,
|
567
|
+
baseConfig,
|
568
|
+
config,
|
569
|
+
newFetchController,
|
570
|
+
options,
|
571
|
+
request
|
572
|
+
});
|
573
|
+
try {
|
574
|
+
await handleRequestCancelStrategy();
|
575
|
+
await executeHooksInTryBlock(options.onRequest?.({
|
576
|
+
baseConfig,
|
577
|
+
config,
|
578
|
+
options,
|
579
|
+
request
|
580
|
+
}));
|
581
|
+
const { extraOptionsValidationResult, requestOptionsValidationResult } = await handleOptionsValidation({
|
582
|
+
extraOptions: options,
|
583
|
+
requestOptions: request,
|
584
|
+
schema: resolvedSchema,
|
585
|
+
schemaConfig: resolvedSchemaConfig
|
586
|
+
});
|
587
|
+
const shouldApplySchemaOutput = Boolean(extraOptionsValidationResult) || Boolean(requestOptionsValidationResult) || !resolvedSchemaConfig?.disableValidationOutputApplication;
|
588
|
+
if (shouldApplySchemaOutput) options = {
|
589
|
+
...options,
|
590
|
+
...extraOptionsValidationResult
|
591
|
+
};
|
592
|
+
const validBody = getBody({
|
593
|
+
body: shouldApplySchemaOutput ? requestOptionsValidationResult?.body : request.body,
|
594
|
+
bodySerializer: options.bodySerializer
|
595
|
+
});
|
596
|
+
const validHeaders = await getHeaders({
|
597
|
+
auth: options.auth,
|
598
|
+
baseHeaders: request.headers,
|
599
|
+
body: request.body,
|
600
|
+
headers: shouldApplySchemaOutput ? requestOptionsValidationResult?.headers : request.headers
|
601
|
+
});
|
602
|
+
const validMethod = getMethod({
|
603
|
+
initURL: resolvedInitURL,
|
604
|
+
method: shouldApplySchemaOutput ? requestOptionsValidationResult?.method : request.method,
|
605
|
+
schemaConfig: resolvedSchemaConfig
|
606
|
+
});
|
607
|
+
request = {
|
608
|
+
...request,
|
609
|
+
...Boolean(validBody) && { body: validBody },
|
610
|
+
...Boolean(validHeaders) && { headers: validHeaders },
|
611
|
+
...Boolean(validMethod) && { method: validMethod }
|
612
|
+
};
|
613
|
+
const response = await handleRequestDeferStrategy(options, request);
|
614
|
+
const shouldCloneResponse = dedupeStrategy === "defer" || options.cloneResponse;
|
615
|
+
if (!response.ok) {
|
616
|
+
const errorData = await resolveResponseData(shouldCloneResponse ? response.clone() : response, options.responseType, options.responseParser);
|
617
|
+
const validErrorData = await handleValidation(resolvedSchema?.errorData, {
|
618
|
+
inputValue: errorData,
|
619
|
+
response,
|
620
|
+
schemaConfig: resolvedSchemaConfig
|
621
|
+
});
|
622
|
+
throw new HTTPError({
|
623
|
+
defaultErrorMessage: options.defaultErrorMessage,
|
624
|
+
errorData: validErrorData,
|
625
|
+
response
|
626
|
+
}, { cause: validErrorData });
|
627
|
+
}
|
628
|
+
const successData = await resolveResponseData(shouldCloneResponse ? response.clone() : response, options.responseType, options.responseParser);
|
629
|
+
const validSuccessData = await handleValidation(resolvedSchema?.data, {
|
630
|
+
inputValue: successData,
|
631
|
+
response,
|
632
|
+
schemaConfig: resolvedSchemaConfig
|
633
|
+
});
|
634
|
+
const successContext = {
|
635
|
+
baseConfig,
|
636
|
+
config,
|
637
|
+
data: validSuccessData,
|
638
|
+
options,
|
639
|
+
request,
|
640
|
+
response
|
641
|
+
};
|
642
|
+
await executeHooksInTryBlock(options.onSuccess?.(successContext), options.onResponse?.({
|
643
|
+
...successContext,
|
644
|
+
error: null
|
645
|
+
}));
|
646
|
+
const successResult = resolveSuccessResult(successContext.data, {
|
647
|
+
response: successContext.response,
|
648
|
+
resultMode: options.resultMode
|
649
|
+
});
|
650
|
+
return successResult;
|
651
|
+
} catch (error) {
|
652
|
+
const errorInfo = {
|
653
|
+
cloneResponse: options.cloneResponse,
|
654
|
+
defaultErrorMessage: options.defaultErrorMessage,
|
655
|
+
resultMode: options.resultMode
|
656
|
+
};
|
657
|
+
const generalErrorResult = resolveErrorResult(error, errorInfo);
|
658
|
+
const errorContext = {
|
659
|
+
baseConfig,
|
660
|
+
config,
|
661
|
+
error: generalErrorResult?.error,
|
662
|
+
options,
|
663
|
+
request,
|
664
|
+
response: generalErrorResult?.response
|
665
|
+
};
|
666
|
+
const shouldThrowOnError = isFunction(options.throwOnError) ? options.throwOnError(errorContext) : options.throwOnError;
|
667
|
+
const hookInfo = {
|
668
|
+
errorInfo,
|
669
|
+
shouldThrowOnError
|
670
|
+
};
|
671
|
+
const handleRetryOrGetErrorResult = async () => {
|
672
|
+
const { currentAttemptCount, getDelay, shouldAttemptRetry } = createRetryStrategy(errorContext);
|
673
|
+
const shouldRetry = !combinedSignal.aborted && await shouldAttemptRetry();
|
674
|
+
if (shouldRetry) {
|
675
|
+
const retryContext = {
|
676
|
+
...errorContext,
|
677
|
+
retryAttemptCount: currentAttemptCount
|
678
|
+
};
|
679
|
+
const hookError$1 = await executeHooksInCatchBlock([options.onRetry?.(retryContext)], hookInfo);
|
680
|
+
if (hookError$1) return hookError$1;
|
681
|
+
const delay = getDelay();
|
682
|
+
await waitFor(delay);
|
683
|
+
const updatedOptions = {
|
684
|
+
...config,
|
685
|
+
"~retryAttemptCount": currentAttemptCount + 1
|
686
|
+
};
|
687
|
+
return callApi$1(initURLOrURLObject, updatedOptions);
|
688
|
+
}
|
689
|
+
if (shouldThrowOnError) throw error;
|
690
|
+
return generalErrorResult;
|
691
|
+
};
|
692
|
+
if (isHTTPErrorInstance(error)) {
|
693
|
+
const hookError$1 = await executeHooksInCatchBlock([
|
694
|
+
options.onResponseError?.(errorContext),
|
695
|
+
options.onError?.(errorContext),
|
696
|
+
options.onResponse?.({
|
697
|
+
...errorContext,
|
698
|
+
data: null
|
699
|
+
})
|
700
|
+
], hookInfo);
|
701
|
+
return hookError$1 ?? await handleRetryOrGetErrorResult();
|
702
|
+
}
|
703
|
+
if (isValidationErrorInstance(error)) {
|
704
|
+
const hookError$1 = await executeHooksInCatchBlock([
|
705
|
+
options.onValidationError?.(errorContext),
|
706
|
+
options.onRequestError?.(errorContext),
|
707
|
+
options.onError?.(errorContext)
|
708
|
+
], hookInfo);
|
709
|
+
return hookError$1 ?? await handleRetryOrGetErrorResult();
|
710
|
+
}
|
711
|
+
let message = error?.message;
|
712
|
+
if (error instanceof DOMException && error.name === "AbortError") {
|
713
|
+
message = getAbortErrorMessage(options.dedupeKey, options.fullURL);
|
714
|
+
!shouldThrowOnError && console.error(`${error.name}:`, message);
|
715
|
+
}
|
716
|
+
if (error instanceof DOMException && error.name === "TimeoutError") {
|
717
|
+
message = `Request timed out after ${options.timeout}ms`;
|
718
|
+
!shouldThrowOnError && console.error(`${error.name}:`, message);
|
719
|
+
}
|
720
|
+
const hookError = await executeHooksInCatchBlock([options.onRequestError?.(errorContext), options.onError?.(errorContext)], hookInfo);
|
721
|
+
return hookError ?? getCustomizedErrorResult(await handleRetryOrGetErrorResult(), { message });
|
722
|
+
} finally {
|
723
|
+
removeDedupeKeyFromCache();
|
724
|
+
}
|
725
|
+
};
|
726
|
+
return callApi$1;
|
719
727
|
};
|
720
|
-
|
728
|
+
const callApi = createFetchClient();
|
721
729
|
|
722
|
-
|
723
|
-
|
724
|
-
|
730
|
+
//#endregion
|
731
|
+
//#region src/defineParameters.ts
|
732
|
+
const defineParameters = (...parameters) => {
|
733
|
+
return parameters;
|
725
734
|
};
|
726
735
|
|
727
|
-
|
728
|
-
|
736
|
+
//#endregion
|
737
|
+
export { HTTPError, ValidationError, callApi, createFetchClient, defineParameters, definePlugin, defineSchema };
|
729
738
|
//# sourceMappingURL=index.js.map
|