intelicoreact 2.0.16 → 2.0.17
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/css/accordion.css +1 -1
- package/dist/css/advanced-status.css +1 -1
- package/dist/css/datepicker.css +1 -1
- package/dist/css/dropdown-live-search.css +1 -1
- package/dist/css/dropdown.css +1 -1
- package/dist/css/input-date-range.css +1 -1
- package/dist/css/main-menu.css +1 -1
- package/dist/css/switcher-radio.css +1 -1
- package/dist/css/switcher-range-list.css +1 -1
- package/dist/css/switcher-tags-dropdown.css +1 -1
- package/dist/css/switcher-textarea.css +1 -1
- package/dist/css/table.css +1 -1
- package/dist/css/tags-dropdown.css +1 -1
- package/dist/css/wizard-stepper.css +1 -1
- package/dist/es/_virtual/_rolldown/runtime.js +27 -0
- package/dist/es/charts.js +4 -0
- package/dist/es/classes.js +4 -0
- package/dist/es/form.js +99 -0
- package/dist/es/hooks.js +32 -0
- package/dist/es/icons.js +10 -0
- package/dist/es/icons.js.map +1 -0
- package/dist/es/index.js +71 -0
- package/dist/es/layout.js +3 -0
- package/dist/es/presets.js +6 -0
- package/dist/es/router-ui.js +8 -0
- package/dist/es/sdk.js +1 -0
- package/dist/es/styles/base.css +1 -0
- package/dist/es/types/index.js +2 -0
- package/dist/es/ui.js +42 -0
- package/dist/es/utils.js +6 -0
- package/dist/intelicoreact.css +1 -1
- package/dist/scss/_mixins.scss +2 -2
- package/dist/scss/_vars.scss +1 -1
- package/dist/scss/main.scss +4 -1
- package/package.json +46 -64
- package/charts/package.json +0 -5
- package/classes/package.json +0 -5
- package/dist/charts.cjs +0 -927
- package/dist/charts.cjs.map +0 -7
- package/dist/charts.js +0 -911
- package/dist/charts.js.map +0 -7
- package/dist/classes.cjs +0 -1858
- package/dist/classes.cjs.map +0 -7
- package/dist/classes.js +0 -1836
- package/dist/classes.js.map +0 -7
- package/dist/form.cjs +0 -15167
- package/dist/form.cjs.map +0 -7
- package/dist/form.js +0 -15182
- package/dist/form.js.map +0 -7
- package/dist/hooks.cjs +0 -2330
- package/dist/hooks.cjs.map +0 -7
- package/dist/hooks.js +0 -2298
- package/dist/hooks.js.map +0 -7
- package/dist/icons.cjs +0 -1807
- package/dist/icons.cjs.map +0 -7
- package/dist/icons.js +0 -1785
- package/dist/icons.js.map +0 -7
- package/dist/index.cjs +0 -22917
- package/dist/index.cjs.map +0 -7
- package/dist/index.js +0 -22938
- package/dist/index.js.map +0 -7
- package/dist/layout.cjs +0 -458
- package/dist/layout.cjs.map +0 -7
- package/dist/layout.js +0 -426
- package/dist/layout.js.map +0 -7
- package/dist/presets.cjs +0 -262
- package/dist/presets.cjs.map +0 -7
- package/dist/presets.js +0 -240
- package/dist/presets.js.map +0 -7
- package/dist/router-ui.cjs +0 -989
- package/dist/router-ui.cjs.map +0 -7
- package/dist/router-ui.js +0 -957
- package/dist/router-ui.js.map +0 -7
- package/dist/sdk.cjs +0 -451
- package/dist/sdk.cjs.map +0 -7
- package/dist/sdk.js +0 -429
- package/dist/sdk.js.map +0 -7
- package/dist/types/index.cjs +0 -18
- package/dist/types/index.cjs.map +0 -7
- package/dist/types/index.js +0 -1
- package/dist/types/index.js.map +0 -7
- package/dist/ui.cjs +0 -4090
- package/dist/ui.cjs.map +0 -7
- package/dist/ui.js +0 -4064
- package/dist/ui.js.map +0 -7
- package/dist/utils.cjs +0 -653
- package/dist/utils.cjs.map +0 -7
- package/dist/utils.js +0 -621
- package/dist/utils.js.map +0 -7
- package/form/package.json +0 -5
- package/hooks/package.json +0 -5
- package/icons/package.json +0 -5
- package/layout/package.json +0 -5
- package/presets/package.json +0 -5
- package/router-ui/package.json +0 -5
- package/sdk/package.json +0 -5
- package/types/package.json +0 -5
- package/ui/package.json +0 -5
- package/utils/package.json +0 -5
package/dist/classes.js
DELETED
|
@@ -1,1836 +0,0 @@
|
|
|
1
|
-
// src/Classes/AbortableFetch.js
|
|
2
|
-
var RESPONSE_AS_OBJECT_ALWAYS_VALUE = "always";
|
|
3
|
-
var AbortableFetch = class {
|
|
4
|
-
#pathPrefix = null;
|
|
5
|
-
#method = null;
|
|
6
|
-
#queryParameters = null;
|
|
7
|
-
#headers = null;
|
|
8
|
-
#body = null;
|
|
9
|
-
#options = null;
|
|
10
|
-
#callback = null;
|
|
11
|
-
#catchCallback = null;
|
|
12
|
-
#everyPromiseCallback = null;
|
|
13
|
-
#isResponseAsObject = false;
|
|
14
|
-
constructor(input) {
|
|
15
|
-
if (input && (typeof input !== "object" || Array.isArray(input)))
|
|
16
|
-
throw new Error("Not valid input value!");
|
|
17
|
-
this.getPathPrefix = this.getPathPrefix.bind(this);
|
|
18
|
-
this.setPathPrefix = this.setPathPrefix.bind(this);
|
|
19
|
-
this.getMethod = this.getMethod.bind(this);
|
|
20
|
-
this.setMethod = this.setMethod.bind(this);
|
|
21
|
-
this.getQueryParameters = this.getQueryParameters.bind(this);
|
|
22
|
-
this.getQueryString = this.getQueryString.bind(this);
|
|
23
|
-
this.setQueryParameters = this.setQueryParameters.bind(this);
|
|
24
|
-
this.getHeaders = this.getHeaders.bind(this);
|
|
25
|
-
this.getHeadersObj = this.getHeadersObj.bind(this);
|
|
26
|
-
this.setHeaders = this.setHeaders.bind(this);
|
|
27
|
-
this.getBody = this.getBody.bind(this);
|
|
28
|
-
this.setBody = this.setBody.bind(this);
|
|
29
|
-
this.getOptions = this.getOptions.bind(this);
|
|
30
|
-
this.setOptions = this.setOptions.bind(this);
|
|
31
|
-
this.getCallback = this.getCallback.bind(this);
|
|
32
|
-
this.setCallback = this.setCallback.bind(this);
|
|
33
|
-
this.getCatchCallback = this.getCatchCallback.bind(this);
|
|
34
|
-
this.setCatchCallback = this.setCatchCallback.bind(this);
|
|
35
|
-
this.getEveryPromiseCallback = this.getEveryPromiseCallback.bind(this);
|
|
36
|
-
this.setEveryPromiseCallback = this.setEveryPromiseCallback.bind(this);
|
|
37
|
-
this.getIsResponseAsObject = this.getIsResponseAsObject.bind(this);
|
|
38
|
-
this.setIsResponseAsObject = this.setIsResponseAsObject.bind(this);
|
|
39
|
-
this.getProps = this.getProps.bind(this);
|
|
40
|
-
this.setProps = this.setProps.bind(this);
|
|
41
|
-
this.request = this.request.bind(this);
|
|
42
|
-
this.repeatRequest = this.repeatRequest.bind(this);
|
|
43
|
-
this.setProps(input || {});
|
|
44
|
-
}
|
|
45
|
-
request(props) {
|
|
46
|
-
if (!props || typeof props !== "object" && typeof props !== "string")
|
|
47
|
-
throw new Error("Not valid props value!");
|
|
48
|
-
const stringifyBody = (b) => b?.constructor === FormData ? b : JSON.stringify(b);
|
|
49
|
-
this.requestInput = props;
|
|
50
|
-
const requests = getRequestsArray.call(this, props);
|
|
51
|
-
if (!requests.length)
|
|
52
|
-
return Promise.reject(new Error("There are no any valid props"));
|
|
53
|
-
const abortController = new AbortController();
|
|
54
|
-
let externalRequest = Promise.all(
|
|
55
|
-
requests.map(async (item) => {
|
|
56
|
-
const safelyQuery = item.path.includes("?") ? `&${item.queryParameters.replace(/\?/g, "")}` : item.queryParameters;
|
|
57
|
-
let request = fetch(`${item.pathPrefix}${item.path}${safelyQuery}`, {
|
|
58
|
-
...item.options,
|
|
59
|
-
method: item.method,
|
|
60
|
-
headers: item.headers,
|
|
61
|
-
...item.body ? { body: stringifyBody(item.body) } : {},
|
|
62
|
-
signal: abortController.signal
|
|
63
|
-
}).then((response) => {
|
|
64
|
-
response.request = item;
|
|
65
|
-
return response;
|
|
66
|
-
}).catch(
|
|
67
|
-
(response) => {
|
|
68
|
-
return Promise.resolve({
|
|
69
|
-
ok: false,
|
|
70
|
-
status: 0,
|
|
71
|
-
statusText: response,
|
|
72
|
-
request: item
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
);
|
|
76
|
-
if (this.#everyPromiseCallback && !item.isSkipEveryPromiseCallback)
|
|
77
|
-
request = request.then(
|
|
78
|
-
(response) => this.#everyPromiseCallback(response)
|
|
79
|
-
);
|
|
80
|
-
if (item.callback)
|
|
81
|
-
request = request.then((response) => item.callback(response));
|
|
82
|
-
if (this.#isResponseAsObject)
|
|
83
|
-
request = request.then((response) => ({ name: item.name, response }));
|
|
84
|
-
return request;
|
|
85
|
-
})
|
|
86
|
-
);
|
|
87
|
-
externalRequest = externalRequest.then(
|
|
88
|
-
(response) => response.length < 2 ? response[0] : response
|
|
89
|
-
);
|
|
90
|
-
if (this.#isResponseAsObject) {
|
|
91
|
-
externalRequest = externalRequest.then((response) => {
|
|
92
|
-
if (Array.isArray(props) && props.length > 1)
|
|
93
|
-
return response.reduce(
|
|
94
|
-
(ac, item) => ({ ...ac, [item.name]: item.response }),
|
|
95
|
-
{}
|
|
96
|
-
);
|
|
97
|
-
else
|
|
98
|
-
return this.#isResponseAsObject === RESPONSE_AS_OBJECT_ALWAYS_VALUE ? { [response.name]: response.response } : response.response;
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
externalRequest = externalRequest.then(
|
|
102
|
-
(response) => this.#callback ? this.#callback(response) : response
|
|
103
|
-
);
|
|
104
|
-
externalRequest = externalRequest.catch(
|
|
105
|
-
(error) => this.#catchCallback ? this.#catchCallback(error) : error
|
|
106
|
-
);
|
|
107
|
-
externalRequest.__proto__.abort = () => abortController.abort();
|
|
108
|
-
return externalRequest;
|
|
109
|
-
function getRequestsArray(input) {
|
|
110
|
-
const requestsArray = (() => {
|
|
111
|
-
if (typeof input === "string") return [{ path: input }];
|
|
112
|
-
return Array.isArray(input) ? [...input] : [input];
|
|
113
|
-
})();
|
|
114
|
-
return requestsArray.reduce((ac, item, index) => {
|
|
115
|
-
const itemObj = typeof item === "object" && item !== null && !Array.isArray(item) ? item : {};
|
|
116
|
-
const {
|
|
117
|
-
name,
|
|
118
|
-
path,
|
|
119
|
-
method,
|
|
120
|
-
queryParameters,
|
|
121
|
-
headers,
|
|
122
|
-
body,
|
|
123
|
-
options,
|
|
124
|
-
callback,
|
|
125
|
-
mergeProps,
|
|
126
|
-
isNoPathPrefix,
|
|
127
|
-
isSkipEveryPromiseCallback
|
|
128
|
-
} = itemObj;
|
|
129
|
-
const safelyMergeProps = mergeProps instanceof Object && !Array.isArray(mergeProps) ? mergeProps : {};
|
|
130
|
-
const getMergeProps = (key) => safelyMergeProps.all ?? safelyMergeProps[key];
|
|
131
|
-
if (!path || typeof path !== "string") return ac;
|
|
132
|
-
const {
|
|
133
|
-
name: omitName,
|
|
134
|
-
path: omitPath,
|
|
135
|
-
pathPrefix: omitPathPrefix,
|
|
136
|
-
method: omitMethod,
|
|
137
|
-
queryParameters: omitQueryParameters,
|
|
138
|
-
headers: omitHeaders,
|
|
139
|
-
body: omitBody,
|
|
140
|
-
options: omitOptions,
|
|
141
|
-
callback: omitCallback,
|
|
142
|
-
mergeProps: omitMergeProps,
|
|
143
|
-
...optionsRest
|
|
144
|
-
} = options || {};
|
|
145
|
-
return [
|
|
146
|
-
...ac,
|
|
147
|
-
{
|
|
148
|
-
path,
|
|
149
|
-
pathPrefix: getMergeProps("pathPrefix") === "onlyLocal" || isNoPathPrefix ? "" : this.#pathPrefix || "",
|
|
150
|
-
method: (() => {
|
|
151
|
-
if (getMergeProps("method") === "onlyLocal")
|
|
152
|
-
return method || "GET";
|
|
153
|
-
return getMergeProps("method") === "onlyGlobal" ? this.#method || "GET" : method || this.#method || "GET";
|
|
154
|
-
})(),
|
|
155
|
-
queryParameters: (() => {
|
|
156
|
-
if ((getMergeProps("queryParameters") ?? getMergeProps("query")) === "onlyLocal") {
|
|
157
|
-
return this.getQueryString(this.getQueryArray(queryParameters));
|
|
158
|
-
}
|
|
159
|
-
return (getMergeProps("queryParameters") ?? getMergeProps("query")) === "onlyGlobal" ? this.getQueryString(this.getQueryArray(this.#queryParameters)) : this.getQueryString([
|
|
160
|
-
...this.getQueryArray(this.#queryParameters),
|
|
161
|
-
...this.getQueryArray(queryParameters)
|
|
162
|
-
]);
|
|
163
|
-
})(),
|
|
164
|
-
headers: (() => {
|
|
165
|
-
if (getMergeProps("headers") === "onlyLocal")
|
|
166
|
-
return this.getHeadersObj(headers || {});
|
|
167
|
-
return getMergeProps("headers") === "onlyGlobal" ? this.getHeadersObj({ ...this.#headers || {} }) : this.getHeadersObj({
|
|
168
|
-
...this.#headers || {},
|
|
169
|
-
...headers || {}
|
|
170
|
-
});
|
|
171
|
-
})(),
|
|
172
|
-
body: (() => {
|
|
173
|
-
if (getMergeProps("body") === "onlyLocal") return body || null;
|
|
174
|
-
if (getMergeProps("body") === "onlyGlobal")
|
|
175
|
-
return this.#body || null;
|
|
176
|
-
if (body && this.#body && typeof body === typeof this.#body && typeof body === "object") {
|
|
177
|
-
return Array.isArray(body) ? [...this.#body, ...body] : { ...this.#body, ...body };
|
|
178
|
-
} else return body || this.#body || null;
|
|
179
|
-
})(),
|
|
180
|
-
options: (() => {
|
|
181
|
-
if (getMergeProps("options") === "onlyLocal")
|
|
182
|
-
return { ...optionsRest || {} };
|
|
183
|
-
return getMergeProps("options") === "onlyGlobal" ? { ...this.#options || {} } : { ...this.#options || {}, ...optionsRest || {} };
|
|
184
|
-
})(),
|
|
185
|
-
callback,
|
|
186
|
-
isSkipEveryPromiseCallback,
|
|
187
|
-
...this.getIsResponseAsObject() ? { name: name && typeof name === "string" ? name : index } : {}
|
|
188
|
-
}
|
|
189
|
-
];
|
|
190
|
-
}, []);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
repeatRequest() {
|
|
194
|
-
return this.request(this.requestInput);
|
|
195
|
-
}
|
|
196
|
-
// ***** getters and setters *****
|
|
197
|
-
getPathPrefix() {
|
|
198
|
-
return this.#pathPrefix;
|
|
199
|
-
}
|
|
200
|
-
setPathPrefix(value) {
|
|
201
|
-
if (value && typeof value !== "string")
|
|
202
|
-
throw new Error("Not valid pathPrefix value!");
|
|
203
|
-
this.#pathPrefix = value || null;
|
|
204
|
-
}
|
|
205
|
-
getMethod() {
|
|
206
|
-
return this.#method;
|
|
207
|
-
}
|
|
208
|
-
setMethod(value) {
|
|
209
|
-
const methods = [
|
|
210
|
-
"GET",
|
|
211
|
-
"HEAD",
|
|
212
|
-
"POST",
|
|
213
|
-
"PUT",
|
|
214
|
-
"DELETE",
|
|
215
|
-
"CONNECT",
|
|
216
|
-
"OPTIONS",
|
|
217
|
-
"TRACE",
|
|
218
|
-
"PATCH"
|
|
219
|
-
];
|
|
220
|
-
if (value && !methods.includes(value))
|
|
221
|
-
throw new Error("Not valid method value!");
|
|
222
|
-
this.#method = value || null;
|
|
223
|
-
}
|
|
224
|
-
getQueryParameters() {
|
|
225
|
-
return this.#queryParameters;
|
|
226
|
-
}
|
|
227
|
-
// eslint-disable-next-line class-methods-use-this
|
|
228
|
-
getQueryArray(value) {
|
|
229
|
-
if (typeof value === "string") return value?.replace(/\?/g, "")?.split("&");
|
|
230
|
-
else if (Array.isArray(value))
|
|
231
|
-
return value.map((item) => item.replace(/\?/g, ""));
|
|
232
|
-
else if (typeof value === "object" && value !== null)
|
|
233
|
-
return Object.keys(value).filter((key) => key && value[key]).map((key) => `${key}=${value[key]}`);
|
|
234
|
-
else return [];
|
|
235
|
-
}
|
|
236
|
-
// eslint-disable-next-line class-methods-use-this
|
|
237
|
-
getQueryString(value) {
|
|
238
|
-
if (!Array.isArray(value))
|
|
239
|
-
throw new Error("Not valid query parameters value!");
|
|
240
|
-
return value.length ? `?${value.join("&")}` : "";
|
|
241
|
-
}
|
|
242
|
-
setQueryParameters(value) {
|
|
243
|
-
if (value && !Array.isArray(value))
|
|
244
|
-
throw new Error("Not valid query parameters value!");
|
|
245
|
-
this.#queryParameters = value || null;
|
|
246
|
-
}
|
|
247
|
-
getHeaders() {
|
|
248
|
-
return this.#headers;
|
|
249
|
-
}
|
|
250
|
-
// eslint-disable-next-line class-methods-use-this
|
|
251
|
-
getHeadersObj(value) {
|
|
252
|
-
const headers = new Headers();
|
|
253
|
-
if (!value) return headers;
|
|
254
|
-
if (typeof value !== "object" || Array.isArray(value))
|
|
255
|
-
throw new Error("Not valid headers value!");
|
|
256
|
-
Object.keys(value).forEach((item) => {
|
|
257
|
-
headers.append(item, value[item]);
|
|
258
|
-
});
|
|
259
|
-
return headers;
|
|
260
|
-
}
|
|
261
|
-
setHeaders(value) {
|
|
262
|
-
if (value && (typeof value !== "object" || Array.isArray(value)))
|
|
263
|
-
throw new Error("Not valid headers value!");
|
|
264
|
-
this.#headers = value || null;
|
|
265
|
-
}
|
|
266
|
-
getBody() {
|
|
267
|
-
return this.#body;
|
|
268
|
-
}
|
|
269
|
-
setBody(value) {
|
|
270
|
-
this.#body = value;
|
|
271
|
-
}
|
|
272
|
-
getOptions() {
|
|
273
|
-
return this.#options;
|
|
274
|
-
}
|
|
275
|
-
setOptions(value) {
|
|
276
|
-
if (value && (typeof value !== "object" || Array.isArray(value)))
|
|
277
|
-
throw new Error("Not valid options value!");
|
|
278
|
-
this.#options = { ...value };
|
|
279
|
-
}
|
|
280
|
-
getCallback() {
|
|
281
|
-
return this.#callback;
|
|
282
|
-
}
|
|
283
|
-
setCallback(value) {
|
|
284
|
-
if (value && typeof value !== "function")
|
|
285
|
-
throw new Error("Not valid callback value!");
|
|
286
|
-
this.#callback = value || null;
|
|
287
|
-
}
|
|
288
|
-
getCatchCallback() {
|
|
289
|
-
return this.#catchCallback;
|
|
290
|
-
}
|
|
291
|
-
setCatchCallback(value) {
|
|
292
|
-
if (value && typeof value !== "function")
|
|
293
|
-
throw new Error("Not valid callback value!");
|
|
294
|
-
this.#catchCallback = value || null;
|
|
295
|
-
}
|
|
296
|
-
getEveryPromiseCallback() {
|
|
297
|
-
return this.#everyPromiseCallback;
|
|
298
|
-
}
|
|
299
|
-
setEveryPromiseCallback(value) {
|
|
300
|
-
if (value && typeof value !== "function")
|
|
301
|
-
throw new Error("Not valid callback value!");
|
|
302
|
-
this.#everyPromiseCallback = value || null;
|
|
303
|
-
}
|
|
304
|
-
getIsResponseAsObject() {
|
|
305
|
-
return this.#isResponseAsObject;
|
|
306
|
-
}
|
|
307
|
-
setIsResponseAsObject(value) {
|
|
308
|
-
this.#isResponseAsObject = typeof value !== "boolean" && value !== "always" ? Boolean(value) : value;
|
|
309
|
-
}
|
|
310
|
-
getProps() {
|
|
311
|
-
return {
|
|
312
|
-
pathPrefix: this.getPathPrefix() || null,
|
|
313
|
-
method: this.getMethod() || null,
|
|
314
|
-
queryParameters: this.getQueryParameters() || null,
|
|
315
|
-
headers: this.getHeaders() || null,
|
|
316
|
-
body: this.getBody() || null,
|
|
317
|
-
options: this.getOptions() || null,
|
|
318
|
-
callback: this.getCallback() || null,
|
|
319
|
-
everyPromiseCallback: this.getEveryPromiseCallback(),
|
|
320
|
-
// isAnywayRunCallback: this.getIsAnywayRunCallback(),
|
|
321
|
-
isResponseAsObject: this.getIsResponseAsObject()
|
|
322
|
-
};
|
|
323
|
-
}
|
|
324
|
-
setProps(input) {
|
|
325
|
-
const {
|
|
326
|
-
pathPrefix,
|
|
327
|
-
method,
|
|
328
|
-
queryParameters,
|
|
329
|
-
headers,
|
|
330
|
-
body,
|
|
331
|
-
options,
|
|
332
|
-
callback,
|
|
333
|
-
catchCallback,
|
|
334
|
-
everyPromiseCallback,
|
|
335
|
-
// isAnywayRunCallback,
|
|
336
|
-
isResponseAsObject
|
|
337
|
-
} = input;
|
|
338
|
-
if (pathPrefix) this.setPathPrefix(pathPrefix);
|
|
339
|
-
if (method) this.setMethod(method);
|
|
340
|
-
if (queryParameters)
|
|
341
|
-
this.setQueryParameters(this.getQueryArray(queryParameters));
|
|
342
|
-
if (headers) this.setHeaders(headers);
|
|
343
|
-
if (body) this.setBody(body);
|
|
344
|
-
if (options) this.setOptions(options);
|
|
345
|
-
if (callback) this.setCallback(callback);
|
|
346
|
-
if (catchCallback) this.setCatchCallback(catchCallback);
|
|
347
|
-
if (everyPromiseCallback)
|
|
348
|
-
this.setEveryPromiseCallback(everyPromiseCallback);
|
|
349
|
-
if (isResponseAsObject !== void 0)
|
|
350
|
-
this.setIsResponseAsObject(isResponseAsObject);
|
|
351
|
-
}
|
|
352
|
-
};
|
|
353
|
-
var AbortableFetch_default = AbortableFetch;
|
|
354
|
-
|
|
355
|
-
// src/Classes/AnimatedHandler.js
|
|
356
|
-
var DEFAULT_ANIMATION_DURATION = 200;
|
|
357
|
-
var AnimatedHandler = class {
|
|
358
|
-
constructor(params) {
|
|
359
|
-
const {
|
|
360
|
-
type = "",
|
|
361
|
-
animationTarget,
|
|
362
|
-
animation,
|
|
363
|
-
settings,
|
|
364
|
-
hendler
|
|
365
|
-
} = params || {};
|
|
366
|
-
if (!animationTarget || !hendler) throw new Error("Bad input!");
|
|
367
|
-
const {
|
|
368
|
-
keyframes,
|
|
369
|
-
delay,
|
|
370
|
-
direction,
|
|
371
|
-
duration,
|
|
372
|
-
easing,
|
|
373
|
-
endDelay,
|
|
374
|
-
fill,
|
|
375
|
-
iterationStart,
|
|
376
|
-
iterations
|
|
377
|
-
} = animation || {};
|
|
378
|
-
return function(...args) {
|
|
379
|
-
const keyframesToUse = Array.isArray(keyframes) ? keyframes : [
|
|
380
|
-
{ height: `${animationTarget.clientHeight}px`, opacity: 1 },
|
|
381
|
-
{ height: "0", opacity: 0 }
|
|
382
|
-
];
|
|
383
|
-
const durationToUse = duration || DEFAULT_ANIMATION_DURATION;
|
|
384
|
-
animationTarget.animate(keyframesToUse, animation);
|
|
385
|
-
return new Promise((res) => {
|
|
386
|
-
setTimeout(
|
|
387
|
-
() => res(hendler ? hendler(...args) : void 0),
|
|
388
|
-
durationToUse
|
|
389
|
-
);
|
|
390
|
-
});
|
|
391
|
-
};
|
|
392
|
-
}
|
|
393
|
-
};
|
|
394
|
-
var AnimatedHandler_default = AnimatedHandler;
|
|
395
|
-
|
|
396
|
-
// src/Classes/RESTAPI/partials/AbortableFetch.ts
|
|
397
|
-
var HTTP_METHODS = ["GET", "HEAD", "POST", "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE", "PATCH"];
|
|
398
|
-
function isHttpMethod(value) {
|
|
399
|
-
return HTTP_METHODS.includes(value);
|
|
400
|
-
}
|
|
401
|
-
var RESPONSE_AS_OBJECT_ALWAYS_VALUE2 = "always";
|
|
402
|
-
var AbortableFetch2 = class {
|
|
403
|
-
#pathPrefix = null;
|
|
404
|
-
#method = null;
|
|
405
|
-
#queryParameters = null;
|
|
406
|
-
#headers = null;
|
|
407
|
-
#body = null;
|
|
408
|
-
#options = null;
|
|
409
|
-
#callback = null;
|
|
410
|
-
#catchCallback = null;
|
|
411
|
-
#everyPromiseCallback = null;
|
|
412
|
-
#isResponseAsObject = false;
|
|
413
|
-
// ? Последний вход request() — используется repeatRequest() для повторного запроса той же пачки.
|
|
414
|
-
requestInput = [];
|
|
415
|
-
constructor(input) {
|
|
416
|
-
if (input && !getIsOnlyAnObject(input)) throw new Error("Not valid input value!");
|
|
417
|
-
this.getPathPrefix = this.getPathPrefix.bind(this);
|
|
418
|
-
this.setPathPrefix = this.setPathPrefix.bind(this);
|
|
419
|
-
this.getMethod = this.getMethod.bind(this);
|
|
420
|
-
this.setMethod = this.setMethod.bind(this);
|
|
421
|
-
this.getQueryParameters = this.getQueryParameters.bind(this);
|
|
422
|
-
this.getQueryString = this.getQueryString.bind(this);
|
|
423
|
-
this.setQueryParameters = this.setQueryParameters.bind(this);
|
|
424
|
-
this.getHeaders = this.getHeaders.bind(this);
|
|
425
|
-
this.getHeadersObj = this.getHeadersObj.bind(this);
|
|
426
|
-
this.setHeaders = this.setHeaders.bind(this);
|
|
427
|
-
this.getBody = this.getBody.bind(this);
|
|
428
|
-
this.setBody = this.setBody.bind(this);
|
|
429
|
-
this.getOptions = this.getOptions.bind(this);
|
|
430
|
-
this.setOptions = this.setOptions.bind(this);
|
|
431
|
-
this.getCallback = this.getCallback.bind(this);
|
|
432
|
-
this.setCallback = this.setCallback.bind(this);
|
|
433
|
-
this.getCatchCallback = this.getCatchCallback.bind(this);
|
|
434
|
-
this.setCatchCallback = this.setCatchCallback.bind(this);
|
|
435
|
-
this.getEveryPromiseCallback = this.getEveryPromiseCallback.bind(this);
|
|
436
|
-
this.setEveryPromiseCallback = this.setEveryPromiseCallback.bind(this);
|
|
437
|
-
this.getIsResponseAsObject = this.getIsResponseAsObject.bind(this);
|
|
438
|
-
this.setIsResponseAsObject = this.setIsResponseAsObject.bind(this);
|
|
439
|
-
this.getProps = this.getProps.bind(this);
|
|
440
|
-
this.setProps = this.setProps.bind(this);
|
|
441
|
-
this.request = this.request.bind(this);
|
|
442
|
-
this.repeatRequest = this.repeatRequest.bind(this);
|
|
443
|
-
this.setProps(input || {});
|
|
444
|
-
}
|
|
445
|
-
/**
|
|
446
|
-
* Выполняет один или несколько HTTP-запросов (нативный fetch) с возможностью отмены.
|
|
447
|
-
*
|
|
448
|
-
* Метод `abort()` навешивается на прототип возвращаемого промиса (как в исходной реализации),
|
|
449
|
-
* что позволяет отменить всю цепочку запросов вызовом `abort()` на возвращённом промисе.
|
|
450
|
-
*
|
|
451
|
-
* @param props - путь, объект описания запроса или их массив.
|
|
452
|
-
* @returns Промис с результатом (форма зависит от isResponseAsObject); на прототипе доступен `abort()`.
|
|
453
|
-
*/
|
|
454
|
-
async request(props) {
|
|
455
|
-
if (!getIsOnlyAnObject(props) && !Array.isArray(props) && typeof props !== "string") throw new Error("Not valid props value!");
|
|
456
|
-
const stringifyBody = (b) => b instanceof FormData ? b : JSON.stringify(b);
|
|
457
|
-
this.requestInput = props;
|
|
458
|
-
const requests = getRequestsArray.call(this, props);
|
|
459
|
-
const ABORTABLE_FETCH_CONTEXT = this;
|
|
460
|
-
const abortController = new AbortController();
|
|
461
|
-
const addProps = (response, request) => {
|
|
462
|
-
return Object.assign(response, {
|
|
463
|
-
request,
|
|
464
|
-
...ABORTABLE_FETCH_CONTEXT.#isResponseAsObject ? { name: getIsOnlyAnObject(request) ? request.name || "" : "" } : {}
|
|
465
|
-
});
|
|
466
|
-
};
|
|
467
|
-
const externalRequest = Promise.all(
|
|
468
|
-
requests.map((item) => {
|
|
469
|
-
const safelyQuery = item.path.includes("?") ? `&${item.queryParameters.replace(/\?/g, "")}` : item.queryParameters;
|
|
470
|
-
const internalRequest = fetch(`${item.pathPrefix}${item.path}${safelyQuery}`, {
|
|
471
|
-
...item.options,
|
|
472
|
-
method: item.method,
|
|
473
|
-
headers: item.headers,
|
|
474
|
-
...item.body ? { body: stringifyBody(item.body) } : {},
|
|
475
|
-
signal: abortController.signal
|
|
476
|
-
}).then(async (response) => addProps(response, item)).catch(async (response) => {
|
|
477
|
-
if (response instanceof Response) return Promise.resolve(addProps(response, item));
|
|
478
|
-
return Promise.resolve(
|
|
479
|
-
addProps(
|
|
480
|
-
{
|
|
481
|
-
ok: false,
|
|
482
|
-
status: 0,
|
|
483
|
-
statusText: response,
|
|
484
|
-
request: item
|
|
485
|
-
},
|
|
486
|
-
item
|
|
487
|
-
)
|
|
488
|
-
);
|
|
489
|
-
}).then(async (res) => {
|
|
490
|
-
return typeof ABORTABLE_FETCH_CONTEXT.#everyPromiseCallback === "function" && !item.isSkipEveryPromiseCallback ? await ABORTABLE_FETCH_CONTEXT.#everyPromiseCallback(res) : res;
|
|
491
|
-
}).then(async (res) => {
|
|
492
|
-
return await (typeof item.callback === "function" ? item.callback(res) : res);
|
|
493
|
-
}).then(async (res) => {
|
|
494
|
-
return { request: item, response: res, ...item.name ? { name: item.name } : {} };
|
|
495
|
-
});
|
|
496
|
-
const internalProto = Object.getPrototypeOf(internalRequest);
|
|
497
|
-
internalProto.abort = () => abortController.abort();
|
|
498
|
-
return internalRequest;
|
|
499
|
-
})
|
|
500
|
-
).then(async (resArr) => {
|
|
501
|
-
if (resArr.length < 1) {
|
|
502
|
-
return ABORTABLE_FETCH_CONTEXT.#isResponseAsObject ? {} : [];
|
|
503
|
-
}
|
|
504
|
-
if (ABORTABLE_FETCH_CONTEXT.#isResponseAsObject === RESPONSE_AS_OBJECT_ALWAYS_VALUE2) {
|
|
505
|
-
return resArr.reduce((ac, item) => ({ ...ac, [String(item.name)]: item.response }), {});
|
|
506
|
-
}
|
|
507
|
-
if (resArr.length === 1) return resArr[0].response;
|
|
508
|
-
return ABORTABLE_FETCH_CONTEXT.#isResponseAsObject === true ? resArr.reduce((ac, item) => ({ ...ac, [String(item.name)]: item.response }), {}) : resArr.map((item) => item.response);
|
|
509
|
-
}).then(async (res) => {
|
|
510
|
-
return typeof ABORTABLE_FETCH_CONTEXT.#callback === "function" ? await ABORTABLE_FETCH_CONTEXT.#callback(res) : res;
|
|
511
|
-
}).catch(async (res) => {
|
|
512
|
-
return typeof ABORTABLE_FETCH_CONTEXT.#catchCallback === "function" ? await ABORTABLE_FETCH_CONTEXT.#catchCallback(res) : res;
|
|
513
|
-
});
|
|
514
|
-
const externalProto = Object.getPrototypeOf(externalRequest);
|
|
515
|
-
externalProto.abort = () => abortController.abort();
|
|
516
|
-
return externalRequest;
|
|
517
|
-
function getRequestsArray(input) {
|
|
518
|
-
const requestsArray = (() => {
|
|
519
|
-
if (typeof input === "string") return [{ path: input }];
|
|
520
|
-
return Array.isArray(input) ? [...input] : [input];
|
|
521
|
-
})();
|
|
522
|
-
return requestsArray.reduce((ac, item, index) => {
|
|
523
|
-
const itemObj = getIsOnlyAnObject(item) ? item : {};
|
|
524
|
-
const { name, path, method, queryParameters, headers, body, options, callback, mergeProps, isNoPathPrefix, isSkipEveryPromiseCallback } = itemObj;
|
|
525
|
-
const safelyMergeProps = getIsOnlyAnObject(mergeProps) ? mergeProps : {};
|
|
526
|
-
const getMergeProps = (key) => safelyMergeProps.all ?? safelyMergeProps[key];
|
|
527
|
-
if (!path || typeof path !== "string") return ac;
|
|
528
|
-
const {
|
|
529
|
-
name: omitName,
|
|
530
|
-
path: omitPath,
|
|
531
|
-
pathPrefix: omitPathPrefix,
|
|
532
|
-
method: omitMethod,
|
|
533
|
-
queryParameters: omitQueryParameters,
|
|
534
|
-
headers: omitHeaders,
|
|
535
|
-
body: omitBody,
|
|
536
|
-
options: omitOptions,
|
|
537
|
-
callback: omitCallback,
|
|
538
|
-
mergeProps: omitMergeProps,
|
|
539
|
-
...optionsRest
|
|
540
|
-
} = getIsOnlyAnObject(options) ? options : {};
|
|
541
|
-
const localMethod = typeof method === "string" && isHttpMethod(method) ? method : null;
|
|
542
|
-
const localCallback = typeof callback === "function" ? (res) => callback(res) : void 0;
|
|
543
|
-
return [
|
|
544
|
-
...ac,
|
|
545
|
-
{
|
|
546
|
-
path,
|
|
547
|
-
pathPrefix: getMergeProps("pathPrefix") === "onlyLocal" || isNoPathPrefix ? "" : this.#pathPrefix || "",
|
|
548
|
-
method: (() => {
|
|
549
|
-
if (getMergeProps("method") === "onlyLocal") return localMethod || "GET";
|
|
550
|
-
return getMergeProps("method") === "onlyGlobal" ? this.#method || "GET" : localMethod || this.#method || "GET";
|
|
551
|
-
})(),
|
|
552
|
-
queryParameters: (() => {
|
|
553
|
-
if ((getMergeProps("queryParameters") ?? getMergeProps("query")) === "onlyLocal") {
|
|
554
|
-
return this.getQueryString(this.getQueryArray(queryParameters));
|
|
555
|
-
}
|
|
556
|
-
return (getMergeProps("queryParameters") ?? getMergeProps("query")) === "onlyGlobal" ? this.getQueryString(this.getQueryArray(this.#queryParameters)) : this.getQueryString([...this.getQueryArray(this.#queryParameters), ...this.getQueryArray(queryParameters)]);
|
|
557
|
-
})(),
|
|
558
|
-
headers: (() => {
|
|
559
|
-
if (getMergeProps("headers") === "onlyLocal") return this.getHeadersObj(getIsOnlyAnObject(headers) ? headers : {});
|
|
560
|
-
return getMergeProps("headers") === "onlyGlobal" ? this.getHeadersObj({ ...this.#headers || {} }) : this.getHeadersObj({
|
|
561
|
-
...this.#headers || {},
|
|
562
|
-
...getIsOnlyAnObject(headers) ? headers : {}
|
|
563
|
-
});
|
|
564
|
-
})(),
|
|
565
|
-
body: (() => {
|
|
566
|
-
if (getMergeProps("body") === "onlyLocal") return body || null;
|
|
567
|
-
if (getMergeProps("body") === "onlyGlobal") return this.#body || null;
|
|
568
|
-
if (body && this.#body && typeof body === typeof this.#body && typeof body === "object") {
|
|
569
|
-
return Array.isArray(body) ? [...Array.isArray(this.#body) ? this.#body : [], ...body] : { ...getIsOnlyAnObject(this.#body) ? this.#body : {}, ...getIsOnlyAnObject(body) ? body : {} };
|
|
570
|
-
} else {
|
|
571
|
-
return body || this.#body || null;
|
|
572
|
-
}
|
|
573
|
-
})(),
|
|
574
|
-
options: (() => {
|
|
575
|
-
if (getMergeProps("options") === "onlyLocal") return { ...optionsRest };
|
|
576
|
-
return getMergeProps("options") === "onlyGlobal" ? { ...this.#options || {} } : { ...this.#options || {}, ...optionsRest };
|
|
577
|
-
})(),
|
|
578
|
-
callback: localCallback,
|
|
579
|
-
isSkipEveryPromiseCallback: Boolean(isSkipEveryPromiseCallback),
|
|
580
|
-
...this.getIsResponseAsObject() ? { name: name && typeof name === "string" ? name : index } : {}
|
|
581
|
-
}
|
|
582
|
-
];
|
|
583
|
-
}, []);
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
/** Повторяет последний выполненный запрос (ту же пачку). */
|
|
587
|
-
repeatRequest() {
|
|
588
|
-
return this.request(this.requestInput);
|
|
589
|
-
}
|
|
590
|
-
// ***** getters and setters *****
|
|
591
|
-
getPathPrefix() {
|
|
592
|
-
return this.#pathPrefix;
|
|
593
|
-
}
|
|
594
|
-
setPathPrefix(value) {
|
|
595
|
-
if (value && typeof value !== "string") throw new Error("Not valid pathPrefix value!");
|
|
596
|
-
this.#pathPrefix = value || null;
|
|
597
|
-
}
|
|
598
|
-
getMethod() {
|
|
599
|
-
return this.#method;
|
|
600
|
-
}
|
|
601
|
-
setMethod(value) {
|
|
602
|
-
if (value && !isHttpMethod(value)) throw new Error("Not valid method value!");
|
|
603
|
-
this.#method = value || null;
|
|
604
|
-
}
|
|
605
|
-
getQueryParameters() {
|
|
606
|
-
return this.#queryParameters;
|
|
607
|
-
}
|
|
608
|
-
getQueryArray(value) {
|
|
609
|
-
if (typeof value === "string") {
|
|
610
|
-
return (value[0] === "?" ? value.slice(1) : value).split("&");
|
|
611
|
-
} else if (Array.isArray(value)) {
|
|
612
|
-
return value.map((item) => `${item}`);
|
|
613
|
-
} else if (typeof value === "object" && value !== null) {
|
|
614
|
-
const record = getIsOnlyAnObject(value) ? value : {};
|
|
615
|
-
return Object.keys(record).filter((key) => Boolean(key) && Boolean(record[key])).map((key) => `${key}=${record[key]}`);
|
|
616
|
-
} else {
|
|
617
|
-
return [];
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
getQueryString(value) {
|
|
621
|
-
if (!value) return "";
|
|
622
|
-
if (!Array.isArray(value)) throw new Error("Not valid query parameters value!");
|
|
623
|
-
return value.length ? `?${value.join("&")}` : "";
|
|
624
|
-
}
|
|
625
|
-
setQueryParameters(value) {
|
|
626
|
-
if (value && !Array.isArray(value)) throw new Error("Not valid query parameters value!");
|
|
627
|
-
this.#queryParameters = value || null;
|
|
628
|
-
}
|
|
629
|
-
getHeaders() {
|
|
630
|
-
return this.#headers;
|
|
631
|
-
}
|
|
632
|
-
getHeadersObj(obj) {
|
|
633
|
-
const headers = new Headers();
|
|
634
|
-
if (!obj) return headers;
|
|
635
|
-
if (typeof obj !== "object" || Array.isArray(obj)) throw new Error("Not valid headers value!");
|
|
636
|
-
Object.keys(obj).forEach((key) => {
|
|
637
|
-
headers.append(key, `${obj[key]}`);
|
|
638
|
-
});
|
|
639
|
-
return headers;
|
|
640
|
-
}
|
|
641
|
-
setHeaders(value) {
|
|
642
|
-
if (value && (typeof value !== "object" || Array.isArray(value))) throw new Error("Not valid headers value!");
|
|
643
|
-
this.#headers = value || null;
|
|
644
|
-
}
|
|
645
|
-
getBody() {
|
|
646
|
-
return this.#body;
|
|
647
|
-
}
|
|
648
|
-
setBody(value) {
|
|
649
|
-
this.#body = value;
|
|
650
|
-
}
|
|
651
|
-
getOptions() {
|
|
652
|
-
return this.#options;
|
|
653
|
-
}
|
|
654
|
-
setOptions(value) {
|
|
655
|
-
if (value && (typeof value !== "object" || Array.isArray(value))) throw new Error("Not valid options value!");
|
|
656
|
-
this.#options = { ...value };
|
|
657
|
-
}
|
|
658
|
-
getCallback() {
|
|
659
|
-
return this.#callback;
|
|
660
|
-
}
|
|
661
|
-
setCallback(value) {
|
|
662
|
-
if (value && typeof value !== "function") throw new Error("Not valid callback value!");
|
|
663
|
-
this.#callback = value || null;
|
|
664
|
-
}
|
|
665
|
-
getCatchCallback() {
|
|
666
|
-
return this.#catchCallback;
|
|
667
|
-
}
|
|
668
|
-
setCatchCallback(value) {
|
|
669
|
-
if (value && typeof value !== "function") throw new Error("Not valid callback value!");
|
|
670
|
-
this.#catchCallback = value || null;
|
|
671
|
-
}
|
|
672
|
-
getEveryPromiseCallback() {
|
|
673
|
-
return this.#everyPromiseCallback;
|
|
674
|
-
}
|
|
675
|
-
setEveryPromiseCallback(value) {
|
|
676
|
-
if (value && typeof value !== "function") throw new Error("Not valid callback value!");
|
|
677
|
-
this.#everyPromiseCallback = value || null;
|
|
678
|
-
}
|
|
679
|
-
getIsResponseAsObject() {
|
|
680
|
-
return this.#isResponseAsObject;
|
|
681
|
-
}
|
|
682
|
-
setIsResponseAsObject(value) {
|
|
683
|
-
this.#isResponseAsObject = typeof value !== "boolean" && value !== "always" ? Boolean(value) : value;
|
|
684
|
-
}
|
|
685
|
-
getProps() {
|
|
686
|
-
return {
|
|
687
|
-
pathPrefix: this.getPathPrefix() || null,
|
|
688
|
-
method: this.getMethod() || null,
|
|
689
|
-
queryParameters: this.getQueryParameters() || null,
|
|
690
|
-
headers: this.getHeaders() || null,
|
|
691
|
-
body: this.getBody() || null,
|
|
692
|
-
options: this.getOptions() || null,
|
|
693
|
-
callback: this.getCallback() || null,
|
|
694
|
-
everyPromiseCallback: this.getEveryPromiseCallback(),
|
|
695
|
-
// isAnywayRunCallback: this.getIsAnywayRunCallback(),
|
|
696
|
-
isResponseAsObject: this.getIsResponseAsObject()
|
|
697
|
-
};
|
|
698
|
-
}
|
|
699
|
-
setProps(input) {
|
|
700
|
-
const {
|
|
701
|
-
pathPrefix,
|
|
702
|
-
method,
|
|
703
|
-
queryParameters,
|
|
704
|
-
headers,
|
|
705
|
-
body,
|
|
706
|
-
options,
|
|
707
|
-
callback,
|
|
708
|
-
catchCallback,
|
|
709
|
-
everyPromiseCallback,
|
|
710
|
-
// isAnywayRunCallback,
|
|
711
|
-
isResponseAsObject
|
|
712
|
-
} = input;
|
|
713
|
-
if (pathPrefix) this.setPathPrefix(typeof pathPrefix === "string" ? pathPrefix : null);
|
|
714
|
-
if (method) this.setMethod(typeof method === "string" && isHttpMethod(method) ? method : null);
|
|
715
|
-
if (queryParameters) this.setQueryParameters(this.getQueryArray(queryParameters));
|
|
716
|
-
if (headers) this.setHeaders(getIsOnlyAnObject(headers) ? headers : null);
|
|
717
|
-
if (body) this.setBody(body);
|
|
718
|
-
if (options) this.setOptions(getIsOnlyAnObject(options) ? options : null);
|
|
719
|
-
if (callback && typeof callback === "function") {
|
|
720
|
-
const fn = callback;
|
|
721
|
-
this.setCallback(function wrappedCallback(response) {
|
|
722
|
-
return fn.call(this, response);
|
|
723
|
-
});
|
|
724
|
-
}
|
|
725
|
-
if (catchCallback && typeof catchCallback === "function") {
|
|
726
|
-
const fn = catchCallback;
|
|
727
|
-
this.setCatchCallback(function wrappedCatchCallback(response) {
|
|
728
|
-
return fn.call(this, response);
|
|
729
|
-
});
|
|
730
|
-
}
|
|
731
|
-
if (everyPromiseCallback && typeof everyPromiseCallback === "function") {
|
|
732
|
-
const fn = everyPromiseCallback;
|
|
733
|
-
this.setEveryPromiseCallback(function wrappedEveryPromiseCallback(response) {
|
|
734
|
-
return fn.call(this, response);
|
|
735
|
-
});
|
|
736
|
-
}
|
|
737
|
-
if (isResponseAsObject !== void 0) this.setIsResponseAsObject(isResponseAsObject);
|
|
738
|
-
}
|
|
739
|
-
};
|
|
740
|
-
var AbortableFetch_default2 = AbortableFetch2;
|
|
741
|
-
|
|
742
|
-
// src/Classes/RESTAPI/partials/_utils.ts
|
|
743
|
-
function getIsOnlyAnObject(input) {
|
|
744
|
-
return typeof input === "object" && input instanceof Object && !Array.isArray(input) && !(input instanceof Set) && !(input instanceof Map);
|
|
745
|
-
}
|
|
746
|
-
function clone(input) {
|
|
747
|
-
if (input === null || typeof input !== "object") return input;
|
|
748
|
-
if (Array.isArray(input)) return input.map((item) => clone(item));
|
|
749
|
-
const source = getIsOnlyAnObject(input) ? input : {};
|
|
750
|
-
const data = {};
|
|
751
|
-
Object.keys(source).forEach((key) => {
|
|
752
|
-
data[key] = clone(source[key]);
|
|
753
|
-
});
|
|
754
|
-
return data;
|
|
755
|
-
}
|
|
756
|
-
function omitKeys(obj, keys = []) {
|
|
757
|
-
const source = obj ?? {};
|
|
758
|
-
const keySet = new Set(keys);
|
|
759
|
-
const result = {};
|
|
760
|
-
Object.keys(source).forEach((key) => {
|
|
761
|
-
if (!keySet.has(key)) result[key] = source[key];
|
|
762
|
-
});
|
|
763
|
-
return result;
|
|
764
|
-
}
|
|
765
|
-
async function getResponseClone(res) {
|
|
766
|
-
if (res && typeof res === "object" && "clone" in res && typeof res.clone === "function") {
|
|
767
|
-
return res.clone();
|
|
768
|
-
}
|
|
769
|
-
return clone(res);
|
|
770
|
-
}
|
|
771
|
-
function addCustomMethods(data, prefix) {
|
|
772
|
-
const preparedPrefix = (prefix || "").toString();
|
|
773
|
-
Object.keys(data).forEach((key) => {
|
|
774
|
-
const preparedKey = `${preparedPrefix}${key}`;
|
|
775
|
-
if (typeof data[key] === "function" && getIsOnlyAnObject(this)) this[preparedKey] = data[key];
|
|
776
|
-
});
|
|
777
|
-
}
|
|
778
|
-
async function getInstanceOfFetchSystem(isGetBody) {
|
|
779
|
-
const API_CONTEXT = this;
|
|
780
|
-
const CREDENTIALS_CONTEXT = API_CONTEXT.credentialsProcessing;
|
|
781
|
-
let credentials = {};
|
|
782
|
-
if (CREDENTIALS_CONTEXT) {
|
|
783
|
-
const cred = await CREDENTIALS_CONTEXT.getCredentials();
|
|
784
|
-
credentials = CREDENTIALS_CONTEXT.isUseRefreshTokensPropcessing ? await CREDENTIALS_CONTEXT.waitRefresh(Boolean(cred.isNeedRefresh) && !CREDENTIALS_CONTEXT.getIsTokenStartRefresh()).then(
|
|
785
|
-
async () => CREDENTIALS_CONTEXT.processCredentials(await CREDENTIALS_CONTEXT.getCredentials())
|
|
786
|
-
) : cred;
|
|
787
|
-
}
|
|
788
|
-
if (credentials.isRefreshFailed) return null;
|
|
789
|
-
if (API_CONTEXT.addAsCommon && typeof API_CONTEXT.addAsCommon !== "function") {
|
|
790
|
-
throw new Error("addAsCommon must be function [getInstanceOfFetchSystem]");
|
|
791
|
-
}
|
|
792
|
-
const {
|
|
793
|
-
headers: headersToAbortableFetchInstance,
|
|
794
|
-
queryParameters: queryParamsToAbortableFetchInstance,
|
|
795
|
-
options: optionsToAbortableFetchInstance
|
|
796
|
-
} = await API_CONTEXT.addAsCommon?.() || {};
|
|
797
|
-
if (headersToAbortableFetchInstance && !getIsOnlyAnObject(headersToAbortableFetchInstance) || optionsToAbortableFetchInstance && !getIsOnlyAnObject(optionsToAbortableFetchInstance) || queryParamsToAbortableFetchInstance && !(typeof queryParamsToAbortableFetchInstance === "string" || getIsOnlyAnObject(queryParamsToAbortableFetchInstance) || Array.isArray(queryParamsToAbortableFetchInstance))) {
|
|
798
|
-
throw new Error("Bad output format from addAsCommon [getInstanceOfFetchSystem]");
|
|
799
|
-
}
|
|
800
|
-
return (CREDENTIALS_CONTEXT?.isUseRefreshTokensPropcessing ? CREDENTIALS_CONTEXT.waitRefresh() : Promise.resolve()).then(
|
|
801
|
-
async () => new AbortableFetch_default2({
|
|
802
|
-
// ? Метод по умолчанию
|
|
803
|
-
method: "GET",
|
|
804
|
-
// ? Заголовки по умолчанию
|
|
805
|
-
headers: {
|
|
806
|
-
...headersToAbortableFetchInstance,
|
|
807
|
-
// ? (*) Тут обрабатываются кейсы
|
|
808
|
-
// ? - когда нет this.credentialsProcessing
|
|
809
|
-
// ? (мы НЕ хотим добавлять токены в принципе, не зашли в верхнюю if-ку)
|
|
810
|
-
// ? - когда есть this.credentialsProcessing, но нет credentials.token (не авторизованы)
|
|
811
|
-
// ? (зашли в верхнюю if-ку, попробовали получить/обновить креды)
|
|
812
|
-
...credentials.token ? CREDENTIALS_CONTEXT?.getHeadersForAuthorize?.(credentials.token) || {} : {}
|
|
813
|
-
},
|
|
814
|
-
queryParameters: await API_CONTEXT.processQueryParams(queryParamsToAbortableFetchInstance),
|
|
815
|
-
// ? Опции по умолчанию
|
|
816
|
-
options: {
|
|
817
|
-
mode: "cors",
|
|
818
|
-
redirect: "follow",
|
|
819
|
-
...optionsToAbortableFetchInstance
|
|
820
|
-
},
|
|
821
|
-
// ? Каждый запрос (каждый запрос мультизапроса), сделаный методом request этого экземпляра выполнит этот колбек
|
|
822
|
-
everyPromiseCallback: async function everyPromiseCallback(response) {
|
|
823
|
-
const ABORTABLE_FETCH_INSTANCE = this;
|
|
824
|
-
if (!response.status) {
|
|
825
|
-
const reqInput = ABORTABLE_FETCH_INSTANCE.requestInput;
|
|
826
|
-
const responseRequest = getIsOnlyAnObject(response.request) ? response.request : {};
|
|
827
|
-
const request = Array.isArray(reqInput) ? reqInput.find((item) => getIsOnlyAnObject(item) && item.path === responseRequest.path) : void 0;
|
|
828
|
-
const mesageOptions = getIsOnlyAnObject(request) && getIsOnlyAnObject(request.mesageOptions) ? request.mesageOptions : void 0;
|
|
829
|
-
const isUseErrorToast = mesageOptions?.isUseErrorToast;
|
|
830
|
-
if (isUseErrorToast) {
|
|
831
|
-
API_CONTEXT.sendMessage?.(API_CONTEXT.NO_INET, mesageOptions, response);
|
|
832
|
-
}
|
|
833
|
-
}
|
|
834
|
-
return API_CONTEXT.REJECT_CODES.includes(Number(response.status)) || CREDENTIALS_CONTEXT?.isUseRefreshTokensPropcessing && Boolean(CREDENTIALS_CONTEXT?.CODES_USING_THE_REFRESH_ATTEMPT?.includes(Number(response.status))) ? Promise.reject(new Error(`status:${Number(response.status)}`)) : Promise.resolve(!isGetBody ? response : await API_CONTEXT.getResponseBody(response));
|
|
835
|
-
},
|
|
836
|
-
// ? Если хоть один запрос из пачки будет зареджекчен, зареджектится вся пачка.
|
|
837
|
-
// ? В этом случае будет выполнен этот колбэк
|
|
838
|
-
catchCallback: async function catchCallback(res) {
|
|
839
|
-
const ABORTABLE_FETCH_INSTANCE = this;
|
|
840
|
-
if (!CREDENTIALS_CONTEXT) return Promise.reject(res);
|
|
841
|
-
const code = Number(res instanceof Error ? res.message.split(":")[1] : "");
|
|
842
|
-
if (CREDENTIALS_CONTEXT.CODES_USING_THE_REFRESH_ATTEMPT?.includes(code)) {
|
|
843
|
-
const isDoRefresh = !CREDENTIALS_CONTEXT.getIsTokenStartRefresh();
|
|
844
|
-
return CREDENTIALS_CONTEXT.waitRefresh(isDoRefresh).then(async () => {
|
|
845
|
-
const newCredentials = await CREDENTIALS_CONTEXT.processCredentials({
|
|
846
|
-
...await CREDENTIALS_CONTEXT.getCredentials(true),
|
|
847
|
-
isCatchCallbackProcess: isDoRefresh
|
|
848
|
-
});
|
|
849
|
-
const currentHeaders = ABORTABLE_FETCH_INSTANCE.getHeaders();
|
|
850
|
-
ABORTABLE_FETCH_INSTANCE.setHeaders({
|
|
851
|
-
...getIsOnlyAnObject(currentHeaders) ? currentHeaders : {},
|
|
852
|
-
...newCredentials.token ? { Authorization: `Bearer ${newCredentials.token}` } : {}
|
|
853
|
-
});
|
|
854
|
-
if (newCredentials.token) return ABORTABLE_FETCH_INSTANCE.repeatRequest();
|
|
855
|
-
return Promise.reject(res);
|
|
856
|
-
});
|
|
857
|
-
}
|
|
858
|
-
return Promise.reject(res);
|
|
859
|
-
}
|
|
860
|
-
})
|
|
861
|
-
);
|
|
862
|
-
}
|
|
863
|
-
|
|
864
|
-
// src/Classes/RESTAPI/partials/Utils.ts
|
|
865
|
-
var Utils = class {
|
|
866
|
-
// ! Могут содержаться НЕасинхронные методы!
|
|
867
|
-
/**
|
|
868
|
-
* Нормализатор сложных query-параметров.
|
|
869
|
-
*
|
|
870
|
-
* Например: `&key1=&&&===&&&key2====&&&&&&&&key3=...`. Для корректной работы на вход нужно подавать
|
|
871
|
-
* НЕ кодированные значения. По умолчанию выходные значения query-параметров НЕ кодируются.
|
|
872
|
-
*
|
|
873
|
-
* @param queryParams - query в виде строки, массива или объекта.
|
|
874
|
-
* @param settings - формат вывода (`array` | `string` | `object`) и флаг кодирования.
|
|
875
|
-
* @returns Нормализованные query-параметры в выбранном формате.
|
|
876
|
-
*/
|
|
877
|
-
// ? Ф-я normalizeQueryParams является нормализатором сложных квери
|
|
878
|
-
// ? Например: &key1=&&&===&&&key2====&&&&&&&&key3=....
|
|
879
|
-
// ? Для корректной работы на вход нужно подавать НЕ кодированные значения
|
|
880
|
-
// ? По умолчанию выходные значения квери-параметров НЕ кодируются
|
|
881
|
-
normalizeQueryParams(queryParams, settings) {
|
|
882
|
-
if (settings && !getIsOnlyAnObject(settings)) {
|
|
883
|
-
throw new Error("Bad settings [class Utils, normalizeQueryParams]");
|
|
884
|
-
}
|
|
885
|
-
const getInitialArr = (input) => {
|
|
886
|
-
const prepareParam = (key, value) => {
|
|
887
|
-
if (!value) return `${key}=`;
|
|
888
|
-
else if (typeof value === "string" || typeof value === "number") return `${key}=${value}`;
|
|
889
|
-
else if (Array.isArray(value)) return `${key}=${value.join("")}`;
|
|
890
|
-
else return `${key}=Bad-data-format`;
|
|
891
|
-
};
|
|
892
|
-
if (Array.isArray(input)) {
|
|
893
|
-
return input.map((item) => {
|
|
894
|
-
if (typeof item !== "string") return [];
|
|
895
|
-
const index = item.indexOf("=");
|
|
896
|
-
if (index === -1) return [item];
|
|
897
|
-
return [item.slice(0, index), item.slice(index + 1)];
|
|
898
|
-
}).filter(([key]) => Boolean(key)).map(([key, value]) => prepareParam(key, value));
|
|
899
|
-
} else if (getIsOnlyAnObject(input)) {
|
|
900
|
-
return Object.keys(input).map((key) => prepareParam(key, input[key]));
|
|
901
|
-
} else if (typeof input === "string") {
|
|
902
|
-
return (input[0] === "?" ? input.slice(1) : input).split("&");
|
|
903
|
-
} else {
|
|
904
|
-
return [];
|
|
905
|
-
}
|
|
906
|
-
};
|
|
907
|
-
const { isEncode = false, outputAs = "array" } = settings || {};
|
|
908
|
-
const initialStructure = getInitialArr(queryParams);
|
|
909
|
-
const normalizedStructure = initialStructure.reduce(
|
|
910
|
-
(acc, str, idx) => {
|
|
911
|
-
const lastIndex = acc.result.length - 1;
|
|
912
|
-
const processToJoin = (val, recoverableSymbol = "&") => {
|
|
913
|
-
const encodedToJoin = `${encodeURIComponent(recoverableSymbol)}${encodeURIComponent(val)}`;
|
|
914
|
-
acc.result[lastIndex] = `${acc.result[lastIndex]}${encodedToJoin}`;
|
|
915
|
-
acc.toJoin = null;
|
|
916
|
-
};
|
|
917
|
-
if (typeof acc.toJoin === "string") processToJoin(acc.toJoin);
|
|
918
|
-
const index = str.indexOf("=");
|
|
919
|
-
if (index !== -1 && index !== 0) {
|
|
920
|
-
const key = str.slice(0, index);
|
|
921
|
-
acc.result.push(`${key}=${encodeURIComponent(str.slice(index + 1))}`);
|
|
922
|
-
} else {
|
|
923
|
-
acc.toJoin = str;
|
|
924
|
-
}
|
|
925
|
-
if (idx === initialStructure.length - 1 && typeof acc.toJoin === "string") processToJoin(acc.toJoin);
|
|
926
|
-
return acc;
|
|
927
|
-
},
|
|
928
|
-
{ result: [], toJoin: null }
|
|
929
|
-
).result;
|
|
930
|
-
const outputStructure = normalizedStructure.map((item) => {
|
|
931
|
-
const [key, value] = item.split("=");
|
|
932
|
-
return [key, !isEncode ? decodeURIComponent(value ?? "") : value ?? ""];
|
|
933
|
-
});
|
|
934
|
-
switch (outputAs) {
|
|
935
|
-
case "string":
|
|
936
|
-
return outputStructure.length ? `?${outputStructure.map(([key, value]) => `${key}=${value}`).join("&")}` : "";
|
|
937
|
-
case "object":
|
|
938
|
-
return outputStructure.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {});
|
|
939
|
-
default:
|
|
940
|
-
return outputStructure.map(([key, value]) => `${key}=${value}`);
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
|
-
};
|
|
944
|
-
var Utils_default = Utils;
|
|
945
|
-
|
|
946
|
-
// src/Classes/RESTAPI/partials/ApiUtils.ts
|
|
947
|
-
var ApiUtils = class extends Utils_default {
|
|
948
|
-
/** Корневой путь API (раскладывается в ApiBase из constants.API_PATH). */
|
|
949
|
-
API_PATH;
|
|
950
|
-
constructor(settings) {
|
|
951
|
-
super();
|
|
952
|
-
const { utils } = settings || {};
|
|
953
|
-
if (getIsOnlyAnObject(utils)) addCustomMethods.call(this, utils);
|
|
954
|
-
}
|
|
955
|
-
/**
|
|
956
|
-
* Разбирает единый объект параметров запроса на части в зависимости от варианта использования.
|
|
957
|
-
*
|
|
958
|
-
* @param apiParams - объединённые параметры запроса.
|
|
959
|
-
* @param variant - `'doRequestMapping'` для мультизапроса либо `undefined` для одиночного.
|
|
960
|
-
* @returns Для `doRequestMapping` — объект параметров; иначе кортеж `[параметры, настройки]`.
|
|
961
|
-
*/
|
|
962
|
-
// ? Планируется, что метод будет использоваться неизменно, однако технически его можно перегрузить на экземпляре
|
|
963
|
-
// ? Метод не планировался как асинхронный,
|
|
964
|
-
// ? однако ввиду того что он может быть перегружен на экземпляре асинхронность предусматривается
|
|
965
|
-
async splitProperties(apiParams, variant) {
|
|
966
|
-
const {
|
|
967
|
-
isResponseAsObject,
|
|
968
|
-
isGetBody,
|
|
969
|
-
finalCallback,
|
|
970
|
-
isToastResult,
|
|
971
|
-
toastOptions,
|
|
972
|
-
isNoToastSuccess,
|
|
973
|
-
isNoToastError,
|
|
974
|
-
isNoToast,
|
|
975
|
-
successMess,
|
|
976
|
-
commonSuccessMessage,
|
|
977
|
-
successMessages,
|
|
978
|
-
successMessageType,
|
|
979
|
-
errorMess,
|
|
980
|
-
commonErrorMessage,
|
|
981
|
-
errorMessages,
|
|
982
|
-
...restParams
|
|
983
|
-
} = apiParams || {};
|
|
984
|
-
switch (variant) {
|
|
985
|
-
case "doRequestMapping":
|
|
986
|
-
return {
|
|
987
|
-
...restParams,
|
|
988
|
-
isGetBody,
|
|
989
|
-
isToastResult,
|
|
990
|
-
toastOptions,
|
|
991
|
-
isNoToastSuccess,
|
|
992
|
-
isNoToastError,
|
|
993
|
-
isNoToast,
|
|
994
|
-
successMess,
|
|
995
|
-
commonSuccessMessage,
|
|
996
|
-
successMessages,
|
|
997
|
-
successMessageType,
|
|
998
|
-
errorMess,
|
|
999
|
-
commonErrorMessage,
|
|
1000
|
-
errorMessages
|
|
1001
|
-
};
|
|
1002
|
-
default:
|
|
1003
|
-
return [
|
|
1004
|
-
restParams,
|
|
1005
|
-
{
|
|
1006
|
-
isGetBody,
|
|
1007
|
-
isResponseAsObject,
|
|
1008
|
-
...finalCallback ? { callback: finalCallback } : {},
|
|
1009
|
-
isToastResult,
|
|
1010
|
-
toastOptions,
|
|
1011
|
-
isNoToastSuccess,
|
|
1012
|
-
isNoToastError,
|
|
1013
|
-
isNoToast,
|
|
1014
|
-
commonSuccessMessage: successMess || commonSuccessMessage,
|
|
1015
|
-
successMessages,
|
|
1016
|
-
successMessageType,
|
|
1017
|
-
commonErrorMessage: errorMess || commonErrorMessage,
|
|
1018
|
-
errorMessages
|
|
1019
|
-
}
|
|
1020
|
-
];
|
|
1021
|
-
}
|
|
1022
|
-
}
|
|
1023
|
-
/**
|
|
1024
|
-
* Обработчик пропы `api` из объекта описания запроса — возвращает корневой путь API.
|
|
1025
|
-
*
|
|
1026
|
-
* @returns Корневой путь (по умолчанию — API_PATH).
|
|
1027
|
-
*/
|
|
1028
|
-
// ! Обработчик пропы api из объекта описания запроса
|
|
1029
|
-
// ? Планируется, что метод будет перегружаться на экземпляре,
|
|
1030
|
-
// ? т.к. на разных проектах могут быть разные интерпретации пропы api
|
|
1031
|
-
// ? Метод не планировался как асинхронный,
|
|
1032
|
-
// ? однако ввиду того что он может быть перегружен на экземпляре асинхронность предусматривается
|
|
1033
|
-
async getRootPath(_apiProp) {
|
|
1034
|
-
return this.API_PATH;
|
|
1035
|
-
}
|
|
1036
|
-
/**
|
|
1037
|
-
* Извлекает тело ответа в нужном виде (json/blob/text/arrayBuffer/formData) либо по content-type.
|
|
1038
|
-
*
|
|
1039
|
-
* @param response - объект Response (иначе значение возвращается как есть).
|
|
1040
|
-
* @param getBodyAs - желаемый способ извлечения тела.
|
|
1041
|
-
* @returns Промис с телом ответа (или исходным значением / null при ошибке).
|
|
1042
|
-
*/
|
|
1043
|
-
// ? Планируется, что метод будет использоваться неизменно, однако технически его можно перегрузить на экземпляре
|
|
1044
|
-
// ? Метод планировался как асинхронный
|
|
1045
|
-
async getResponseBody(response, getBodyAs) {
|
|
1046
|
-
if (!(response instanceof Response)) return response;
|
|
1047
|
-
const contentType = response.headers.get("content-type");
|
|
1048
|
-
if (!contentType) return "";
|
|
1049
|
-
const bodyReaders = {
|
|
1050
|
-
json: (r) => r.json(),
|
|
1051
|
-
blob: (r) => r.blob(),
|
|
1052
|
-
text: (r) => r.text(),
|
|
1053
|
-
arrayBuffer: (r) => r.arrayBuffer(),
|
|
1054
|
-
formData: (r) => r.formData()
|
|
1055
|
-
};
|
|
1056
|
-
const isBodyKey = (key) => key in bodyReaders;
|
|
1057
|
-
const reader = typeof getBodyAs === "string" && isBodyKey(getBodyAs) ? bodyReaders[getBodyAs] : contentType.includes("text/csv") ? bodyReaders.blob : contentType.includes("json") ? bodyReaders.json : bodyReaders.text;
|
|
1058
|
-
try {
|
|
1059
|
-
return await reader(response);
|
|
1060
|
-
} catch {
|
|
1061
|
-
console.log("Failed to extract the body");
|
|
1062
|
-
return null;
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
/**
|
|
1066
|
-
* Формирует структуру ошибки из тела ответа (точка расширения под формат бэкенда).
|
|
1067
|
-
*
|
|
1068
|
-
* @param res - уже извлечённое тело ответа.
|
|
1069
|
-
* @returns Структура сообщения об ошибке.
|
|
1070
|
-
*/
|
|
1071
|
-
// ! Обработчик структуры для ошибки (не рендер месседжа, а имеено формирование ошибки),
|
|
1072
|
-
// ? Планируется, что метод будет перегружаться на экземпляре,
|
|
1073
|
-
// ? т.к. на разных проектах могут быть разные структуры тела ответа для ошибки
|
|
1074
|
-
// ? Метод не планировался как асинхронный,
|
|
1075
|
-
// ? однако ввиду того что он может быть перегружен на экземпляре асинхронность предусматривается
|
|
1076
|
-
// ? res - уже тело ответа
|
|
1077
|
-
async getErrorMessage(res) {
|
|
1078
|
-
return res;
|
|
1079
|
-
}
|
|
1080
|
-
/**
|
|
1081
|
-
* Проверяет код ответа и (если задан sendMessage) информирует пользователя об успехе/ошибке.
|
|
1082
|
-
*
|
|
1083
|
-
* @param res - объект Response (или совместимый с полем `ok`).
|
|
1084
|
-
* @param settings - сообщения и настройки тостов для данного запроса.
|
|
1085
|
-
* @returns Исходный `res` (метод не меняет ответ, только сигналит сообщением).
|
|
1086
|
-
*/
|
|
1087
|
-
// ? Планируется, что метод будет использоваться неизменно, однако технически его можно перегрузить на экземпляре
|
|
1088
|
-
// ? Метод планировался как асинхронный
|
|
1089
|
-
async checkResponseCode(res, settings) {
|
|
1090
|
-
const send = this.sendMessage;
|
|
1091
|
-
if (typeof send !== "function") return res;
|
|
1092
|
-
const { successMess, errorMess } = settings || {};
|
|
1093
|
-
const isOk = getIsOnlyAnObject(res) ? Boolean(res.ok) : false;
|
|
1094
|
-
const message = isOk ? successMess || this.DEFAULT_SUCCESS_MESSAGE : errorMess || await this.getErrorMessage(await this.getResponseBody(await getResponseClone(res)));
|
|
1095
|
-
try {
|
|
1096
|
-
send(message, settings, await getResponseClone(res));
|
|
1097
|
-
} catch {
|
|
1098
|
-
}
|
|
1099
|
-
return res;
|
|
1100
|
-
}
|
|
1101
|
-
/**
|
|
1102
|
-
* Структуры, которые будут использоваться для КАЖДОГО запроса, сделанного экземпляром RESTAPI.
|
|
1103
|
-
*
|
|
1104
|
-
* @returns Объект `{ headers, queryParameters, options }` (по умолчанию пустой).
|
|
1105
|
-
*/
|
|
1106
|
-
// ? Суть метода:
|
|
1107
|
-
// ? передать из вне структуры, которые будут использоваться для КАЖДОГО запроса сделанного экземпляром RESTAPI
|
|
1108
|
-
// ! Данные затрут прочие настройки КРОМЕ данных по логике авторизации
|
|
1109
|
-
// ? Планируется, что метод будет перегружаться на экземпляре
|
|
1110
|
-
// ? Метод не планировался как асинхронный,
|
|
1111
|
-
// ? однако ввиду того что он может быть перегружен на экземпляре асинхронность предусматривается
|
|
1112
|
-
async addAsCommon() {
|
|
1113
|
-
return {};
|
|
1114
|
-
}
|
|
1115
|
-
/**
|
|
1116
|
-
* Общий обработчик query-параметров (точка расширения, напр. кодирование/приведение к массиву).
|
|
1117
|
-
*
|
|
1118
|
-
* @param queryParams - входные query-параметры.
|
|
1119
|
-
* @returns Обработанные query-параметры (по умолчанию — без изменений).
|
|
1120
|
-
*/
|
|
1121
|
-
// ! Обработчик квери-параметров для общего процессинга,
|
|
1122
|
-
// ! Например для кодирования decodeURIComponent или/и приведения в формат массива
|
|
1123
|
-
// ? Планируется, что метод будет перегружаться на экземпляре,
|
|
1124
|
-
// ? т.к. на разных проектах могут быть разные договоренности по форматам
|
|
1125
|
-
// ? Метод не планировался как асинхронный,
|
|
1126
|
-
// ? однако ввиду того что он может быть перегружен на экземпляре асинхронность предусматривается
|
|
1127
|
-
async processQueryParams(queryParams) {
|
|
1128
|
-
return queryParams;
|
|
1129
|
-
}
|
|
1130
|
-
};
|
|
1131
|
-
var ApiUtils_default = ApiUtils;
|
|
1132
|
-
|
|
1133
|
-
// src/Classes/RESTAPI/partials/sse.ts
|
|
1134
|
-
function parseSSEEvent(block) {
|
|
1135
|
-
if (typeof block !== "string") return null;
|
|
1136
|
-
const event = { event: "message", data: "", id: void 0, retry: void 0 };
|
|
1137
|
-
const dataLines = [];
|
|
1138
|
-
let hasField = false;
|
|
1139
|
-
block.split("\n").forEach((line) => {
|
|
1140
|
-
if (line === "" || line[0] === ":") return;
|
|
1141
|
-
const colonIdx = line.indexOf(":");
|
|
1142
|
-
const field = colonIdx === -1 ? line : line.slice(0, colonIdx);
|
|
1143
|
-
let value = colonIdx === -1 ? "" : line.slice(colonIdx + 1);
|
|
1144
|
-
if (value[0] === " ") value = value.slice(1);
|
|
1145
|
-
switch (field) {
|
|
1146
|
-
case "event":
|
|
1147
|
-
event.event = value;
|
|
1148
|
-
hasField = true;
|
|
1149
|
-
break;
|
|
1150
|
-
case "data":
|
|
1151
|
-
dataLines.push(value);
|
|
1152
|
-
hasField = true;
|
|
1153
|
-
break;
|
|
1154
|
-
case "id":
|
|
1155
|
-
event.id = value;
|
|
1156
|
-
hasField = true;
|
|
1157
|
-
break;
|
|
1158
|
-
case "retry":
|
|
1159
|
-
if (/^\d+$/.test(value)) {
|
|
1160
|
-
event.retry = Number(value);
|
|
1161
|
-
hasField = true;
|
|
1162
|
-
}
|
|
1163
|
-
break;
|
|
1164
|
-
default:
|
|
1165
|
-
break;
|
|
1166
|
-
}
|
|
1167
|
-
});
|
|
1168
|
-
if (!hasField) return null;
|
|
1169
|
-
event.data = dataLines.join("\n");
|
|
1170
|
-
return event;
|
|
1171
|
-
}
|
|
1172
|
-
function safeCall(fn, ...args) {
|
|
1173
|
-
if (typeof fn !== "function") return;
|
|
1174
|
-
try {
|
|
1175
|
-
fn(...args);
|
|
1176
|
-
} catch {
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
async function readSSE(response, { onEvent, onChunk, handlers, parseJson } = {}) {
|
|
1180
|
-
const events = [];
|
|
1181
|
-
const stream = response.body;
|
|
1182
|
-
if (!stream) return events;
|
|
1183
|
-
const reader = stream.getReader();
|
|
1184
|
-
const decoder = new TextDecoder("utf-8");
|
|
1185
|
-
let buffer = "";
|
|
1186
|
-
let pendingCR = "";
|
|
1187
|
-
const normalize = (chunk) => chunk.replace(/\r\n|\r/g, "\n");
|
|
1188
|
-
const flush = (rawBlock) => {
|
|
1189
|
-
const event = parseSSEEvent(rawBlock);
|
|
1190
|
-
if (!event) return;
|
|
1191
|
-
if (parseJson && typeof event.data === "string" && event.data !== "") {
|
|
1192
|
-
try {
|
|
1193
|
-
event.data = JSON.parse(event.data);
|
|
1194
|
-
} catch {
|
|
1195
|
-
}
|
|
1196
|
-
}
|
|
1197
|
-
events.push(event);
|
|
1198
|
-
safeCall(onEvent, event);
|
|
1199
|
-
safeCall(onChunk, event.data, event);
|
|
1200
|
-
if (handlers) safeCall(handlers[event.event], event.data, event);
|
|
1201
|
-
};
|
|
1202
|
-
try {
|
|
1203
|
-
while (true) {
|
|
1204
|
-
const { done, value } = await reader.read();
|
|
1205
|
-
if (done) break;
|
|
1206
|
-
let chunk = pendingCR + decoder.decode(value, { stream: true });
|
|
1207
|
-
pendingCR = "";
|
|
1208
|
-
if (chunk.endsWith("\r")) {
|
|
1209
|
-
pendingCR = "\r";
|
|
1210
|
-
chunk = chunk.slice(0, -1);
|
|
1211
|
-
}
|
|
1212
|
-
buffer += normalize(chunk);
|
|
1213
|
-
let sepIdx;
|
|
1214
|
-
while ((sepIdx = buffer.indexOf("\n\n")) !== -1) {
|
|
1215
|
-
const rawBlock = buffer.slice(0, sepIdx);
|
|
1216
|
-
buffer = buffer.slice(sepIdx + 2);
|
|
1217
|
-
flush(rawBlock);
|
|
1218
|
-
}
|
|
1219
|
-
}
|
|
1220
|
-
buffer += normalize(pendingCR + decoder.decode());
|
|
1221
|
-
buffer = buffer.replace(/\n+$/g, "");
|
|
1222
|
-
if (buffer !== "") flush(buffer);
|
|
1223
|
-
} catch (error) {
|
|
1224
|
-
const name = error && typeof error === "object" && "name" in error ? error.name : void 0;
|
|
1225
|
-
if (name !== "AbortError") throw error;
|
|
1226
|
-
} finally {
|
|
1227
|
-
try {
|
|
1228
|
-
reader.releaseLock?.();
|
|
1229
|
-
} catch {
|
|
1230
|
-
}
|
|
1231
|
-
}
|
|
1232
|
-
return events;
|
|
1233
|
-
}
|
|
1234
|
-
|
|
1235
|
-
// src/Classes/RESTAPI/partials/ApiRequestCreators.ts
|
|
1236
|
-
function isStreamResponse(value) {
|
|
1237
|
-
if (!getIsOnlyAnObject(value) || !value.ok) return false;
|
|
1238
|
-
const body = value.body;
|
|
1239
|
-
return typeof body === "object" && body !== null && "getReader" in body && typeof body.getReader === "function";
|
|
1240
|
-
}
|
|
1241
|
-
var PREFIX_OF_CLASS_UTILS = "createRequest_";
|
|
1242
|
-
var ApiRequestCreators = class extends ApiUtils_default {
|
|
1243
|
-
constructor(settings) {
|
|
1244
|
-
super(settings);
|
|
1245
|
-
const { requestsCreators } = settings || {};
|
|
1246
|
-
if (getIsOnlyAnObject(requestsCreators)) addCustomMethods.call(this, requestsCreators, PREFIX_OF_CLASS_UTILS);
|
|
1247
|
-
}
|
|
1248
|
-
/**
|
|
1249
|
-
* Крейтер типа `toJson`: пользовательский callback получит тело ответа (Response.json()).
|
|
1250
|
-
*
|
|
1251
|
-
* @param props - объект описания запроса.
|
|
1252
|
-
* @param variant - вариант обработки splitProperties.
|
|
1253
|
-
*/
|
|
1254
|
-
// ? При типе toJson пользовательский callback на вход получит тело ответа реализованное методом Response.json()
|
|
1255
|
-
// ? независимо от насторойки isGetBody
|
|
1256
|
-
async createRequest_toJson(props, variant) {
|
|
1257
|
-
const safelyProps = omitKeys(props, ["getBodyAs"]);
|
|
1258
|
-
return this.splitProperties(
|
|
1259
|
-
{
|
|
1260
|
-
...safelyProps,
|
|
1261
|
-
isGetBody: false,
|
|
1262
|
-
callback: async (res) => {
|
|
1263
|
-
const output = await this.getResponseBody(res, "json");
|
|
1264
|
-
return await (props.callback?.(output) ?? output);
|
|
1265
|
-
}
|
|
1266
|
-
},
|
|
1267
|
-
variant
|
|
1268
|
-
);
|
|
1269
|
-
}
|
|
1270
|
-
/**
|
|
1271
|
-
* Крейтер типа `toJsonAdvanced`: callback получит структуру `{ response, result }`.
|
|
1272
|
-
*
|
|
1273
|
-
* @param props - объект описания запроса.
|
|
1274
|
-
* @param variant - вариант обработки splitProperties.
|
|
1275
|
-
*/
|
|
1276
|
-
// ? При типе toJsonAdvanced пользовательский callback на вход получит структуру { response, result },
|
|
1277
|
-
// ? где response - объект Response, result - тело ответа реализованное методом Response.json()
|
|
1278
|
-
// ? независимо от насторойки isGetBody
|
|
1279
|
-
async createRequest_toJsonAdvanced(props, variant) {
|
|
1280
|
-
const safelyProps = omitKeys(props, ["getBodyAs"]);
|
|
1281
|
-
return this.splitProperties(
|
|
1282
|
-
{
|
|
1283
|
-
...safelyProps,
|
|
1284
|
-
isGetBody: false,
|
|
1285
|
-
callback: async (res) => {
|
|
1286
|
-
const output = {
|
|
1287
|
-
response: res,
|
|
1288
|
-
result: await this.getResponseBody(await getResponseClone(res), "json")
|
|
1289
|
-
};
|
|
1290
|
-
return await (props.callback?.(output) ?? output);
|
|
1291
|
-
}
|
|
1292
|
-
},
|
|
1293
|
-
variant
|
|
1294
|
-
);
|
|
1295
|
-
}
|
|
1296
|
-
/**
|
|
1297
|
-
* Крейтер типа `blob`: callback получит тело ответа (Response.blob()).
|
|
1298
|
-
*
|
|
1299
|
-
* @param props - объект описания запроса.
|
|
1300
|
-
* @param variant - вариант обработки splitProperties.
|
|
1301
|
-
*/
|
|
1302
|
-
// ? При типе blob пользовательский callback на вход получит тело ответа реализованное методом Response.blob(),
|
|
1303
|
-
// ? независимо от насторойки isGetBody
|
|
1304
|
-
async createRequest_blob(props, variant) {
|
|
1305
|
-
const safelyProps = omitKeys(props, ["getBodyAs"]);
|
|
1306
|
-
return this.splitProperties(
|
|
1307
|
-
{
|
|
1308
|
-
...safelyProps,
|
|
1309
|
-
isGetBody: false,
|
|
1310
|
-
callback: async (res) => {
|
|
1311
|
-
const output = await this.getResponseBody(await getResponseClone(res), "blob");
|
|
1312
|
-
return await (props.callback?.(output) ?? output);
|
|
1313
|
-
}
|
|
1314
|
-
},
|
|
1315
|
-
variant
|
|
1316
|
-
);
|
|
1317
|
-
}
|
|
1318
|
-
/**
|
|
1319
|
-
* Крейтер типа `sse`: обрабатывает ответ как поток Server-Sent Events (text/event-stream).
|
|
1320
|
-
*
|
|
1321
|
-
* Дополнительные пропы объекта описания запроса: `onEvent`, `onChunk`, `handlers`, `parseJson`.
|
|
1322
|
-
* По умолчанию добавляется заголовок `Accept: text/event-stream`. Метод doRequest резолвится
|
|
1323
|
-
* массивом всех событий ПОСЛЕ закрытия потока; отмена — методом `.abort()` возвращённого промиса.
|
|
1324
|
-
*
|
|
1325
|
-
* @param props - объект описания запроса (плюс onEvent/onChunk/handlers/parseJson).
|
|
1326
|
-
* @param variant - вариант обработки splitProperties.
|
|
1327
|
-
*/
|
|
1328
|
-
// ? При типе sse запрос обрабатывается как поток Server-Sent Events (text/event-stream).
|
|
1329
|
-
// ? Дополнительные пропы объекта описания запроса:
|
|
1330
|
-
// ? - onEvent(event) — вызывается на каждое распарсенное событие { event, data, id, retry };
|
|
1331
|
-
// ? - onChunk(data, event) — вызывается на полезную нагрузку (поле data) каждого события;
|
|
1332
|
-
// ? - handlers — карта { имяСобытия: cb } для типизированной обработки по полю event
|
|
1333
|
-
// ? (например { delta, status, done }); cb получает (data, event);
|
|
1334
|
-
// ? - parseJson — если true, поле data каждого события прогоняется через JSON.parse.
|
|
1335
|
-
// ? По умолчанию добавляется заголовок Accept: text/event-stream (его можно переопределить через headers).
|
|
1336
|
-
// ? Пользовательский callback (если передан) на вход получит итоговый массив всех событий.
|
|
1337
|
-
// ? Метод doRequest резолвится массивом всех событий ПОСЛЕ закрытия потока;
|
|
1338
|
-
// ? отмена потока выполняется методом .abort() возвращённого промиса (через встроенный AbortController).
|
|
1339
|
-
async createRequest_sse(props, variant) {
|
|
1340
|
-
const safelyProps = omitKeys(props, ["getBodyAs", "onChunk", "onEvent", "handlers", "parseJson"]);
|
|
1341
|
-
const { onChunk, onEvent, handlers, parseJson } = props;
|
|
1342
|
-
const sseOptions = {
|
|
1343
|
-
onChunk: typeof onChunk === "function" ? (data, event) => onChunk(data, event) : void 0,
|
|
1344
|
-
onEvent: typeof onEvent === "function" ? (event) => onEvent(event) : void 0,
|
|
1345
|
-
parseJson: Boolean(parseJson),
|
|
1346
|
-
handlers: getIsOnlyAnObject(handlers) ? Object.keys(handlers).reduce((acc, key) => {
|
|
1347
|
-
const fn = handlers[key];
|
|
1348
|
-
acc[key] = typeof fn === "function" ? (data, event) => fn(data, event) : void 0;
|
|
1349
|
-
return acc;
|
|
1350
|
-
}, {}) : void 0
|
|
1351
|
-
};
|
|
1352
|
-
return this.splitProperties(
|
|
1353
|
-
{
|
|
1354
|
-
...safelyProps,
|
|
1355
|
-
headers: { Accept: "text/event-stream", ...getIsOnlyAnObject(safelyProps.headers) ? safelyProps.headers : {} },
|
|
1356
|
-
isGetBody: false,
|
|
1357
|
-
callback: async (res) => {
|
|
1358
|
-
const output = isStreamResponse(res) ? await readSSE(res, sseOptions) : res;
|
|
1359
|
-
return await (props.callback?.(output) ?? output);
|
|
1360
|
-
}
|
|
1361
|
-
},
|
|
1362
|
-
variant
|
|
1363
|
-
);
|
|
1364
|
-
}
|
|
1365
|
-
/**
|
|
1366
|
-
* Крейтер типа `testBadResponse`: callback получит синтетический Response со статусом 401.
|
|
1367
|
-
*
|
|
1368
|
-
* @param props - объект описания запроса.
|
|
1369
|
-
* @param variant - вариант обработки splitProperties.
|
|
1370
|
-
*/
|
|
1371
|
-
// ? При типе testBadResponse пользовательский callback на вход получит объект Response в 401-м статусе
|
|
1372
|
-
// ? независимо независимо вообще ни от чего
|
|
1373
|
-
async createRequest_testBadResponse(props, variant) {
|
|
1374
|
-
return this.splitProperties(
|
|
1375
|
-
{
|
|
1376
|
-
...props,
|
|
1377
|
-
callback: async () => Promise.resolve(
|
|
1378
|
-
new Response(JSON.stringify({ errors: [{ message: "test bad Response" }] }), {
|
|
1379
|
-
status: 401,
|
|
1380
|
-
statusText: "test bad Response",
|
|
1381
|
-
headers: (() => {
|
|
1382
|
-
const headers = new Headers();
|
|
1383
|
-
headers.append("content-type", "application/json");
|
|
1384
|
-
return headers;
|
|
1385
|
-
})()
|
|
1386
|
-
})
|
|
1387
|
-
).then((res) => props.callback?.(res) ?? res)
|
|
1388
|
-
},
|
|
1389
|
-
variant
|
|
1390
|
-
);
|
|
1391
|
-
}
|
|
1392
|
-
/**
|
|
1393
|
-
* Крейтер по умолчанию: callback получит объект Response (или тело ответа при isGetBody: 'first').
|
|
1394
|
-
*
|
|
1395
|
-
* @param props - объект описания запроса.
|
|
1396
|
-
* @param variant - вариант обработки splitProperties.
|
|
1397
|
-
*/
|
|
1398
|
-
// ? По умолчанию пользовательский callback на вход получит
|
|
1399
|
-
// ? - либо объект Response
|
|
1400
|
-
// ? - либо тело ответа (в случае isGetBody: 'first') полученное методом getResponseBody (смотри класс ApiUtils)
|
|
1401
|
-
async createRequest_default(props, variant) {
|
|
1402
|
-
return this.splitProperties(props, variant);
|
|
1403
|
-
}
|
|
1404
|
-
};
|
|
1405
|
-
var ApiRequestCreators_default = ApiRequestCreators;
|
|
1406
|
-
|
|
1407
|
-
// src/Classes/RESTAPI/partials/ApiBase.ts
|
|
1408
|
-
var ApiBase = class extends ApiRequestCreators_default {
|
|
1409
|
-
/** Текст ошибки невалидных данных запроса. */
|
|
1410
|
-
BAD_REQUEST_DATA_TEXT;
|
|
1411
|
-
/** Текст сообщения об успехе по умолчанию. */
|
|
1412
|
-
DEFAULT_SUCCESS_MESSAGE;
|
|
1413
|
-
/** Текст сообщения об ошибке по умолчанию. */
|
|
1414
|
-
DEFAULT_ERROR_MESSAGE;
|
|
1415
|
-
/** Текст сообщения об отсутствии сети. */
|
|
1416
|
-
NO_INET;
|
|
1417
|
-
/** Коды ответа, по которым запрос считается отклонённым. */
|
|
1418
|
-
REJECT_CODES;
|
|
1419
|
-
constructor(settings) {
|
|
1420
|
-
super(settings);
|
|
1421
|
-
const {
|
|
1422
|
-
API_PATH,
|
|
1423
|
-
BAD_REQUEST_DATA_TEXT = "Bad request data",
|
|
1424
|
-
DEFAULT_SUCCESS_MESSAGE = "Success",
|
|
1425
|
-
DEFAULT_ERROR_MESSAGE = "Something wrong, try again",
|
|
1426
|
-
NO_INET = "Please check your network connection and reload page",
|
|
1427
|
-
REJECT_CODES = [],
|
|
1428
|
-
...customConstants
|
|
1429
|
-
} = settings.constants || {};
|
|
1430
|
-
if (typeof API_PATH !== "string") throw new Error("No API_PATH [ApiBase constructor]");
|
|
1431
|
-
if (typeof BAD_REQUEST_DATA_TEXT !== "string" || typeof DEFAULT_SUCCESS_MESSAGE !== "string" || typeof DEFAULT_ERROR_MESSAGE !== "string" || typeof NO_INET !== "string" || !Array.isArray(REJECT_CODES) || !REJECT_CODES.every((i) => typeof i === "number")) {
|
|
1432
|
-
throw new Error("Bad input data [ApiBase constructor]");
|
|
1433
|
-
}
|
|
1434
|
-
this.API_PATH = API_PATH;
|
|
1435
|
-
this.BAD_REQUEST_DATA_TEXT = BAD_REQUEST_DATA_TEXT;
|
|
1436
|
-
this.DEFAULT_SUCCESS_MESSAGE = DEFAULT_SUCCESS_MESSAGE;
|
|
1437
|
-
this.DEFAULT_ERROR_MESSAGE = DEFAULT_ERROR_MESSAGE;
|
|
1438
|
-
this.NO_INET = NO_INET;
|
|
1439
|
-
this.REJECT_CODES = REJECT_CODES;
|
|
1440
|
-
Object.keys(customConstants).forEach((key) => {
|
|
1441
|
-
this[key] = customConstants[key];
|
|
1442
|
-
});
|
|
1443
|
-
}
|
|
1444
|
-
};
|
|
1445
|
-
var ApiBase_default = ApiBase;
|
|
1446
|
-
|
|
1447
|
-
// src/Classes/RESTAPI/partials/CredentialsProcessing.ts
|
|
1448
|
-
function decodeJWT(token) {
|
|
1449
|
-
try {
|
|
1450
|
-
const payload = token.split(".")[1] ?? "";
|
|
1451
|
-
const decoded = JSON.parse(atob(payload));
|
|
1452
|
-
return getIsOnlyAnObject(decoded) ? decoded : null;
|
|
1453
|
-
} catch {
|
|
1454
|
-
return null;
|
|
1455
|
-
}
|
|
1456
|
-
}
|
|
1457
|
-
var CredentialsProcessing = class {
|
|
1458
|
-
/** Включён ли флоу рефреша токенов. */
|
|
1459
|
-
isUseRefreshTokensPropcessing = false;
|
|
1460
|
-
/** Учётные данные по умолчанию (пустые). */
|
|
1461
|
-
DEFAULT_CREDENTIALS = {};
|
|
1462
|
-
/** Внешний метод получения учётных данных. */
|
|
1463
|
-
getCredentialsByOuter;
|
|
1464
|
-
/** Внешний метод формирования заголовков авторизации по токену. */
|
|
1465
|
-
getHeadersForAuthorize;
|
|
1466
|
-
/** Необязательный преобразователь учётных данных после getCredentials. */
|
|
1467
|
-
importCredentials;
|
|
1468
|
-
/** Необязательный метод сохранения учётных данных (обязателен для флоу рефреша). */
|
|
1469
|
-
saveCredentials;
|
|
1470
|
-
/** Внешний метод рефреша учётных данных. */
|
|
1471
|
-
refreshCredentialsByOuter;
|
|
1472
|
-
/** Полный путь до эндпоинта рефреша токена. */
|
|
1473
|
-
REFRESH_TOKEN_PATH;
|
|
1474
|
-
/** Коды ответа, по которым триггерится попытка рефреша. */
|
|
1475
|
-
CODES_USING_THE_REFRESH_ATTEMPT;
|
|
1476
|
-
/** Ключ флага «рефреш начат» в localStorage. */
|
|
1477
|
-
REFRESH_TOKEN_FLAG = "refreshTokenFlag";
|
|
1478
|
-
/** Интервал опроса флага обновления токена, мс. */
|
|
1479
|
-
INTERVAL_FOR_CHECKING_TOKEN_UPDATE = 50;
|
|
1480
|
-
/** Колбэк, вызываемый после неудачного рефреша. */
|
|
1481
|
-
callbackAfterRejectRefresh;
|
|
1482
|
-
/** Доступ к верхнему контексту RESTAPI (навешивается из конструктора RESTAPI). */
|
|
1483
|
-
getRESTAPIContext;
|
|
1484
|
-
constructor(settings) {
|
|
1485
|
-
const { credentialsProcessing } = settings;
|
|
1486
|
-
const {
|
|
1487
|
-
// ? Для корректной работы установки токенов в запросы от API
|
|
1488
|
-
// ? нужно передавать методы getCredentials и getHeadersForAuthorize
|
|
1489
|
-
getCredentials,
|
|
1490
|
-
getHeadersForAuthorize,
|
|
1491
|
-
// ? На вход получит токен, должна вернуть объект для коструктора Headers
|
|
1492
|
-
// ? Так же опционально можно передавать
|
|
1493
|
-
importCredentials,
|
|
1494
|
-
// ? если он передается, то он будет применяться к выводу от вызова getCredentials
|
|
1495
|
-
saveCredentials,
|
|
1496
|
-
// ? можно будет найти в объекте credentialsProcessing, чтобы использовать кастомными методами
|
|
1497
|
-
// ! Либо вызов getCredentials, либо цепочка вызовов importCredentials(getCredentials())
|
|
1498
|
-
// ! должна возвращать требуемую классом структуру
|
|
1499
|
-
// ! Класс требует структуры
|
|
1500
|
-
// ! - { token }, если флоу рефреш токена НЕ используется
|
|
1501
|
-
// ! - { token, refreshToken, expires }, если используется флоу рефреш токена
|
|
1502
|
-
// *********
|
|
1503
|
-
// ? Подключает флоу рефреша токенов
|
|
1504
|
-
isUseRefreshTokensPropcessing = false,
|
|
1505
|
-
// ! Для корректной работы флоу рефреша токенов передача метода saveCredentials становится ОБЯЗАТЕЛЬНОЙ
|
|
1506
|
-
// ? Так же для корректной работы флоу рефреша токенов нужно
|
|
1507
|
-
// ? - либо
|
|
1508
|
-
refreshCredentials,
|
|
1509
|
-
// ! метод должен возвращать такую же структуру как и метод getCredentials,
|
|
1510
|
-
// ? на вход получит текущие креды, к выходу будет применен importCredentials, если этот метод передавался
|
|
1511
|
-
// ? - либо
|
|
1512
|
-
REFRESH_TOKEN_PATH,
|
|
1513
|
-
// ! REFRESH_TOKEN_PATH передается ПОЛНОСТЬЮ (глобальная адресация)!
|
|
1514
|
-
CODES_USING_THE_REFRESH_ATTEMPT,
|
|
1515
|
-
// ? указывает по каким кодам ответа триггериться рефреш, массив чисел
|
|
1516
|
-
// ? Опционально
|
|
1517
|
-
REFRESH_TOKEN_FLAG = "refreshTokenFlag",
|
|
1518
|
-
INTERVAL_FOR_CHECKING_TOKEN_UPDATE = 50,
|
|
1519
|
-
// ms
|
|
1520
|
-
callbackAfterRejectRefresh
|
|
1521
|
-
} = credentialsProcessing || {};
|
|
1522
|
-
if (typeof getCredentials !== "function") throw new Error("No getCredentials method [CredentialsProcessing]");
|
|
1523
|
-
if (typeof getHeadersForAuthorize !== "function") {
|
|
1524
|
-
throw new TypeError("No getHeadersForAuthorize method [CredentialsProcessing]");
|
|
1525
|
-
}
|
|
1526
|
-
if (importCredentials && typeof importCredentials !== "function") {
|
|
1527
|
-
throw new Error("Bad importCredentials method [CredentialsProcessing]");
|
|
1528
|
-
}
|
|
1529
|
-
this.isUseRefreshTokensPropcessing = Boolean(isUseRefreshTokensPropcessing);
|
|
1530
|
-
this.DEFAULT_CREDENTIALS = {};
|
|
1531
|
-
this.getCredentialsByOuter = () => getCredentials();
|
|
1532
|
-
this.getHeadersForAuthorize = (token) => {
|
|
1533
|
-
const result = getHeadersForAuthorize(token);
|
|
1534
|
-
return getIsOnlyAnObject(result) ? result : {};
|
|
1535
|
-
};
|
|
1536
|
-
if (typeof importCredentials === "function") this.importCredentials = (cred) => importCredentials(cred);
|
|
1537
|
-
if (saveCredentials || isUseRefreshTokensPropcessing) {
|
|
1538
|
-
if (typeof saveCredentials !== "function") throw new Error("No saveCredentials method [CredentialsProcessing]");
|
|
1539
|
-
else this.saveCredentials = (cred) => saveCredentials(cred);
|
|
1540
|
-
}
|
|
1541
|
-
if (isUseRefreshTokensPropcessing) {
|
|
1542
|
-
if (typeof refreshCredentials === "function") {
|
|
1543
|
-
this.refreshCredentialsByOuter = (cred) => refreshCredentials(cred);
|
|
1544
|
-
} else {
|
|
1545
|
-
if (typeof this.refreshCredentialsByOuter === "function" && typeof REFRESH_TOKEN_PATH !== "string") {
|
|
1546
|
-
throw new TypeError("No REFRESH_TOKEN_PATH [CredentialsProcessing]");
|
|
1547
|
-
}
|
|
1548
|
-
this.REFRESH_TOKEN_PATH = typeof REFRESH_TOKEN_PATH === "string" ? REFRESH_TOKEN_PATH : void 0;
|
|
1549
|
-
}
|
|
1550
|
-
if (!Array.isArray(CODES_USING_THE_REFRESH_ATTEMPT)) {
|
|
1551
|
-
throw new TypeError("No CODES_USING_THE_REFRESH_ATTEMPT [CredentialsProcessing]");
|
|
1552
|
-
}
|
|
1553
|
-
if (!CODES_USING_THE_REFRESH_ATTEMPT.every((i) => typeof i === "number")) {
|
|
1554
|
-
throw new Error("Invalid format of CODES_USING_THE_REFRESH_ATTEMPT elements [CredentialsProcessing]");
|
|
1555
|
-
}
|
|
1556
|
-
if (typeof REFRESH_TOKEN_FLAG !== "string") throw new Error("Bad REFRESH_TOKEN_FLAG [CredentialsProcessing]");
|
|
1557
|
-
if (typeof INTERVAL_FOR_CHECKING_TOKEN_UPDATE !== "number") {
|
|
1558
|
-
throw new TypeError("Bad INTERVAL_FOR_CHECKING_TOKEN_UPDATE [CredentialsProcessing]");
|
|
1559
|
-
}
|
|
1560
|
-
if (typeof INTERVAL_FOR_CHECKING_TOKEN_UPDATE !== "number") {
|
|
1561
|
-
throw new TypeError("Bad INTERVAL_FOR_CHECKING_TOKEN_UPDATE [CredentialsProcessing]");
|
|
1562
|
-
}
|
|
1563
|
-
if (callbackAfterRejectRefresh && typeof callbackAfterRejectRefresh !== "function") {
|
|
1564
|
-
throw new Error("Bad INTERVAL_FOR_CHECKING_TOKEN_UPDATE [CredentialsProcessing]");
|
|
1565
|
-
}
|
|
1566
|
-
this.CODES_USING_THE_REFRESH_ATTEMPT = CODES_USING_THE_REFRESH_ATTEMPT;
|
|
1567
|
-
this.REFRESH_TOKEN_FLAG = REFRESH_TOKEN_FLAG;
|
|
1568
|
-
this.INTERVAL_FOR_CHECKING_TOKEN_UPDATE = INTERVAL_FOR_CHECKING_TOKEN_UPDATE;
|
|
1569
|
-
if (typeof callbackAfterRejectRefresh === "function") this.callbackAfterRejectRefresh = () => callbackAfterRejectRefresh();
|
|
1570
|
-
}
|
|
1571
|
-
}
|
|
1572
|
-
/** Возвращает значение флага «рефреш начат» из localStorage. */
|
|
1573
|
-
getIsTokenStartRefresh() {
|
|
1574
|
-
return localStorage.getItem(this.REFRESH_TOKEN_FLAG);
|
|
1575
|
-
}
|
|
1576
|
-
/** Выставляет флаг «рефреш начат» в localStorage. */
|
|
1577
|
-
setIsTokenStartRefresh() {
|
|
1578
|
-
localStorage.setItem(this.REFRESH_TOKEN_FLAG, String(true));
|
|
1579
|
-
}
|
|
1580
|
-
/** Снимает флаг «рефреш начат» из localStorage. */
|
|
1581
|
-
removeIsTokenStartRefresh() {
|
|
1582
|
-
localStorage.removeItem(this.REFRESH_TOKEN_FLAG);
|
|
1583
|
-
}
|
|
1584
|
-
/**
|
|
1585
|
-
* Возвращает текущие учётные данные (с учётом importCredentials и проверки истечения JWT).
|
|
1586
|
-
*
|
|
1587
|
-
* @param isCatchCallbackProcess - флаг процесса обработки ошибки (отключает проверку истечения).
|
|
1588
|
-
* @param callback - необязательный колбэк, получающий итоговые учётные данные.
|
|
1589
|
-
* @returns Промис с учётными данными.
|
|
1590
|
-
*/
|
|
1591
|
-
async getCredentials(isCatchCallbackProcess, callback) {
|
|
1592
|
-
let credentials = await this.getCredentialsByOuter();
|
|
1593
|
-
if (typeof this.importCredentials === "function") credentials = await this.importCredentials(credentials);
|
|
1594
|
-
const credObj = getIsOnlyAnObject(credentials) ? credentials : {};
|
|
1595
|
-
const token = credObj.token || null;
|
|
1596
|
-
if (token && !isCatchCallbackProcess) {
|
|
1597
|
-
let decoded;
|
|
1598
|
-
try {
|
|
1599
|
-
decoded = decodeJWT(token);
|
|
1600
|
-
} catch {
|
|
1601
|
-
decoded = null;
|
|
1602
|
-
}
|
|
1603
|
-
const currentTime = Date.now() / 1e3;
|
|
1604
|
-
if (decoded !== null && Number(decoded.exp) < currentTime) credObj.isNeedRefresh = true;
|
|
1605
|
-
}
|
|
1606
|
-
if (callback) await callback({ ...credObj, isCatchCallbackProcess });
|
|
1607
|
-
return { ...credObj, isCatchCallbackProcess };
|
|
1608
|
-
}
|
|
1609
|
-
/**
|
|
1610
|
-
* Выполняет рефреш учётных данных (внешним методом либо дефолтным OAuth-флоу).
|
|
1611
|
-
*
|
|
1612
|
-
* @param currentCredentials - текущие учётные данные.
|
|
1613
|
-
* @param callback - необязательный колбэк сохранения новых учётных данных.
|
|
1614
|
-
* @returns Промис с новыми учётными данными.
|
|
1615
|
-
*/
|
|
1616
|
-
async refreshCredentials(currentCredentials, callback) {
|
|
1617
|
-
const CONTEXT = this;
|
|
1618
|
-
async function finalize(cred) {
|
|
1619
|
-
if (callback) await callback(cred);
|
|
1620
|
-
return Promise.resolve(cred).then(async (res) => {
|
|
1621
|
-
CONTEXT.removeIsTokenStartRefresh();
|
|
1622
|
-
return res;
|
|
1623
|
-
});
|
|
1624
|
-
}
|
|
1625
|
-
if (!currentCredentials?.token || !currentCredentials?.refreshToken) return finalize(CONTEXT.DEFAULT_CREDENTIALS);
|
|
1626
|
-
async function refreshCredentialsByDefault() {
|
|
1627
|
-
const { token, refreshToken } = currentCredentials;
|
|
1628
|
-
const headers = new Headers(Object.entries(CONTEXT.getHeadersForAuthorize(token || "")).map(([key, value]) => [key, `${value}`]));
|
|
1629
|
-
const body = new FormData();
|
|
1630
|
-
body.append("grant_type", "refresh_token");
|
|
1631
|
-
body.append("refresh_token", refreshToken || "");
|
|
1632
|
-
body.append("client_id", "oauth");
|
|
1633
|
-
body.append("client_secret", "secret");
|
|
1634
|
-
body.append("access_type", "offline");
|
|
1635
|
-
return fetch(`${CONTEXT.REFRESH_TOKEN_PATH}`, {
|
|
1636
|
-
mode: "cors",
|
|
1637
|
-
method: "POST",
|
|
1638
|
-
headers,
|
|
1639
|
-
body,
|
|
1640
|
-
redirect: "follow"
|
|
1641
|
-
});
|
|
1642
|
-
}
|
|
1643
|
-
const newCredentials = typeof CONTEXT.refreshCredentialsByOuter === "function" ? await CONTEXT.refreshCredentialsByOuter(currentCredentials) : await refreshCredentialsByDefault();
|
|
1644
|
-
return finalize(getIsOnlyAnObject(newCredentials) ? newCredentials : CONTEXT.DEFAULT_CREDENTIALS);
|
|
1645
|
-
}
|
|
1646
|
-
/**
|
|
1647
|
-
* Ожидает завершения рефреша токена (или запускает его флаг при необходимости).
|
|
1648
|
-
*
|
|
1649
|
-
* @param isNeedRefresh - выставить ли флаг «рефреш начат» при отсутствии активного рефреша.
|
|
1650
|
-
* @returns Промис, который резолвится по завершении ожидания.
|
|
1651
|
-
*/
|
|
1652
|
-
async waitRefresh(isNeedRefresh) {
|
|
1653
|
-
return new Promise((resolve) => {
|
|
1654
|
-
if (!this.getIsTokenStartRefresh()) {
|
|
1655
|
-
if (isNeedRefresh) this.setIsTokenStartRefresh();
|
|
1656
|
-
resolve();
|
|
1657
|
-
} else {
|
|
1658
|
-
const intervalId = setInterval(() => {
|
|
1659
|
-
if (!this.getIsTokenStartRefresh()) {
|
|
1660
|
-
clearInterval(intervalId);
|
|
1661
|
-
resolve();
|
|
1662
|
-
}
|
|
1663
|
-
}, this.INTERVAL_FOR_CHECKING_TOKEN_UPDATE);
|
|
1664
|
-
}
|
|
1665
|
-
});
|
|
1666
|
-
}
|
|
1667
|
-
/**
|
|
1668
|
-
* Обрабатывает учётные данные: при необходимости рефрешит токен и возвращает актуальные данные.
|
|
1669
|
-
*
|
|
1670
|
-
* @param cred - текущие учётные данные.
|
|
1671
|
-
* @returns Промис с актуальными учётными данными (с флагом isRefreshFailed при неудаче).
|
|
1672
|
-
*/
|
|
1673
|
-
async processCredentials(cred) {
|
|
1674
|
-
if (!cred.isNeedRefresh && !cred.isCatchCallbackProcess) return cred;
|
|
1675
|
-
const CONTEXT = this;
|
|
1676
|
-
return CONTEXT.refreshCredentials(cred, (response) => CONTEXT.saveCredentials?.(response)).then(() => {
|
|
1677
|
-
return new Promise((resolve) => {
|
|
1678
|
-
setTimeout(async () => {
|
|
1679
|
-
const newCredentials = await CONTEXT.getCredentials();
|
|
1680
|
-
if (!newCredentials?.token) {
|
|
1681
|
-
newCredentials.isRefreshFailed = true;
|
|
1682
|
-
setTimeout(() => {
|
|
1683
|
-
CONTEXT?.callbackAfterRejectRefresh?.();
|
|
1684
|
-
}, 0);
|
|
1685
|
-
}
|
|
1686
|
-
resolve(newCredentials);
|
|
1687
|
-
}, 0);
|
|
1688
|
-
});
|
|
1689
|
-
});
|
|
1690
|
-
}
|
|
1691
|
-
};
|
|
1692
|
-
var CredentialsProcessing_default = CredentialsProcessing;
|
|
1693
|
-
|
|
1694
|
-
// src/Classes/RESTAPI/index.ts
|
|
1695
|
-
function returnTheContext() {
|
|
1696
|
-
return this;
|
|
1697
|
-
}
|
|
1698
|
-
var RESTAPI = class extends ApiBase_default {
|
|
1699
|
-
/** Функция показа сообщений пользователю (или null, если информирование отключено). */
|
|
1700
|
-
sendMessage = null;
|
|
1701
|
-
/** Обработчик учётных данных (создаётся при наличии настройки credentialsProcessing). */
|
|
1702
|
-
credentialsProcessing;
|
|
1703
|
-
constructor(settings) {
|
|
1704
|
-
super(settings);
|
|
1705
|
-
const { sendMessage, credentialsProcessing } = settings || {};
|
|
1706
|
-
this.sendMessage = typeof sendMessage === "function" ? sendMessage : null;
|
|
1707
|
-
if (getIsOnlyAnObject(credentialsProcessing)) {
|
|
1708
|
-
this.credentialsProcessing = new CredentialsProcessing_default(settings);
|
|
1709
|
-
this.credentialsProcessing.getRESTAPIContext = returnTheContext.bind(this);
|
|
1710
|
-
}
|
|
1711
|
-
}
|
|
1712
|
-
/**
|
|
1713
|
-
* Основной (базовый) метод API: выполняет мультизапрос (или одиночный запрос).
|
|
1714
|
-
*
|
|
1715
|
-
* @param inputRequests - путь, объект описания запроса или их массив.
|
|
1716
|
-
* @param settings - общие настройки запроса (формат ответа, тосты, сообщения и т.п.).
|
|
1717
|
-
* @returns Промис с результатом (форма зависит от isResponseAsObject).
|
|
1718
|
-
*/
|
|
1719
|
-
// ! Основной (базовый) метод API, мультизапросы
|
|
1720
|
-
async doRequest(inputRequests, settings) {
|
|
1721
|
-
if (typeof inputRequests !== "string" && typeof inputRequests !== "object") {
|
|
1722
|
-
return Promise.reject(new Error(this.BAD_REQUEST_DATA_TEXT));
|
|
1723
|
-
}
|
|
1724
|
-
const API_CONTEXT = this;
|
|
1725
|
-
const { isResponseAsObject, isGetBody, callback, ...partialRestSettings } = settings || {};
|
|
1726
|
-
const {
|
|
1727
|
-
commonSuccessMessage: CSMfromSettings,
|
|
1728
|
-
commonErrorMessage: CEMfromSettings,
|
|
1729
|
-
successMessageType: SMTfromSettings,
|
|
1730
|
-
isToastResult: isToastFromSettings,
|
|
1731
|
-
toastOptions: TOFomSettings,
|
|
1732
|
-
isNoToastSuccess: isNTSFromSettings,
|
|
1733
|
-
isNoToastError: isNTEFromSettings,
|
|
1734
|
-
isNoToast: isNoToastFromSettings,
|
|
1735
|
-
successMessages,
|
|
1736
|
-
errorMessages
|
|
1737
|
-
} = partialRestSettings || {};
|
|
1738
|
-
const instance = await getInstanceOfFetchSystem.call(this);
|
|
1739
|
-
if (!instance) {
|
|
1740
|
-
throw new Error("It is impossible to make a request!");
|
|
1741
|
-
}
|
|
1742
|
-
instance.setIsResponseAsObject(isResponseAsObject ?? true);
|
|
1743
|
-
if (typeof callback === "function") instance.setCallback(callback);
|
|
1744
|
-
function getRequests() {
|
|
1745
|
-
let output;
|
|
1746
|
-
if (typeof inputRequests === "string") output = [{ path: inputRequests }];
|
|
1747
|
-
else output = Array.isArray(inputRequests) ? inputRequests : [inputRequests];
|
|
1748
|
-
function getCallback(item, mesageOptions) {
|
|
1749
|
-
const getBodyAs = typeof item.getBodyAs === "string" ? item.getBodyAs : void 0;
|
|
1750
|
-
const finalIsGetBody = typeof item.isGetBody === "boolean" || typeof item.isGetBody === "string" ? item.isGetBody : isGetBody;
|
|
1751
|
-
const finalIsGetBodyFirst = finalIsGetBody === "first";
|
|
1752
|
-
const checkResponseCallback = finalIsGetBodyFirst ? async (res, options) => API_CONTEXT.getResponseBody(await API_CONTEXT.checkResponseCode(res, options), getBodyAs) : async (res, options) => API_CONTEXT.checkResponseCode(res, options);
|
|
1753
|
-
const itemCallback = item.callback;
|
|
1754
|
-
const callbackFn = typeof itemCallback === "function" ? async (res) => itemCallback(await checkResponseCallback(res, mesageOptions)) : async (res) => checkResponseCallback(res, mesageOptions);
|
|
1755
|
-
return finalIsGetBody && !finalIsGetBodyFirst ? async (res) => API_CONTEXT.getResponseBody(await callbackFn(res), getBodyAs) : callbackFn;
|
|
1756
|
-
}
|
|
1757
|
-
async function getRequestItem(item, idx) {
|
|
1758
|
-
const itemObj = getIsOnlyAnObject(item) ? item : { path: item };
|
|
1759
|
-
const { type, ...partialRestFirst } = itemObj;
|
|
1760
|
-
const itemAfterRequestCreating = await (async () => {
|
|
1761
|
-
const key = `createRequest_${typeof type === "string" ? type : "default"}`;
|
|
1762
|
-
const creator = key in API_CONTEXT ? API_CONTEXT[key] : void 0;
|
|
1763
|
-
const result = typeof creator === "function" ? creator.call(API_CONTEXT, partialRestFirst, "doRequestMapping") : API_CONTEXT.createRequest_default(partialRestFirst, "doRequestMapping");
|
|
1764
|
-
const awaited = await result;
|
|
1765
|
-
return getIsOnlyAnObject(awaited) ? awaited : {};
|
|
1766
|
-
})();
|
|
1767
|
-
const { fullPath, api, path, query, queryParameters, ...partialRestSecond } = itemAfterRequestCreating;
|
|
1768
|
-
const {
|
|
1769
|
-
successMess,
|
|
1770
|
-
commonSuccessMessage,
|
|
1771
|
-
successMessageType,
|
|
1772
|
-
errorMess,
|
|
1773
|
-
commonErrorMessage,
|
|
1774
|
-
isToastResult,
|
|
1775
|
-
toastOptions,
|
|
1776
|
-
isNoToastSuccess,
|
|
1777
|
-
isNoToastError,
|
|
1778
|
-
isNoToast,
|
|
1779
|
-
...rest
|
|
1780
|
-
} = partialRestSecond;
|
|
1781
|
-
const successMessagesArr = Array.isArray(successMessages) ? successMessages : void 0;
|
|
1782
|
-
const errorMessagesArr = Array.isArray(errorMessages) ? errorMessages : void 0;
|
|
1783
|
-
const useSuccessMessageFlag = Boolean(
|
|
1784
|
-
successMess || commonSuccessMessage || successMessagesArr?.[idx] || CSMfromSettings || isToastResult || isToastFromSettings
|
|
1785
|
-
);
|
|
1786
|
-
const isUseSuccessToast = useSuccessMessageFlag && !isNoToast && !isNoToastFromSettings && !isNoToastSuccess && !isNTSFromSettings;
|
|
1787
|
-
const isUseErrorToast = !isNoToast && !isNoToastFromSettings && !isNoToastError && !isNTEFromSettings;
|
|
1788
|
-
const mesageOptions = {
|
|
1789
|
-
successMess: successMess || commonSuccessMessage || successMessagesArr?.[idx] || CSMfromSettings,
|
|
1790
|
-
successMessageType: successMessageType || SMTfromSettings,
|
|
1791
|
-
errorMess: errorMess || commonErrorMessage || errorMessagesArr?.[idx] || CEMfromSettings,
|
|
1792
|
-
isUseSuccessToast,
|
|
1793
|
-
isUseErrorToast,
|
|
1794
|
-
toastOptions: toastOptions || TOFomSettings
|
|
1795
|
-
};
|
|
1796
|
-
return {
|
|
1797
|
-
...rest,
|
|
1798
|
-
path: `${fullPath || await API_CONTEXT.getRootPath(api) + (typeof path === "string" ? path : "")}`,
|
|
1799
|
-
// ? Запускаем самовызывающуюся асинхронную ф-ю, ждем резолва промиса от нее
|
|
1800
|
-
queryParameters: await (async () => {
|
|
1801
|
-
const queryParams = query || queryParameters || "";
|
|
1802
|
-
const preparedQueryParams = await API_CONTEXT.processQueryParams(queryParams);
|
|
1803
|
-
return preparedQueryParams;
|
|
1804
|
-
})(),
|
|
1805
|
-
mesageOptions,
|
|
1806
|
-
callback: getCallback(itemAfterRequestCreating, mesageOptions)
|
|
1807
|
-
};
|
|
1808
|
-
}
|
|
1809
|
-
return output.map((item, idx) => getRequestItem(item, idx));
|
|
1810
|
-
}
|
|
1811
|
-
return instance.request(await Promise.all(getRequests()));
|
|
1812
|
-
}
|
|
1813
|
-
/**
|
|
1814
|
-
* Метод API для одиночных запросов: применяет крейтер по `type` и делегирует в {@link RESTAPI.doRequest}.
|
|
1815
|
-
*
|
|
1816
|
-
* @param requestSettings - объект описания одиночного запроса (с необязательным `type`).
|
|
1817
|
-
* @returns Промис с результатом запроса.
|
|
1818
|
-
*/
|
|
1819
|
-
// ! Метод API для одиночных запросов
|
|
1820
|
-
async doMonoRequest(requestSettings) {
|
|
1821
|
-
if (!getIsOnlyAnObject(requestSettings)) throw new Error(`${this.BAD_REQUEST_DATA_TEXT} [RESTAPI.doMonoRequest]`);
|
|
1822
|
-
const { type, ...requestSettingsRest } = requestSettings;
|
|
1823
|
-
const key = `createRequest_${typeof type === "string" ? type : ""}`;
|
|
1824
|
-
const creator = type && key in this ? this[key] : void 0;
|
|
1825
|
-
const created = typeof creator === "function" ? await creator.call(this, requestSettingsRest) : await this.createRequest_default(requestSettingsRest);
|
|
1826
|
-
const doRequestArgs = Array.isArray(created) ? created : [created];
|
|
1827
|
-
return this.doRequest(doRequestArgs[0], doRequestArgs[1]);
|
|
1828
|
-
}
|
|
1829
|
-
};
|
|
1830
|
-
var RESTAPI_default = RESTAPI;
|
|
1831
|
-
export {
|
|
1832
|
-
AbortableFetch_default as AbortableFetch,
|
|
1833
|
-
AnimatedHandler_default as AnimatedHandler,
|
|
1834
|
-
RESTAPI_default as RESTAPI
|
|
1835
|
-
};
|
|
1836
|
-
//# sourceMappingURL=classes.js.map
|