intelicoreact 2.0.8 → 2.0.10
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/Atomic/FormElements/Dropdown/components/DropdownLoader.d.ts +4 -0
- package/dist/Atomic/FormElements/FormattedRawSSN/FormattedRawSSN_old.d.ts +11 -0
- package/dist/Atomic/FormElements/NumericInput/NumericInput.d.ts +36 -0
- package/dist/Atomic/FormElements/RangeCalendar/RangeCalendar.d.ts +2 -0
- package/dist/Atomic/FormElements/RangeSlider/RangeSlider.d.ts +19 -0
- package/dist/Atomic/FormElements/SwitcherTagsDropdown/partial/States.d.ts +5 -0
- package/dist/Atomic/FormElements/VariantsListRadio/VariantsListRadio.d.ts +17 -0
- package/dist/Atomic/FormElements/VariantsListRadio/partials/VariantsListRadioItem.d.ts +12 -0
- package/dist/Atomic/FormElements/WidgetPseudoTable/WidgetPseudoTable.d.ts +2 -0
- package/dist/Atomic/FormElements/WidgetPseudoTable/partial/constructor.d.ts +23 -0
- package/dist/Atomic/FormElements/WidgetWithSwitchableRows/WidgetWithSwitchableRows.d.ts +2 -0
- package/dist/Atomic/FormElements/WidgetWithSwitchableRows/partial/constructor.d.ts +38 -0
- package/dist/Atomic/UI/AccordionTable/AccordionTable.d.ts +10 -0
- package/dist/Atomic/UI/AccordionText/AccordionText.d.ts +8 -0
- package/dist/Atomic/UI/Chart/partial/Chart.constants.d.ts +78 -0
- package/dist/Atomic/UI/Chart/partial/datasetSetters.d.ts +13 -0
- package/dist/Atomic/UI/Chart/partial/optionsConstructor.d.ts +145 -0
- package/dist/Atomic/UI/Chart/partial/optionsSetters.d.ts +4 -0
- package/dist/Atomic/UI/CircleProgressBar/CircleProgressBar.d.ts +14 -0
- package/dist/Atomic/UI/ExampleChartIntegration/ExampleChartIntegration.d.ts +2 -0
- package/dist/Atomic/UI/ExampleChartIntegration/partial/utils.d.ts +4 -0
- package/dist/Atomic/UI/MonoAccordion/MonoAccordion._test.d.ts +1 -0
- package/dist/Atomic/UI/MonoAccordion/MonoAccordion.d.ts +12 -0
- package/dist/Atomic/UI/PieChart/PieChart.d.ts +8 -0
- package/dist/Atomic/UI/Table/Partials/TdCell.d.ts +13 -0
- package/dist/Atomic/UI/Table/Partials/TdHeader.d.ts +5 -0
- package/dist/Atomic/UI/Table/Partials/TdRow.d.ts +17 -0
- package/dist/Atomic/UI/Table/Partials/TdTitle.d.ts +5 -0
- package/dist/Atomic/UI/Table/Table.d.ts +9 -0
- package/dist/Atomic/UI/Table/TdTypes/TdActions.d.ts +6 -0
- package/dist/Atomic/UI/Table/TdTypes/TdPriority.d.ts +6 -0
- package/dist/Atomic/UI/Table/TdTypes/TdRange.d.ts +4 -0
- package/dist/Atomic/UI/Table/TdTypes/TdWeight.d.ts +7 -0
- package/dist/Atomic/UI/WizardStepper/constructor.d.ts +51 -0
- package/dist/Classes/AbortableFetch.d.ts +43 -0
- package/dist/Classes/AnimatedHandler.d.ts +4 -0
- package/dist/Classes/RESTAPI/index.d.ts +31 -0
- package/dist/Classes/RESTAPI/partials/AbortableFetch.d.ts +48 -0
- package/dist/Classes/RESTAPI/partials/ApiBase.d.ts +21 -0
- package/dist/Classes/RESTAPI/partials/ApiRequestCreators.d.ts +58 -0
- package/dist/Classes/RESTAPI/partials/ApiUtils.d.ts +63 -0
- package/dist/Classes/RESTAPI/partials/CredentialsProcessing.d.ts +79 -0
- package/dist/Classes/RESTAPI/partials/Utils.d.ts +20 -0
- package/dist/Classes/RESTAPI/partials/_utils.d.ts +54 -0
- package/dist/Classes/RESTAPI/partials/sse.d.ts +27 -0
- package/dist/Classes/RESTAPI/partials/types.d.ts +159 -0
- package/dist/Constants/index.constants.d.ts +20 -0
- package/dist/Functions/Portal.d.ts +6 -0
- package/dist/Functions/customEventListener.d.ts +27 -0
- package/dist/Functions/dateTime.d.ts +95 -0
- package/dist/Functions/fieldValueFormatters.d.ts +19 -0
- package/dist/Functions/hooks/useFormFieldsChangesManager.d.ts +15 -0
- package/dist/Functions/locale/createTranslator.d.ts +3 -0
- package/dist/Functions/operations.d.ts +1 -0
- package/dist/Functions/presets/inputMaskPresets.d.ts +136 -0
- package/dist/Functions/presets/inputPresets.d.ts +16 -0
- package/dist/Functions/presets/mobileKeyboardTypesPresets.d.ts +17 -0
- package/dist/Functions/schemas.d.ts +3 -0
- package/dist/Functions/sdk/runtime-sdk/client.d.ts +1 -1
- package/dist/Functions/useBodyScrollLock.d.ts +2 -0
- package/dist/Functions/useClickOutside.d.ts +1 -0
- package/dist/Functions/useDebounce.d.ts +4 -0
- package/dist/Functions/useFieldFocus.d.ts +7 -0
- package/dist/Functions/useFormTools/form-drivers/ArrayWithObjects.d.ts +15 -0
- package/dist/Functions/useFormTools/form-drivers/ObjectWithIterableObjects.d.ts +12 -0
- package/dist/Functions/useFormTools/form-drivers/ObjectWithNamedKeyObjects.d.ts +15 -0
- package/dist/Functions/useFormTools/functions/General.d.ts +15 -0
- package/dist/Functions/useFormTools/functions/RenderFields.d.ts +7 -0
- package/dist/Functions/useFormTools/functions/usePrevious.d.ts +2 -0
- package/dist/Functions/useFormTools/index.d.ts +86 -0
- package/dist/Functions/useInputHighlightError.d.ts +12 -0
- package/dist/Functions/useLocalStorage.d.ts +2 -0
- package/dist/Functions/useLocationParams.d.ts +1 -0
- package/dist/Functions/useMediaQuery.d.ts +2 -0
- package/dist/Functions/useMetaInfo.d.ts +8 -0
- package/dist/Functions/useMouseUpOutside.d.ts +1 -0
- package/dist/Functions/useOnlineStatus.d.ts +2 -0
- package/dist/Functions/usePasswordChecker.d.ts +7 -0
- package/dist/Functions/usePrevious.d.ts +2 -0
- package/dist/Functions/useResize.d.ts +3 -0
- package/dist/Functions/useScrollTo.d.ts +2 -0
- package/dist/Functions/useToggle.d.ts +7 -0
- package/dist/Functions/utils.d.ts +40 -0
- package/dist/Langs.d.ts +179 -0
- package/dist/Molecular/FormWithDependOn/FormWithDependOn.d.ts +3 -0
- package/dist/Molecular/FormWithDependOn/FormWithDependOn.interface.d.ts +2 -2
- package/dist/Molecular/FormWithDependOn/partials/_utils.d.ts +8 -0
- package/dist/charts.cjs.map +1 -1
- package/dist/classes.cjs +629 -237
- package/dist/classes.cjs.map +4 -4
- package/dist/classes.js +629 -237
- package/dist/classes.js.map +4 -4
- package/dist/index.cjs +627 -235
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +627 -235
- package/dist/index.js.map +4 -4
- package/dist/sdk.cjs.map +1 -1
- package/dist/sdk.d.ts +1 -1
- package/dist/sdk.js.map +1 -1
- package/package.json +5 -3
- package/styles.css +1 -0
package/dist/index.cjs
CHANGED
|
@@ -662,7 +662,11 @@ var AnimatedHandler = class {
|
|
|
662
662
|
};
|
|
663
663
|
var AnimatedHandler_default = AnimatedHandler;
|
|
664
664
|
|
|
665
|
-
// src/Classes/RESTAPI/partials/AbortableFetch.
|
|
665
|
+
// src/Classes/RESTAPI/partials/AbortableFetch.ts
|
|
666
|
+
var HTTP_METHODS = ["GET", "HEAD", "POST", "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE", "PATCH"];
|
|
667
|
+
function isHttpMethod(value) {
|
|
668
|
+
return HTTP_METHODS.includes(value);
|
|
669
|
+
}
|
|
666
670
|
var RESPONSE_AS_OBJECT_ALWAYS_VALUE2 = "always";
|
|
667
671
|
var AbortableFetch2 = class {
|
|
668
672
|
#pathPrefix = null;
|
|
@@ -675,6 +679,8 @@ var AbortableFetch2 = class {
|
|
|
675
679
|
#catchCallback = null;
|
|
676
680
|
#everyPromiseCallback = null;
|
|
677
681
|
#isResponseAsObject = false;
|
|
682
|
+
// ? Последний вход request() — используется repeatRequest() для повторного запроса той же пачки.
|
|
683
|
+
requestInput = [];
|
|
678
684
|
constructor(input) {
|
|
679
685
|
if (input && !getIsOnlyAnObject(input)) throw new Error("Not valid input value!");
|
|
680
686
|
this.getPathPrefix = this.getPathPrefix.bind(this);
|
|
@@ -705,20 +711,30 @@ var AbortableFetch2 = class {
|
|
|
705
711
|
this.repeatRequest = this.repeatRequest.bind(this);
|
|
706
712
|
this.setProps(input || {});
|
|
707
713
|
}
|
|
714
|
+
/**
|
|
715
|
+
* Выполняет один или несколько HTTP-запросов (нативный fetch) с возможностью отмены.
|
|
716
|
+
*
|
|
717
|
+
* Метод `abort()` навешивается на прототип возвращаемого промиса (как в исходной реализации),
|
|
718
|
+
* что позволяет отменить всю цепочку запросов вызовом `abort()` на возвращённом промисе.
|
|
719
|
+
*
|
|
720
|
+
* @param props - путь, объект описания запроса или их массив.
|
|
721
|
+
* @returns Промис с результатом (форма зависит от isResponseAsObject); на прототипе доступен `abort()`.
|
|
722
|
+
*/
|
|
708
723
|
async request(props) {
|
|
709
724
|
if (!getIsOnlyAnObject(props) && !Array.isArray(props) && typeof props !== "string") throw new Error("Not valid props value!");
|
|
710
|
-
const stringifyBody = (b) => b
|
|
725
|
+
const stringifyBody = (b) => b instanceof FormData ? b : JSON.stringify(b);
|
|
711
726
|
this.requestInput = props;
|
|
712
727
|
const requests = getRequestsArray.call(this, props);
|
|
713
728
|
const ABORTABLE_FETCH_CONTEXT = this;
|
|
714
729
|
const abortController = new AbortController();
|
|
715
730
|
const addProps = (response, request) => {
|
|
716
|
-
response
|
|
717
|
-
|
|
718
|
-
|
|
731
|
+
return Object.assign(response, {
|
|
732
|
+
request,
|
|
733
|
+
...ABORTABLE_FETCH_CONTEXT.#isResponseAsObject ? { name: getIsOnlyAnObject(request) ? request.name || "" : "" } : {}
|
|
734
|
+
});
|
|
719
735
|
};
|
|
720
|
-
|
|
721
|
-
requests.map(
|
|
736
|
+
const externalRequest = Promise.all(
|
|
737
|
+
requests.map((item) => {
|
|
722
738
|
const safelyQuery = item.path.includes("?") ? `&${item.queryParameters.replace(/\?/g, "")}` : item.queryParameters;
|
|
723
739
|
const internalRequest = fetch(`${item.pathPrefix}${item.path}${safelyQuery}`, {
|
|
724
740
|
...item.options,
|
|
@@ -729,12 +745,15 @@ var AbortableFetch2 = class {
|
|
|
729
745
|
}).then(async (response) => addProps(response, item)).catch(async (response) => {
|
|
730
746
|
if (response instanceof Response) return Promise.resolve(addProps(response, item));
|
|
731
747
|
return Promise.resolve(
|
|
732
|
-
addProps(
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
748
|
+
addProps(
|
|
749
|
+
{
|
|
750
|
+
ok: false,
|
|
751
|
+
status: 0,
|
|
752
|
+
statusText: response,
|
|
753
|
+
request: item
|
|
754
|
+
},
|
|
755
|
+
item
|
|
756
|
+
)
|
|
738
757
|
);
|
|
739
758
|
}).then(async (res) => {
|
|
740
759
|
return typeof ABORTABLE_FETCH_CONTEXT.#everyPromiseCallback === "function" && !item.isSkipEveryPromiseCallback ? await ABORTABLE_FETCH_CONTEXT.#everyPromiseCallback(res) : res;
|
|
@@ -743,7 +762,8 @@ var AbortableFetch2 = class {
|
|
|
743
762
|
}).then(async (res) => {
|
|
744
763
|
return { request: item, response: res, ...item.name ? { name: item.name } : {} };
|
|
745
764
|
});
|
|
746
|
-
|
|
765
|
+
const internalProto = Object.getPrototypeOf(internalRequest);
|
|
766
|
+
internalProto.abort = () => abortController.abort();
|
|
747
767
|
return internalRequest;
|
|
748
768
|
})
|
|
749
769
|
).then(async (resArr) => {
|
|
@@ -751,16 +771,17 @@ var AbortableFetch2 = class {
|
|
|
751
771
|
return ABORTABLE_FETCH_CONTEXT.#isResponseAsObject ? {} : [];
|
|
752
772
|
}
|
|
753
773
|
if (ABORTABLE_FETCH_CONTEXT.#isResponseAsObject === RESPONSE_AS_OBJECT_ALWAYS_VALUE2) {
|
|
754
|
-
return resArr.reduce((ac, item) => ({ ...ac, [item.name]: item.response }), {});
|
|
774
|
+
return resArr.reduce((ac, item) => ({ ...ac, [String(item.name)]: item.response }), {});
|
|
755
775
|
}
|
|
756
776
|
if (resArr.length === 1) return resArr[0].response;
|
|
757
|
-
return ABORTABLE_FETCH_CONTEXT.#isResponseAsObject === true ? resArr.reduce((ac, item) => ({ ...ac, [item.name]: item.response }), {}) : resArr.map((item) => item.response);
|
|
777
|
+
return ABORTABLE_FETCH_CONTEXT.#isResponseAsObject === true ? resArr.reduce((ac, item) => ({ ...ac, [String(item.name)]: item.response }), {}) : resArr.map((item) => item.response);
|
|
758
778
|
}).then(async (res) => {
|
|
759
779
|
return typeof ABORTABLE_FETCH_CONTEXT.#callback === "function" ? await ABORTABLE_FETCH_CONTEXT.#callback(res) : res;
|
|
760
780
|
}).catch(async (res) => {
|
|
761
781
|
return typeof ABORTABLE_FETCH_CONTEXT.#catchCallback === "function" ? await ABORTABLE_FETCH_CONTEXT.#catchCallback(res) : res;
|
|
762
782
|
});
|
|
763
|
-
|
|
783
|
+
const externalProto = Object.getPrototypeOf(externalRequest);
|
|
784
|
+
externalProto.abort = () => abortController.abort();
|
|
764
785
|
return externalRequest;
|
|
765
786
|
function getRequestsArray(input) {
|
|
766
787
|
const requestsArray = (() => {
|
|
@@ -785,15 +806,17 @@ var AbortableFetch2 = class {
|
|
|
785
806
|
callback: omitCallback,
|
|
786
807
|
mergeProps: omitMergeProps,
|
|
787
808
|
...optionsRest
|
|
788
|
-
} = options
|
|
809
|
+
} = getIsOnlyAnObject(options) ? options : {};
|
|
810
|
+
const localMethod = typeof method === "string" && isHttpMethod(method) ? method : null;
|
|
811
|
+
const localCallback = typeof callback === "function" ? (res) => callback(res) : void 0;
|
|
789
812
|
return [
|
|
790
813
|
...ac,
|
|
791
814
|
{
|
|
792
815
|
path,
|
|
793
816
|
pathPrefix: getMergeProps("pathPrefix") === "onlyLocal" || isNoPathPrefix ? "" : this.#pathPrefix || "",
|
|
794
817
|
method: (() => {
|
|
795
|
-
if (getMergeProps("method") === "onlyLocal") return
|
|
796
|
-
return getMergeProps("method") === "onlyGlobal" ? this.#method || "GET" :
|
|
818
|
+
if (getMergeProps("method") === "onlyLocal") return localMethod || "GET";
|
|
819
|
+
return getMergeProps("method") === "onlyGlobal" ? this.#method || "GET" : localMethod || this.#method || "GET";
|
|
797
820
|
})(),
|
|
798
821
|
queryParameters: (() => {
|
|
799
822
|
if ((getMergeProps("queryParameters") ?? getMergeProps("query")) === "onlyLocal") {
|
|
@@ -802,31 +825,34 @@ var AbortableFetch2 = class {
|
|
|
802
825
|
return (getMergeProps("queryParameters") ?? getMergeProps("query")) === "onlyGlobal" ? this.getQueryString(this.getQueryArray(this.#queryParameters)) : this.getQueryString([...this.getQueryArray(this.#queryParameters), ...this.getQueryArray(queryParameters)]);
|
|
803
826
|
})(),
|
|
804
827
|
headers: (() => {
|
|
805
|
-
if (getMergeProps("headers") === "onlyLocal") return this.getHeadersObj(headers
|
|
828
|
+
if (getMergeProps("headers") === "onlyLocal") return this.getHeadersObj(getIsOnlyAnObject(headers) ? headers : {});
|
|
806
829
|
return getMergeProps("headers") === "onlyGlobal" ? this.getHeadersObj({ ...this.#headers || {} }) : this.getHeadersObj({
|
|
807
830
|
...this.#headers || {},
|
|
808
|
-
...headers
|
|
831
|
+
...getIsOnlyAnObject(headers) ? headers : {}
|
|
809
832
|
});
|
|
810
833
|
})(),
|
|
811
834
|
body: (() => {
|
|
812
835
|
if (getMergeProps("body") === "onlyLocal") return body || null;
|
|
813
836
|
if (getMergeProps("body") === "onlyGlobal") return this.#body || null;
|
|
814
837
|
if (body && this.#body && typeof body === typeof this.#body && typeof body === "object") {
|
|
815
|
-
return Array.isArray(body) ? [...this.#body, ...body] : { ...this.#body, ...body };
|
|
816
|
-
} else
|
|
838
|
+
return Array.isArray(body) ? [...Array.isArray(this.#body) ? this.#body : [], ...body] : { ...getIsOnlyAnObject(this.#body) ? this.#body : {}, ...getIsOnlyAnObject(body) ? body : {} };
|
|
839
|
+
} else {
|
|
840
|
+
return body || this.#body || null;
|
|
841
|
+
}
|
|
817
842
|
})(),
|
|
818
843
|
options: (() => {
|
|
819
|
-
if (getMergeProps("options") === "onlyLocal") return { ...optionsRest
|
|
820
|
-
return getMergeProps("options") === "onlyGlobal" ? { ...this.#options || {} } : { ...this.#options || {}, ...optionsRest
|
|
844
|
+
if (getMergeProps("options") === "onlyLocal") return { ...optionsRest };
|
|
845
|
+
return getMergeProps("options") === "onlyGlobal" ? { ...this.#options || {} } : { ...this.#options || {}, ...optionsRest };
|
|
821
846
|
})(),
|
|
822
|
-
callback,
|
|
823
|
-
isSkipEveryPromiseCallback,
|
|
847
|
+
callback: localCallback,
|
|
848
|
+
isSkipEveryPromiseCallback: Boolean(isSkipEveryPromiseCallback),
|
|
824
849
|
...this.getIsResponseAsObject() ? { name: name && typeof name === "string" ? name : index } : {}
|
|
825
850
|
}
|
|
826
851
|
];
|
|
827
852
|
}, []);
|
|
828
853
|
}
|
|
829
854
|
}
|
|
855
|
+
/** Повторяет последний выполненный запрос (ту же пачку). */
|
|
830
856
|
repeatRequest() {
|
|
831
857
|
return this.request(this.requestInput);
|
|
832
858
|
}
|
|
@@ -842,19 +868,23 @@ var AbortableFetch2 = class {
|
|
|
842
868
|
return this.#method;
|
|
843
869
|
}
|
|
844
870
|
setMethod(value) {
|
|
845
|
-
|
|
846
|
-
if (value && !methods.includes(value)) throw new Error("Not valid method value!");
|
|
871
|
+
if (value && !isHttpMethod(value)) throw new Error("Not valid method value!");
|
|
847
872
|
this.#method = value || null;
|
|
848
873
|
}
|
|
849
874
|
getQueryParameters() {
|
|
850
875
|
return this.#queryParameters;
|
|
851
876
|
}
|
|
852
877
|
getQueryArray(value) {
|
|
853
|
-
if (typeof value === "string")
|
|
854
|
-
|
|
855
|
-
else if (
|
|
856
|
-
return
|
|
857
|
-
} else
|
|
878
|
+
if (typeof value === "string") {
|
|
879
|
+
return (value[0] === "?" ? value.slice(1) : value).split("&");
|
|
880
|
+
} else if (Array.isArray(value)) {
|
|
881
|
+
return value.map((item) => `${item}`);
|
|
882
|
+
} else if (typeof value === "object" && value !== null) {
|
|
883
|
+
const record = getIsOnlyAnObject(value) ? value : {};
|
|
884
|
+
return Object.keys(record).filter((key) => Boolean(key) && Boolean(record[key])).map((key) => `${key}=${record[key]}`);
|
|
885
|
+
} else {
|
|
886
|
+
return [];
|
|
887
|
+
}
|
|
858
888
|
}
|
|
859
889
|
getQueryString(value) {
|
|
860
890
|
if (!value) return "";
|
|
@@ -873,7 +903,7 @@ var AbortableFetch2 = class {
|
|
|
873
903
|
if (!obj) return headers;
|
|
874
904
|
if (typeof obj !== "object" || Array.isArray(obj)) throw new Error("Not valid headers value!");
|
|
875
905
|
Object.keys(obj).forEach((key) => {
|
|
876
|
-
headers.append(key, obj[key]);
|
|
906
|
+
headers.append(key, `${obj[key]}`);
|
|
877
907
|
});
|
|
878
908
|
return headers;
|
|
879
909
|
}
|
|
@@ -949,39 +979,64 @@ var AbortableFetch2 = class {
|
|
|
949
979
|
// isAnywayRunCallback,
|
|
950
980
|
isResponseAsObject
|
|
951
981
|
} = input;
|
|
952
|
-
if (pathPrefix) this.setPathPrefix(pathPrefix);
|
|
953
|
-
if (method) this.setMethod(method);
|
|
982
|
+
if (pathPrefix) this.setPathPrefix(typeof pathPrefix === "string" ? pathPrefix : null);
|
|
983
|
+
if (method) this.setMethod(typeof method === "string" && isHttpMethod(method) ? method : null);
|
|
954
984
|
if (queryParameters) this.setQueryParameters(this.getQueryArray(queryParameters));
|
|
955
|
-
if (headers) this.setHeaders(headers);
|
|
985
|
+
if (headers) this.setHeaders(getIsOnlyAnObject(headers) ? headers : null);
|
|
956
986
|
if (body) this.setBody(body);
|
|
957
|
-
if (options) this.setOptions(options);
|
|
958
|
-
if (callback
|
|
959
|
-
|
|
960
|
-
|
|
987
|
+
if (options) this.setOptions(getIsOnlyAnObject(options) ? options : null);
|
|
988
|
+
if (callback && typeof callback === "function") {
|
|
989
|
+
const fn = callback;
|
|
990
|
+
this.setCallback(function wrappedCallback(response) {
|
|
991
|
+
return fn.call(this, response);
|
|
992
|
+
});
|
|
993
|
+
}
|
|
994
|
+
if (catchCallback && typeof catchCallback === "function") {
|
|
995
|
+
const fn = catchCallback;
|
|
996
|
+
this.setCatchCallback(function wrappedCatchCallback(response) {
|
|
997
|
+
return fn.call(this, response);
|
|
998
|
+
});
|
|
999
|
+
}
|
|
1000
|
+
if (everyPromiseCallback && typeof everyPromiseCallback === "function") {
|
|
1001
|
+
const fn = everyPromiseCallback;
|
|
1002
|
+
this.setEveryPromiseCallback(function wrappedEveryPromiseCallback(response) {
|
|
1003
|
+
return fn.call(this, response);
|
|
1004
|
+
});
|
|
1005
|
+
}
|
|
961
1006
|
if (isResponseAsObject !== void 0) this.setIsResponseAsObject(isResponseAsObject);
|
|
962
1007
|
}
|
|
963
1008
|
};
|
|
964
1009
|
var AbortableFetch_default2 = AbortableFetch2;
|
|
965
1010
|
|
|
966
|
-
// src/Classes/RESTAPI/partials/_utils.
|
|
1011
|
+
// src/Classes/RESTAPI/partials/_utils.ts
|
|
967
1012
|
function getIsOnlyAnObject(input) {
|
|
968
|
-
return typeof input === "object" &&
|
|
969
|
-
input instanceof Object && // "отбивает" null
|
|
970
|
-
!Array.isArray(input) && // "отбивает" массивы
|
|
971
|
-
!(input instanceof Set) && // "отбивает" сеты
|
|
972
|
-
!(input instanceof Map);
|
|
1013
|
+
return typeof input === "object" && input instanceof Object && !Array.isArray(input) && !(input instanceof Set) && !(input instanceof Map);
|
|
973
1014
|
}
|
|
974
|
-
|
|
1015
|
+
function clone(input) {
|
|
975
1016
|
if (input === null || typeof input !== "object") return input;
|
|
976
|
-
|
|
977
|
-
|
|
1017
|
+
if (Array.isArray(input)) return input.map((item) => clone(item));
|
|
1018
|
+
const source = getIsOnlyAnObject(input) ? input : {};
|
|
1019
|
+
const data = {};
|
|
1020
|
+
Object.keys(source).forEach((key) => {
|
|
1021
|
+
data[key] = clone(source[key]);
|
|
1022
|
+
});
|
|
978
1023
|
return data;
|
|
979
|
-
}
|
|
980
|
-
|
|
981
|
-
const
|
|
982
|
-
|
|
983
|
-
}
|
|
984
|
-
|
|
1024
|
+
}
|
|
1025
|
+
function omitKeys(obj, keys = []) {
|
|
1026
|
+
const source = obj ?? {};
|
|
1027
|
+
const keySet = new Set(keys);
|
|
1028
|
+
const result = {};
|
|
1029
|
+
Object.keys(source).forEach((key) => {
|
|
1030
|
+
if (!keySet.has(key)) result[key] = source[key];
|
|
1031
|
+
});
|
|
1032
|
+
return result;
|
|
1033
|
+
}
|
|
1034
|
+
async function getResponseClone(res) {
|
|
1035
|
+
if (res && typeof res === "object" && "clone" in res && typeof res.clone === "function") {
|
|
1036
|
+
return res.clone();
|
|
1037
|
+
}
|
|
1038
|
+
return clone(res);
|
|
1039
|
+
}
|
|
985
1040
|
function addCustomMethods(data, prefix) {
|
|
986
1041
|
const preparedPrefix = (prefix || "").toString();
|
|
987
1042
|
Object.keys(data).forEach((key) => {
|
|
@@ -995,7 +1050,7 @@ async function getInstanceOfFetchSystem(isGetBody) {
|
|
|
995
1050
|
let credentials = {};
|
|
996
1051
|
if (CREDENTIALS_CONTEXT) {
|
|
997
1052
|
const cred = await CREDENTIALS_CONTEXT.getCredentials();
|
|
998
|
-
credentials = CREDENTIALS_CONTEXT.isUseRefreshTokensPropcessing ? await CREDENTIALS_CONTEXT.waitRefresh(cred.isNeedRefresh && !CREDENTIALS_CONTEXT.getIsTokenStartRefresh()).then(
|
|
1053
|
+
credentials = CREDENTIALS_CONTEXT.isUseRefreshTokensPropcessing ? await CREDENTIALS_CONTEXT.waitRefresh(Boolean(cred.isNeedRefresh) && !CREDENTIALS_CONTEXT.getIsTokenStartRefresh()).then(
|
|
999
1054
|
async () => CREDENTIALS_CONTEXT.processCredentials(await CREDENTIALS_CONTEXT.getCredentials())
|
|
1000
1055
|
) : cred;
|
|
1001
1056
|
}
|
|
@@ -1013,52 +1068,57 @@ async function getInstanceOfFetchSystem(isGetBody) {
|
|
|
1013
1068
|
}
|
|
1014
1069
|
return (CREDENTIALS_CONTEXT?.isUseRefreshTokensPropcessing ? CREDENTIALS_CONTEXT.waitRefresh() : Promise.resolve()).then(
|
|
1015
1070
|
async () => new AbortableFetch_default2({
|
|
1016
|
-
|
|
1071
|
+
// ? Метод по умолчанию
|
|
1017
1072
|
method: "GET",
|
|
1018
|
-
|
|
1073
|
+
// ? Заголовки по умолчанию
|
|
1019
1074
|
headers: {
|
|
1020
1075
|
...headersToAbortableFetchInstance,
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1076
|
+
// ? (*) Тут обрабатываются кейсы
|
|
1077
|
+
// ? - когда нет this.credentialsProcessing
|
|
1078
|
+
// ? (мы НЕ хотим добавлять токены в принципе, не зашли в верхнюю if-ку)
|
|
1079
|
+
// ? - когда есть this.credentialsProcessing, но нет credentials.token (не авторизованы)
|
|
1080
|
+
// ? (зашли в верхнюю if-ку, попробовали получить/обновить креды)
|
|
1026
1081
|
...credentials.token ? CREDENTIALS_CONTEXT?.getHeadersForAuthorize?.(credentials.token) || {} : {}
|
|
1027
1082
|
},
|
|
1028
1083
|
queryParameters: await API_CONTEXT.processQueryParams(queryParamsToAbortableFetchInstance),
|
|
1029
|
-
|
|
1084
|
+
// ? Опции по умолчанию
|
|
1030
1085
|
options: {
|
|
1031
1086
|
mode: "cors",
|
|
1032
1087
|
redirect: "follow",
|
|
1033
1088
|
...optionsToAbortableFetchInstance
|
|
1034
1089
|
},
|
|
1035
|
-
|
|
1090
|
+
// ? Каждый запрос (каждый запрос мультизапроса), сделаный методом request этого экземпляра выполнит этот колбек
|
|
1036
1091
|
everyPromiseCallback: async function everyPromiseCallback(response) {
|
|
1037
1092
|
const ABORTABLE_FETCH_INSTANCE = this;
|
|
1038
1093
|
if (!response.status) {
|
|
1039
|
-
const
|
|
1040
|
-
const
|
|
1094
|
+
const reqInput = ABORTABLE_FETCH_INSTANCE.requestInput;
|
|
1095
|
+
const responseRequest = getIsOnlyAnObject(response.request) ? response.request : {};
|
|
1096
|
+
const request = Array.isArray(reqInput) ? reqInput.find((item) => getIsOnlyAnObject(item) && item.path === responseRequest.path) : void 0;
|
|
1097
|
+
const mesageOptions = getIsOnlyAnObject(request) && getIsOnlyAnObject(request.mesageOptions) ? request.mesageOptions : void 0;
|
|
1098
|
+
const isUseErrorToast = mesageOptions?.isUseErrorToast;
|
|
1041
1099
|
if (isUseErrorToast) {
|
|
1042
|
-
API_CONTEXT.sendMessage?.(API_CONTEXT.NO_INET,
|
|
1100
|
+
API_CONTEXT.sendMessage?.(API_CONTEXT.NO_INET, mesageOptions, response);
|
|
1043
1101
|
}
|
|
1044
1102
|
}
|
|
1045
|
-
return API_CONTEXT.REJECT_CODES.includes(response.status) || CREDENTIALS_CONTEXT?.isUseRefreshTokensPropcessing && CREDENTIALS_CONTEXT?.CODES_USING_THE_REFRESH_ATTEMPT?.includes
|
|
1103
|
+
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));
|
|
1046
1104
|
},
|
|
1047
|
-
|
|
1048
|
-
|
|
1105
|
+
// ? Если хоть один запрос из пачки будет зареджекчен, зареджектится вся пачка.
|
|
1106
|
+
// ? В этом случае будет выполнен этот колбэк
|
|
1049
1107
|
catchCallback: async function catchCallback(res) {
|
|
1050
1108
|
const ABORTABLE_FETCH_INSTANCE = this;
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1109
|
+
if (!CREDENTIALS_CONTEXT) return Promise.reject(res);
|
|
1110
|
+
const code = Number(res instanceof Error ? res.message.split(":")[1] : "");
|
|
1111
|
+
if (CREDENTIALS_CONTEXT.CODES_USING_THE_REFRESH_ATTEMPT?.includes(code)) {
|
|
1112
|
+
const isDoRefresh = !CREDENTIALS_CONTEXT.getIsTokenStartRefresh();
|
|
1113
|
+
return CREDENTIALS_CONTEXT.waitRefresh(isDoRefresh).then(async () => {
|
|
1114
|
+
const newCredentials = await CREDENTIALS_CONTEXT.processCredentials({
|
|
1115
|
+
...await CREDENTIALS_CONTEXT.getCredentials(true),
|
|
1057
1116
|
isCatchCallbackProcess: isDoRefresh
|
|
1058
1117
|
});
|
|
1118
|
+
const currentHeaders = ABORTABLE_FETCH_INSTANCE.getHeaders();
|
|
1059
1119
|
ABORTABLE_FETCH_INSTANCE.setHeaders({
|
|
1060
|
-
...
|
|
1061
|
-
...newCredentials
|
|
1120
|
+
...getIsOnlyAnObject(currentHeaders) ? currentHeaders : {},
|
|
1121
|
+
...newCredentials.token ? { Authorization: `Bearer ${newCredentials.token}` } : {}
|
|
1062
1122
|
});
|
|
1063
1123
|
if (newCredentials.token) return ABORTABLE_FETCH_INSTANCE.repeatRequest();
|
|
1064
1124
|
return Promise.reject(res);
|
|
@@ -1070,13 +1130,23 @@ async function getInstanceOfFetchSystem(isGetBody) {
|
|
|
1070
1130
|
);
|
|
1071
1131
|
}
|
|
1072
1132
|
|
|
1073
|
-
// src/Classes/RESTAPI/partials/Utils.
|
|
1133
|
+
// src/Classes/RESTAPI/partials/Utils.ts
|
|
1074
1134
|
var Utils = class {
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1135
|
+
// ! Могут содержаться НЕасинхронные методы!
|
|
1136
|
+
/**
|
|
1137
|
+
* Нормализатор сложных query-параметров.
|
|
1138
|
+
*
|
|
1139
|
+
* Например: `&key1=&&&===&&&key2====&&&&&&&&key3=...`. Для корректной работы на вход нужно подавать
|
|
1140
|
+
* НЕ кодированные значения. По умолчанию выходные значения query-параметров НЕ кодируются.
|
|
1141
|
+
*
|
|
1142
|
+
* @param queryParams - query в виде строки, массива или объекта.
|
|
1143
|
+
* @param settings - формат вывода (`array` | `string` | `object`) и флаг кодирования.
|
|
1144
|
+
* @returns Нормализованные query-параметры в выбранном формате.
|
|
1145
|
+
*/
|
|
1146
|
+
// ? Ф-я normalizeQueryParams является нормализатором сложных квери
|
|
1147
|
+
// ? Например: &key1=&&&===&&&key2====&&&&&&&&key3=....
|
|
1148
|
+
// ? Для корректной работы на вход нужно подавать НЕ кодированные значения
|
|
1149
|
+
// ? По умолчанию выходные значения квери-параметров НЕ кодируются
|
|
1080
1150
|
normalizeQueryParams(queryParams, settings) {
|
|
1081
1151
|
if (settings && !getIsOnlyAnObject(settings)) {
|
|
1082
1152
|
throw new Error("Bad settings [class Utils, normalizeQueryParams]");
|
|
@@ -1095,9 +1165,13 @@ var Utils = class {
|
|
|
1095
1165
|
if (index === -1) return [item];
|
|
1096
1166
|
return [item.slice(0, index), item.slice(index + 1)];
|
|
1097
1167
|
}).filter(([key]) => Boolean(key)).map(([key, value]) => prepareParam(key, value));
|
|
1098
|
-
} else if (getIsOnlyAnObject(input))
|
|
1099
|
-
|
|
1100
|
-
else
|
|
1168
|
+
} else if (getIsOnlyAnObject(input)) {
|
|
1169
|
+
return Object.keys(input).map((key) => prepareParam(key, input[key]));
|
|
1170
|
+
} else if (typeof input === "string") {
|
|
1171
|
+
return (input[0] === "?" ? input.slice(1) : input).split("&");
|
|
1172
|
+
} else {
|
|
1173
|
+
return [];
|
|
1174
|
+
}
|
|
1101
1175
|
};
|
|
1102
1176
|
const { isEncode = false, outputAs = "array" } = settings || {};
|
|
1103
1177
|
const initialStructure = getInitialArr(queryParams);
|
|
@@ -1114,7 +1188,9 @@ var Utils = class {
|
|
|
1114
1188
|
if (index !== -1 && index !== 0) {
|
|
1115
1189
|
const key = str.slice(0, index);
|
|
1116
1190
|
acc.result.push(`${key}=${encodeURIComponent(str.slice(index + 1))}`);
|
|
1117
|
-
} else
|
|
1191
|
+
} else {
|
|
1192
|
+
acc.toJoin = str;
|
|
1193
|
+
}
|
|
1118
1194
|
if (idx === initialStructure.length - 1 && typeof acc.toJoin === "string") processToJoin(acc.toJoin);
|
|
1119
1195
|
return acc;
|
|
1120
1196
|
},
|
|
@@ -1122,7 +1198,7 @@ var Utils = class {
|
|
|
1122
1198
|
).result;
|
|
1123
1199
|
const outputStructure = normalizedStructure.map((item) => {
|
|
1124
1200
|
const [key, value] = item.split("=");
|
|
1125
|
-
return [key, !isEncode ? decodeURIComponent(value) : value];
|
|
1201
|
+
return [key, !isEncode ? decodeURIComponent(value ?? "") : value ?? ""];
|
|
1126
1202
|
});
|
|
1127
1203
|
switch (outputAs) {
|
|
1128
1204
|
case "string":
|
|
@@ -1136,16 +1212,25 @@ var Utils = class {
|
|
|
1136
1212
|
};
|
|
1137
1213
|
var Utils_default = Utils;
|
|
1138
1214
|
|
|
1139
|
-
// src/Classes/RESTAPI/partials/ApiUtils.
|
|
1215
|
+
// src/Classes/RESTAPI/partials/ApiUtils.ts
|
|
1140
1216
|
var ApiUtils = class extends Utils_default {
|
|
1217
|
+
/** Корневой путь API (раскладывается в ApiBase из constants.API_PATH). */
|
|
1218
|
+
API_PATH;
|
|
1141
1219
|
constructor(settings) {
|
|
1142
1220
|
super();
|
|
1143
1221
|
const { utils } = settings || {};
|
|
1144
1222
|
if (getIsOnlyAnObject(utils)) addCustomMethods.call(this, utils);
|
|
1145
1223
|
}
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1224
|
+
/**
|
|
1225
|
+
* Разбирает единый объект параметров запроса на части в зависимости от варианта использования.
|
|
1226
|
+
*
|
|
1227
|
+
* @param apiParams - объединённые параметры запроса.
|
|
1228
|
+
* @param variant - `'doRequestMapping'` для мультизапроса либо `undefined` для одиночного.
|
|
1229
|
+
* @returns Для `doRequestMapping` — объект параметров; иначе кортеж `[параметры, настройки]`.
|
|
1230
|
+
*/
|
|
1231
|
+
// ? Планируется, что метод будет использоваться неизменно, однако технически его можно перегрузить на экземпляре
|
|
1232
|
+
// ? Метод не планировался как асинхронный,
|
|
1233
|
+
// ? однако ввиду того что он может быть перегружен на экземпляре асинхронность предусматривается
|
|
1149
1234
|
async splitProperties(apiParams, variant) {
|
|
1150
1235
|
const {
|
|
1151
1236
|
isResponseAsObject,
|
|
@@ -1204,79 +1289,224 @@ var ApiUtils = class extends Utils_default {
|
|
|
1204
1289
|
];
|
|
1205
1290
|
}
|
|
1206
1291
|
}
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1292
|
+
/**
|
|
1293
|
+
* Обработчик пропы `api` из объекта описания запроса — возвращает корневой путь API.
|
|
1294
|
+
*
|
|
1295
|
+
* @returns Корневой путь (по умолчанию — API_PATH).
|
|
1296
|
+
*/
|
|
1297
|
+
// ! Обработчик пропы api из объекта описания запроса
|
|
1298
|
+
// ? Планируется, что метод будет перегружаться на экземпляре,
|
|
1299
|
+
// ? т.к. на разных проектах могут быть разные интерпретации пропы api
|
|
1300
|
+
// ? Метод не планировался как асинхронный,
|
|
1301
|
+
// ? однако ввиду того что он может быть перегружен на экземпляре асинхронность предусматривается
|
|
1212
1302
|
async getRootPath() {
|
|
1213
1303
|
return this.API_PATH;
|
|
1214
1304
|
}
|
|
1215
|
-
|
|
1216
|
-
|
|
1305
|
+
/**
|
|
1306
|
+
* Извлекает тело ответа в нужном виде (json/blob/text/arrayBuffer/formData) либо по content-type.
|
|
1307
|
+
*
|
|
1308
|
+
* @param response - объект Response (иначе значение возвращается как есть).
|
|
1309
|
+
* @param getBodyAs - желаемый способ извлечения тела.
|
|
1310
|
+
* @returns Промис с телом ответа (или исходным значением / null при ошибке).
|
|
1311
|
+
*/
|
|
1312
|
+
// ? Планируется, что метод будет использоваться неизменно, однако технически его можно перегрузить на экземпляре
|
|
1313
|
+
// ? Метод планировался как асинхронный
|
|
1217
1314
|
async getResponseBody(response, getBodyAs) {
|
|
1218
1315
|
if (!(response instanceof Response)) return response;
|
|
1219
1316
|
const contentType = response.headers.get("content-type");
|
|
1220
1317
|
if (!contentType) return "";
|
|
1221
|
-
const
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1318
|
+
const bodyReaders = {
|
|
1319
|
+
json: (r) => r.json(),
|
|
1320
|
+
blob: (r) => r.blob(),
|
|
1321
|
+
text: (r) => r.text(),
|
|
1322
|
+
arrayBuffer: (r) => r.arrayBuffer(),
|
|
1323
|
+
formData: (r) => r.formData()
|
|
1324
|
+
};
|
|
1325
|
+
const isBodyKey = (key) => key in bodyReaders;
|
|
1326
|
+
const reader = typeof getBodyAs === "string" && isBodyKey(getBodyAs) ? bodyReaders[getBodyAs] : contentType.includes("text/csv") ? bodyReaders.blob : contentType.includes("json") ? bodyReaders.json : bodyReaders.text;
|
|
1230
1327
|
try {
|
|
1231
|
-
return await
|
|
1328
|
+
return await reader(response);
|
|
1232
1329
|
} catch {
|
|
1233
1330
|
console.log("Failed to extract the body");
|
|
1234
1331
|
return null;
|
|
1235
1332
|
}
|
|
1236
1333
|
}
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1334
|
+
/**
|
|
1335
|
+
* Формирует структуру ошибки из тела ответа (точка расширения под формат бэкенда).
|
|
1336
|
+
*
|
|
1337
|
+
* @param res - уже извлечённое тело ответа.
|
|
1338
|
+
* @returns Структура сообщения об ошибке.
|
|
1339
|
+
*/
|
|
1340
|
+
// ! Обработчик структуры для ошибки (не рендер месседжа, а имеено формирование ошибки),
|
|
1341
|
+
// ? Планируется, что метод будет перегружаться на экземпляре,
|
|
1342
|
+
// ? т.к. на разных проектах могут быть разные структуры тела ответа для ошибки
|
|
1343
|
+
// ? Метод не планировался как асинхронный,
|
|
1344
|
+
// ? однако ввиду того что он может быть перегружен на экземпляре асинхронность предусматривается
|
|
1345
|
+
// ? res - уже тело ответа
|
|
1243
1346
|
async getErrorMessage(res) {
|
|
1244
1347
|
return res;
|
|
1245
1348
|
}
|
|
1246
|
-
|
|
1247
|
-
|
|
1349
|
+
/**
|
|
1350
|
+
* Проверяет код ответа и (если задан sendMessage) информирует пользователя об успехе/ошибке.
|
|
1351
|
+
*
|
|
1352
|
+
* @param res - объект Response (или совместимый с полем `ok`).
|
|
1353
|
+
* @param settings - сообщения и настройки тостов для данного запроса.
|
|
1354
|
+
* @returns Исходный `res` (метод не меняет ответ, только сигналит сообщением).
|
|
1355
|
+
*/
|
|
1356
|
+
// ? Планируется, что метод будет использоваться неизменно, однако технически его можно перегрузить на экземпляре
|
|
1357
|
+
// ? Метод планировался как асинхронный
|
|
1248
1358
|
async checkResponseCode(res, settings) {
|
|
1249
|
-
|
|
1359
|
+
const send = this.sendMessage;
|
|
1360
|
+
if (typeof send !== "function") return res;
|
|
1250
1361
|
const { successMess, errorMess } = settings || {};
|
|
1251
|
-
const
|
|
1362
|
+
const isOk = getIsOnlyAnObject(res) ? Boolean(res.ok) : false;
|
|
1363
|
+
const message = isOk ? successMess || this.DEFAULT_SUCCESS_MESSAGE : errorMess || await this.getErrorMessage(await this.getResponseBody(await getResponseClone(res)));
|
|
1252
1364
|
try {
|
|
1253
|
-
|
|
1254
|
-
} catch
|
|
1365
|
+
send(message, settings, await getResponseClone(res));
|
|
1366
|
+
} catch {
|
|
1255
1367
|
}
|
|
1256
1368
|
return res;
|
|
1257
1369
|
}
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1370
|
+
/**
|
|
1371
|
+
* Структуры, которые будут использоваться для КАЖДОГО запроса, сделанного экземпляром RESTAPI.
|
|
1372
|
+
*
|
|
1373
|
+
* @returns Объект `{ headers, queryParameters, options }` (по умолчанию пустой).
|
|
1374
|
+
*/
|
|
1375
|
+
// ? Суть метода:
|
|
1376
|
+
// ? передать из вне структуры, которые будут использоваться для КАЖДОГО запроса сделанного экземпляром RESTAPI
|
|
1377
|
+
// ! Данные затрут прочие настройки КРОМЕ данных по логике авторизации
|
|
1378
|
+
// ? Планируется, что метод будет перегружаться на экземпляре
|
|
1379
|
+
// ? Метод не планировался как асинхронный,
|
|
1380
|
+
// ? однако ввиду того что он может быть перегружен на экземпляре асинхронность предусматривается
|
|
1264
1381
|
async addAsCommon() {
|
|
1265
1382
|
return {};
|
|
1266
1383
|
}
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1384
|
+
/**
|
|
1385
|
+
* Общий обработчик query-параметров (точка расширения, напр. кодирование/приведение к массиву).
|
|
1386
|
+
*
|
|
1387
|
+
* @param queryParams - входные query-параметры.
|
|
1388
|
+
* @returns Обработанные query-параметры (по умолчанию — без изменений).
|
|
1389
|
+
*/
|
|
1390
|
+
// ! Обработчик квери-параметров для общего процессинга,
|
|
1391
|
+
// ! Например для кодирования decodeURIComponent или/и приведения в формат массива
|
|
1392
|
+
// ? Планируется, что метод будет перегружаться на экземпляре,
|
|
1393
|
+
// ? т.к. на разных проектах могут быть разные договоренности по форматам
|
|
1394
|
+
// ? Метод не планировался как асинхронный,
|
|
1395
|
+
// ? однако ввиду того что он может быть перегружен на экземпляре асинхронность предусматривается
|
|
1273
1396
|
async processQueryParams(queryParams) {
|
|
1274
1397
|
return queryParams;
|
|
1275
1398
|
}
|
|
1276
1399
|
};
|
|
1277
1400
|
var ApiUtils_default = ApiUtils;
|
|
1278
1401
|
|
|
1279
|
-
// src/Classes/RESTAPI/partials/
|
|
1402
|
+
// src/Classes/RESTAPI/partials/sse.ts
|
|
1403
|
+
function parseSSEEvent(block) {
|
|
1404
|
+
if (typeof block !== "string") return null;
|
|
1405
|
+
const event = { event: "message", data: "", id: void 0, retry: void 0 };
|
|
1406
|
+
const dataLines = [];
|
|
1407
|
+
let hasField = false;
|
|
1408
|
+
block.split("\n").forEach((line) => {
|
|
1409
|
+
if (line === "" || line[0] === ":") return;
|
|
1410
|
+
const colonIdx = line.indexOf(":");
|
|
1411
|
+
const field = colonIdx === -1 ? line : line.slice(0, colonIdx);
|
|
1412
|
+
let value = colonIdx === -1 ? "" : line.slice(colonIdx + 1);
|
|
1413
|
+
if (value[0] === " ") value = value.slice(1);
|
|
1414
|
+
switch (field) {
|
|
1415
|
+
case "event":
|
|
1416
|
+
event.event = value;
|
|
1417
|
+
hasField = true;
|
|
1418
|
+
break;
|
|
1419
|
+
case "data":
|
|
1420
|
+
dataLines.push(value);
|
|
1421
|
+
hasField = true;
|
|
1422
|
+
break;
|
|
1423
|
+
case "id":
|
|
1424
|
+
event.id = value;
|
|
1425
|
+
hasField = true;
|
|
1426
|
+
break;
|
|
1427
|
+
case "retry":
|
|
1428
|
+
if (/^\d+$/.test(value)) {
|
|
1429
|
+
event.retry = Number(value);
|
|
1430
|
+
hasField = true;
|
|
1431
|
+
}
|
|
1432
|
+
break;
|
|
1433
|
+
default:
|
|
1434
|
+
break;
|
|
1435
|
+
}
|
|
1436
|
+
});
|
|
1437
|
+
if (!hasField) return null;
|
|
1438
|
+
event.data = dataLines.join("\n");
|
|
1439
|
+
return event;
|
|
1440
|
+
}
|
|
1441
|
+
function safeCall(fn, ...args) {
|
|
1442
|
+
if (typeof fn !== "function") return;
|
|
1443
|
+
try {
|
|
1444
|
+
fn(...args);
|
|
1445
|
+
} catch {
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
async function readSSE(response, { onEvent, onChunk, handlers, parseJson } = {}) {
|
|
1449
|
+
const events = [];
|
|
1450
|
+
const stream = response.body;
|
|
1451
|
+
if (!stream) return events;
|
|
1452
|
+
const reader = stream.getReader();
|
|
1453
|
+
const decoder = new TextDecoder("utf-8");
|
|
1454
|
+
let buffer = "";
|
|
1455
|
+
let pendingCR = "";
|
|
1456
|
+
const normalize = (chunk) => chunk.replace(/\r\n|\r/g, "\n");
|
|
1457
|
+
const flush = (rawBlock) => {
|
|
1458
|
+
const event = parseSSEEvent(rawBlock);
|
|
1459
|
+
if (!event) return;
|
|
1460
|
+
if (parseJson && typeof event.data === "string" && event.data !== "") {
|
|
1461
|
+
try {
|
|
1462
|
+
event.data = JSON.parse(event.data);
|
|
1463
|
+
} catch {
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
events.push(event);
|
|
1467
|
+
safeCall(onEvent, event);
|
|
1468
|
+
safeCall(onChunk, event.data, event);
|
|
1469
|
+
if (handlers) safeCall(handlers[event.event], event.data, event);
|
|
1470
|
+
};
|
|
1471
|
+
try {
|
|
1472
|
+
while (true) {
|
|
1473
|
+
const { done, value } = await reader.read();
|
|
1474
|
+
if (done) break;
|
|
1475
|
+
let chunk = pendingCR + decoder.decode(value, { stream: true });
|
|
1476
|
+
pendingCR = "";
|
|
1477
|
+
if (chunk.endsWith("\r")) {
|
|
1478
|
+
pendingCR = "\r";
|
|
1479
|
+
chunk = chunk.slice(0, -1);
|
|
1480
|
+
}
|
|
1481
|
+
buffer += normalize(chunk);
|
|
1482
|
+
let sepIdx;
|
|
1483
|
+
while ((sepIdx = buffer.indexOf("\n\n")) !== -1) {
|
|
1484
|
+
const rawBlock = buffer.slice(0, sepIdx);
|
|
1485
|
+
buffer = buffer.slice(sepIdx + 2);
|
|
1486
|
+
flush(rawBlock);
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1489
|
+
buffer += normalize(pendingCR + decoder.decode());
|
|
1490
|
+
buffer = buffer.replace(/\n+$/g, "");
|
|
1491
|
+
if (buffer !== "") flush(buffer);
|
|
1492
|
+
} catch (error) {
|
|
1493
|
+
const name = error && typeof error === "object" && "name" in error ? error.name : void 0;
|
|
1494
|
+
if (name !== "AbortError") throw error;
|
|
1495
|
+
} finally {
|
|
1496
|
+
try {
|
|
1497
|
+
reader.releaseLock?.();
|
|
1498
|
+
} catch {
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
return events;
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
// src/Classes/RESTAPI/partials/ApiRequestCreators.ts
|
|
1505
|
+
function isStreamResponse(value) {
|
|
1506
|
+
if (!getIsOnlyAnObject(value) || !value.ok) return false;
|
|
1507
|
+
const body = value.body;
|
|
1508
|
+
return typeof body === "object" && body !== null && "getReader" in body && typeof body.getReader === "function";
|
|
1509
|
+
}
|
|
1280
1510
|
var PREFIX_OF_CLASS_UTILS = "createRequest_";
|
|
1281
1511
|
var ApiRequestCreators = class extends ApiUtils_default {
|
|
1282
1512
|
constructor(settings) {
|
|
@@ -1284,8 +1514,14 @@ var ApiRequestCreators = class extends ApiUtils_default {
|
|
|
1284
1514
|
const { requestsCreators } = settings || {};
|
|
1285
1515
|
if (getIsOnlyAnObject(requestsCreators)) addCustomMethods.call(this, requestsCreators, PREFIX_OF_CLASS_UTILS);
|
|
1286
1516
|
}
|
|
1287
|
-
|
|
1288
|
-
|
|
1517
|
+
/**
|
|
1518
|
+
* Крейтер типа `toJson`: пользовательский callback получит тело ответа (Response.json()).
|
|
1519
|
+
*
|
|
1520
|
+
* @param props - объект описания запроса.
|
|
1521
|
+
* @param variant - вариант обработки splitProperties.
|
|
1522
|
+
*/
|
|
1523
|
+
// ? При типе toJson пользовательский callback на вход получит тело ответа реализованное методом Response.json()
|
|
1524
|
+
// ? независимо от насторойки isGetBody
|
|
1289
1525
|
async createRequest_toJson(props, variant) {
|
|
1290
1526
|
const safelyProps = omitKeys(props, ["getBodyAs"]);
|
|
1291
1527
|
return this.splitProperties(
|
|
@@ -1294,15 +1530,21 @@ var ApiRequestCreators = class extends ApiUtils_default {
|
|
|
1294
1530
|
isGetBody: false,
|
|
1295
1531
|
callback: async (res) => {
|
|
1296
1532
|
const output = await this.getResponseBody(res, "json");
|
|
1297
|
-
return await (
|
|
1533
|
+
return await (props.callback?.(output) ?? output);
|
|
1298
1534
|
}
|
|
1299
1535
|
},
|
|
1300
1536
|
variant
|
|
1301
1537
|
);
|
|
1302
1538
|
}
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1539
|
+
/**
|
|
1540
|
+
* Крейтер типа `toJsonAdvanced`: callback получит структуру `{ response, result }`.
|
|
1541
|
+
*
|
|
1542
|
+
* @param props - объект описания запроса.
|
|
1543
|
+
* @param variant - вариант обработки splitProperties.
|
|
1544
|
+
*/
|
|
1545
|
+
// ? При типе toJsonAdvanced пользовательский callback на вход получит структуру { response, result },
|
|
1546
|
+
// ? где response - объект Response, result - тело ответа реализованное методом Response.json()
|
|
1547
|
+
// ? независимо от насторойки isGetBody
|
|
1306
1548
|
async createRequest_toJsonAdvanced(props, variant) {
|
|
1307
1549
|
const safelyProps = omitKeys(props, ["getBodyAs"]);
|
|
1308
1550
|
return this.splitProperties(
|
|
@@ -1314,14 +1556,20 @@ var ApiRequestCreators = class extends ApiUtils_default {
|
|
|
1314
1556
|
response: res,
|
|
1315
1557
|
result: await this.getResponseBody(await getResponseClone(res), "json")
|
|
1316
1558
|
};
|
|
1317
|
-
return await (
|
|
1559
|
+
return await (props.callback?.(output) ?? output);
|
|
1318
1560
|
}
|
|
1319
1561
|
},
|
|
1320
1562
|
variant
|
|
1321
1563
|
);
|
|
1322
1564
|
}
|
|
1323
|
-
|
|
1324
|
-
|
|
1565
|
+
/**
|
|
1566
|
+
* Крейтер типа `blob`: callback получит тело ответа (Response.blob()).
|
|
1567
|
+
*
|
|
1568
|
+
* @param props - объект описания запроса.
|
|
1569
|
+
* @param variant - вариант обработки splitProperties.
|
|
1570
|
+
*/
|
|
1571
|
+
// ? При типе blob пользовательский callback на вход получит тело ответа реализованное методом Response.blob(),
|
|
1572
|
+
// ? независимо от насторойки isGetBody
|
|
1325
1573
|
async createRequest_blob(props, variant) {
|
|
1326
1574
|
const safelyProps = omitKeys(props, ["getBodyAs"]);
|
|
1327
1575
|
return this.splitProperties(
|
|
@@ -1330,14 +1578,67 @@ var ApiRequestCreators = class extends ApiUtils_default {
|
|
|
1330
1578
|
isGetBody: false,
|
|
1331
1579
|
callback: async (res) => {
|
|
1332
1580
|
const output = await this.getResponseBody(await getResponseClone(res), "blob");
|
|
1333
|
-
return await (
|
|
1581
|
+
return await (props.callback?.(output) ?? output);
|
|
1582
|
+
}
|
|
1583
|
+
},
|
|
1584
|
+
variant
|
|
1585
|
+
);
|
|
1586
|
+
}
|
|
1587
|
+
/**
|
|
1588
|
+
* Крейтер типа `sse`: обрабатывает ответ как поток Server-Sent Events (text/event-stream).
|
|
1589
|
+
*
|
|
1590
|
+
* Дополнительные пропы объекта описания запроса: `onEvent`, `onChunk`, `handlers`, `parseJson`.
|
|
1591
|
+
* По умолчанию добавляется заголовок `Accept: text/event-stream`. Метод doRequest резолвится
|
|
1592
|
+
* массивом всех событий ПОСЛЕ закрытия потока; отмена — методом `.abort()` возвращённого промиса.
|
|
1593
|
+
*
|
|
1594
|
+
* @param props - объект описания запроса (плюс onEvent/onChunk/handlers/parseJson).
|
|
1595
|
+
* @param variant - вариант обработки splitProperties.
|
|
1596
|
+
*/
|
|
1597
|
+
// ? При типе sse запрос обрабатывается как поток Server-Sent Events (text/event-stream).
|
|
1598
|
+
// ? Дополнительные пропы объекта описания запроса:
|
|
1599
|
+
// ? - onEvent(event) — вызывается на каждое распарсенное событие { event, data, id, retry };
|
|
1600
|
+
// ? - onChunk(data, event) — вызывается на полезную нагрузку (поле data) каждого события;
|
|
1601
|
+
// ? - handlers — карта { имяСобытия: cb } для типизированной обработки по полю event
|
|
1602
|
+
// ? (например { delta, status, done }); cb получает (data, event);
|
|
1603
|
+
// ? - parseJson — если true, поле data каждого события прогоняется через JSON.parse.
|
|
1604
|
+
// ? По умолчанию добавляется заголовок Accept: text/event-stream (его можно переопределить через headers).
|
|
1605
|
+
// ? Пользовательский callback (если передан) на вход получит итоговый массив всех событий.
|
|
1606
|
+
// ? Метод doRequest резолвится массивом всех событий ПОСЛЕ закрытия потока;
|
|
1607
|
+
// ? отмена потока выполняется методом .abort() возвращённого промиса (через встроенный AbortController).
|
|
1608
|
+
async createRequest_sse(props, variant) {
|
|
1609
|
+
const safelyProps = omitKeys(props, ["getBodyAs", "onChunk", "onEvent", "handlers", "parseJson"]);
|
|
1610
|
+
const { onChunk, onEvent, handlers, parseJson } = props;
|
|
1611
|
+
const sseOptions = {
|
|
1612
|
+
onChunk: typeof onChunk === "function" ? (data, event) => onChunk(data, event) : void 0,
|
|
1613
|
+
onEvent: typeof onEvent === "function" ? (event) => onEvent(event) : void 0,
|
|
1614
|
+
parseJson: Boolean(parseJson),
|
|
1615
|
+
handlers: getIsOnlyAnObject(handlers) ? Object.keys(handlers).reduce((acc, key) => {
|
|
1616
|
+
const fn = handlers[key];
|
|
1617
|
+
acc[key] = typeof fn === "function" ? (data, event) => fn(data, event) : void 0;
|
|
1618
|
+
return acc;
|
|
1619
|
+
}, {}) : void 0
|
|
1620
|
+
};
|
|
1621
|
+
return this.splitProperties(
|
|
1622
|
+
{
|
|
1623
|
+
...safelyProps,
|
|
1624
|
+
headers: { Accept: "text/event-stream", ...getIsOnlyAnObject(safelyProps.headers) ? safelyProps.headers : {} },
|
|
1625
|
+
isGetBody: false,
|
|
1626
|
+
callback: async (res) => {
|
|
1627
|
+
const output = isStreamResponse(res) ? await readSSE(res, sseOptions) : res;
|
|
1628
|
+
return await (props.callback?.(output) ?? output);
|
|
1334
1629
|
}
|
|
1335
1630
|
},
|
|
1336
1631
|
variant
|
|
1337
1632
|
);
|
|
1338
1633
|
}
|
|
1339
|
-
|
|
1340
|
-
|
|
1634
|
+
/**
|
|
1635
|
+
* Крейтер типа `testBadResponse`: callback получит синтетический Response со статусом 401.
|
|
1636
|
+
*
|
|
1637
|
+
* @param props - объект описания запроса.
|
|
1638
|
+
* @param variant - вариант обработки splitProperties.
|
|
1639
|
+
*/
|
|
1640
|
+
// ? При типе testBadResponse пользовательский callback на вход получит объект Response в 401-м статусе
|
|
1641
|
+
// ? независимо независимо вообще ни от чего
|
|
1341
1642
|
async createRequest_testBadResponse(props, variant) {
|
|
1342
1643
|
return this.splitProperties(
|
|
1343
1644
|
{
|
|
@@ -1357,17 +1658,33 @@ var ApiRequestCreators = class extends ApiUtils_default {
|
|
|
1357
1658
|
variant
|
|
1358
1659
|
);
|
|
1359
1660
|
}
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1661
|
+
/**
|
|
1662
|
+
* Крейтер по умолчанию: callback получит объект Response (или тело ответа при isGetBody: 'first').
|
|
1663
|
+
*
|
|
1664
|
+
* @param props - объект описания запроса.
|
|
1665
|
+
* @param variant - вариант обработки splitProperties.
|
|
1666
|
+
*/
|
|
1667
|
+
// ? По умолчанию пользовательский callback на вход получит
|
|
1668
|
+
// ? - либо объект Response
|
|
1669
|
+
// ? - либо тело ответа (в случае isGetBody: 'first') полученное методом getResponseBody (смотри класс ApiUtils)
|
|
1363
1670
|
async createRequest_default(props, variant) {
|
|
1364
1671
|
return this.splitProperties(props, variant);
|
|
1365
1672
|
}
|
|
1366
1673
|
};
|
|
1367
1674
|
var ApiRequestCreators_default = ApiRequestCreators;
|
|
1368
1675
|
|
|
1369
|
-
// src/Classes/RESTAPI/partials/ApiBase.
|
|
1676
|
+
// src/Classes/RESTAPI/partials/ApiBase.ts
|
|
1370
1677
|
var ApiBase = class extends ApiRequestCreators_default {
|
|
1678
|
+
/** Текст ошибки невалидных данных запроса. */
|
|
1679
|
+
BAD_REQUEST_DATA_TEXT;
|
|
1680
|
+
/** Текст сообщения об успехе по умолчанию. */
|
|
1681
|
+
DEFAULT_SUCCESS_MESSAGE;
|
|
1682
|
+
/** Текст сообщения об ошибке по умолчанию. */
|
|
1683
|
+
DEFAULT_ERROR_MESSAGE;
|
|
1684
|
+
/** Текст сообщения об отсутствии сети. */
|
|
1685
|
+
NO_INET;
|
|
1686
|
+
/** Коды ответа, по которым запрос считается отклонённым. */
|
|
1687
|
+
REJECT_CODES;
|
|
1371
1688
|
constructor(settings) {
|
|
1372
1689
|
super(settings);
|
|
1373
1690
|
const {
|
|
@@ -1396,49 +1713,76 @@ var ApiBase = class extends ApiRequestCreators_default {
|
|
|
1396
1713
|
};
|
|
1397
1714
|
var ApiBase_default = ApiBase;
|
|
1398
1715
|
|
|
1399
|
-
// src/Classes/RESTAPI/partials/CredentialsProcessing.
|
|
1716
|
+
// src/Classes/RESTAPI/partials/CredentialsProcessing.ts
|
|
1400
1717
|
function decodeJWT(token) {
|
|
1401
1718
|
try {
|
|
1402
|
-
const payload = token.split(".")[1];
|
|
1403
|
-
|
|
1404
|
-
|
|
1719
|
+
const payload = token.split(".")[1] ?? "";
|
|
1720
|
+
const decoded = JSON.parse(atob(payload));
|
|
1721
|
+
return getIsOnlyAnObject(decoded) ? decoded : null;
|
|
1722
|
+
} catch {
|
|
1405
1723
|
return null;
|
|
1406
1724
|
}
|
|
1407
1725
|
}
|
|
1408
1726
|
var CredentialsProcessing = class {
|
|
1727
|
+
/** Включён ли флоу рефреша токенов. */
|
|
1728
|
+
isUseRefreshTokensPropcessing = false;
|
|
1729
|
+
/** Учётные данные по умолчанию (пустые). */
|
|
1730
|
+
DEFAULT_CREDENTIALS = {};
|
|
1731
|
+
/** Внешний метод получения учётных данных. */
|
|
1732
|
+
getCredentialsByOuter;
|
|
1733
|
+
/** Внешний метод формирования заголовков авторизации по токену. */
|
|
1734
|
+
getHeadersForAuthorize;
|
|
1735
|
+
/** Необязательный преобразователь учётных данных после getCredentials. */
|
|
1736
|
+
importCredentials;
|
|
1737
|
+
/** Необязательный метод сохранения учётных данных (обязателен для флоу рефреша). */
|
|
1738
|
+
saveCredentials;
|
|
1739
|
+
/** Внешний метод рефреша учётных данных. */
|
|
1740
|
+
refreshCredentialsByOuter;
|
|
1741
|
+
/** Полный путь до эндпоинта рефреша токена. */
|
|
1742
|
+
REFRESH_TOKEN_PATH;
|
|
1743
|
+
/** Коды ответа, по которым триггерится попытка рефреша. */
|
|
1744
|
+
CODES_USING_THE_REFRESH_ATTEMPT;
|
|
1745
|
+
/** Ключ флага «рефреш начат» в localStorage. */
|
|
1746
|
+
REFRESH_TOKEN_FLAG = "refreshTokenFlag";
|
|
1747
|
+
/** Интервал опроса флага обновления токена, мс. */
|
|
1748
|
+
INTERVAL_FOR_CHECKING_TOKEN_UPDATE = 50;
|
|
1749
|
+
/** Колбэк, вызываемый после неудачного рефреша. */
|
|
1750
|
+
callbackAfterRejectRefresh;
|
|
1751
|
+
/** Доступ к верхнему контексту RESTAPI (навешивается из конструктора RESTAPI). */
|
|
1752
|
+
getRESTAPIContext;
|
|
1409
1753
|
constructor(settings) {
|
|
1410
1754
|
const { credentialsProcessing } = settings;
|
|
1411
1755
|
const {
|
|
1412
|
-
|
|
1413
|
-
|
|
1756
|
+
// ? Для корректной работы установки токенов в запросы от API
|
|
1757
|
+
// ? нужно передавать методы getCredentials и getHeadersForAuthorize
|
|
1414
1758
|
getCredentials,
|
|
1415
1759
|
getHeadersForAuthorize,
|
|
1416
|
-
|
|
1417
|
-
|
|
1760
|
+
// ? На вход получит токен, должна вернуть объект для коструктора Headers
|
|
1761
|
+
// ? Так же опционально можно передавать
|
|
1418
1762
|
importCredentials,
|
|
1419
|
-
|
|
1763
|
+
// ? если он передается, то он будет применяться к выводу от вызова getCredentials
|
|
1420
1764
|
saveCredentials,
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1765
|
+
// ? можно будет найти в объекте credentialsProcessing, чтобы использовать кастомными методами
|
|
1766
|
+
// ! Либо вызов getCredentials, либо цепочка вызовов importCredentials(getCredentials())
|
|
1767
|
+
// ! должна возвращать требуемую классом структуру
|
|
1768
|
+
// ! Класс требует структуры
|
|
1769
|
+
// ! - { token }, если флоу рефреш токена НЕ используется
|
|
1770
|
+
// ! - { token, refreshToken, expires }, если используется флоу рефреш токена
|
|
1427
1771
|
// *********
|
|
1428
|
-
|
|
1772
|
+
// ? Подключает флоу рефреша токенов
|
|
1429
1773
|
isUseRefreshTokensPropcessing = false,
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1774
|
+
// ! Для корректной работы флоу рефреша токенов передача метода saveCredentials становится ОБЯЗАТЕЛЬНОЙ
|
|
1775
|
+
// ? Так же для корректной работы флоу рефреша токенов нужно
|
|
1776
|
+
// ? - либо
|
|
1433
1777
|
refreshCredentials,
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1778
|
+
// ! метод должен возвращать такую же структуру как и метод getCredentials,
|
|
1779
|
+
// ? на вход получит текущие креды, к выходу будет применен importCredentials, если этот метод передавался
|
|
1780
|
+
// ? - либо
|
|
1437
1781
|
REFRESH_TOKEN_PATH,
|
|
1438
|
-
|
|
1782
|
+
// ! REFRESH_TOKEN_PATH передается ПОЛНОСТЬЮ (глобальная адресация)!
|
|
1439
1783
|
CODES_USING_THE_REFRESH_ATTEMPT,
|
|
1440
|
-
|
|
1441
|
-
|
|
1784
|
+
// ? указывает по каким кодам ответа триггериться рефреш, массив чисел
|
|
1785
|
+
// ? Опционально
|
|
1442
1786
|
REFRESH_TOKEN_FLAG = "refreshTokenFlag",
|
|
1443
1787
|
INTERVAL_FOR_CHECKING_TOKEN_UPDATE = 50,
|
|
1444
1788
|
// ms
|
|
@@ -1446,40 +1790,44 @@ var CredentialsProcessing = class {
|
|
|
1446
1790
|
} = credentialsProcessing || {};
|
|
1447
1791
|
if (typeof getCredentials !== "function") throw new Error("No getCredentials method [CredentialsProcessing]");
|
|
1448
1792
|
if (typeof getHeadersForAuthorize !== "function") {
|
|
1449
|
-
throw new
|
|
1793
|
+
throw new TypeError("No getHeadersForAuthorize method [CredentialsProcessing]");
|
|
1450
1794
|
}
|
|
1451
1795
|
if (importCredentials && typeof importCredentials !== "function") {
|
|
1452
1796
|
throw new Error("Bad importCredentials method [CredentialsProcessing]");
|
|
1453
1797
|
}
|
|
1454
|
-
this.isUseRefreshTokensPropcessing = isUseRefreshTokensPropcessing;
|
|
1798
|
+
this.isUseRefreshTokensPropcessing = Boolean(isUseRefreshTokensPropcessing);
|
|
1455
1799
|
this.DEFAULT_CREDENTIALS = {};
|
|
1456
|
-
this.getCredentialsByOuter = getCredentials;
|
|
1457
|
-
this.getHeadersForAuthorize =
|
|
1458
|
-
|
|
1800
|
+
this.getCredentialsByOuter = () => getCredentials();
|
|
1801
|
+
this.getHeadersForAuthorize = (token) => {
|
|
1802
|
+
const result = getHeadersForAuthorize(token);
|
|
1803
|
+
return getIsOnlyAnObject(result) ? result : {};
|
|
1804
|
+
};
|
|
1805
|
+
if (typeof importCredentials === "function") this.importCredentials = (cred) => importCredentials(cred);
|
|
1459
1806
|
if (saveCredentials || isUseRefreshTokensPropcessing) {
|
|
1460
1807
|
if (typeof saveCredentials !== "function") throw new Error("No saveCredentials method [CredentialsProcessing]");
|
|
1461
|
-
else this.saveCredentials = saveCredentials;
|
|
1808
|
+
else this.saveCredentials = (cred) => saveCredentials(cred);
|
|
1462
1809
|
}
|
|
1463
1810
|
if (isUseRefreshTokensPropcessing) {
|
|
1464
|
-
if (typeof refreshCredentials === "function")
|
|
1465
|
-
|
|
1811
|
+
if (typeof refreshCredentials === "function") {
|
|
1812
|
+
this.refreshCredentialsByOuter = (cred) => refreshCredentials(cred);
|
|
1813
|
+
} else {
|
|
1466
1814
|
if (typeof this.refreshCredentialsByOuter === "function" && typeof REFRESH_TOKEN_PATH !== "string") {
|
|
1467
|
-
throw new
|
|
1815
|
+
throw new TypeError("No REFRESH_TOKEN_PATH [CredentialsProcessing]");
|
|
1468
1816
|
}
|
|
1469
|
-
this.REFRESH_TOKEN_PATH = REFRESH_TOKEN_PATH;
|
|
1817
|
+
this.REFRESH_TOKEN_PATH = typeof REFRESH_TOKEN_PATH === "string" ? REFRESH_TOKEN_PATH : void 0;
|
|
1470
1818
|
}
|
|
1471
1819
|
if (!Array.isArray(CODES_USING_THE_REFRESH_ATTEMPT)) {
|
|
1472
|
-
throw new
|
|
1820
|
+
throw new TypeError("No CODES_USING_THE_REFRESH_ATTEMPT [CredentialsProcessing]");
|
|
1473
1821
|
}
|
|
1474
1822
|
if (!CODES_USING_THE_REFRESH_ATTEMPT.every((i) => typeof i === "number")) {
|
|
1475
1823
|
throw new Error("Invalid format of CODES_USING_THE_REFRESH_ATTEMPT elements [CredentialsProcessing]");
|
|
1476
1824
|
}
|
|
1477
1825
|
if (typeof REFRESH_TOKEN_FLAG !== "string") throw new Error("Bad REFRESH_TOKEN_FLAG [CredentialsProcessing]");
|
|
1478
1826
|
if (typeof INTERVAL_FOR_CHECKING_TOKEN_UPDATE !== "number") {
|
|
1479
|
-
throw new
|
|
1827
|
+
throw new TypeError("Bad INTERVAL_FOR_CHECKING_TOKEN_UPDATE [CredentialsProcessing]");
|
|
1480
1828
|
}
|
|
1481
1829
|
if (typeof INTERVAL_FOR_CHECKING_TOKEN_UPDATE !== "number") {
|
|
1482
|
-
throw new
|
|
1830
|
+
throw new TypeError("Bad INTERVAL_FOR_CHECKING_TOKEN_UPDATE [CredentialsProcessing]");
|
|
1483
1831
|
}
|
|
1484
1832
|
if (callbackAfterRejectRefresh && typeof callbackAfterRejectRefresh !== "function") {
|
|
1485
1833
|
throw new Error("Bad INTERVAL_FOR_CHECKING_TOKEN_UPDATE [CredentialsProcessing]");
|
|
@@ -1487,23 +1835,33 @@ var CredentialsProcessing = class {
|
|
|
1487
1835
|
this.CODES_USING_THE_REFRESH_ATTEMPT = CODES_USING_THE_REFRESH_ATTEMPT;
|
|
1488
1836
|
this.REFRESH_TOKEN_FLAG = REFRESH_TOKEN_FLAG;
|
|
1489
1837
|
this.INTERVAL_FOR_CHECKING_TOKEN_UPDATE = INTERVAL_FOR_CHECKING_TOKEN_UPDATE;
|
|
1490
|
-
if (callbackAfterRejectRefresh) this.callbackAfterRejectRefresh = callbackAfterRejectRefresh;
|
|
1838
|
+
if (typeof callbackAfterRejectRefresh === "function") this.callbackAfterRejectRefresh = () => callbackAfterRejectRefresh();
|
|
1491
1839
|
}
|
|
1492
1840
|
}
|
|
1841
|
+
/** Возвращает значение флага «рефреш начат» из localStorage. */
|
|
1493
1842
|
getIsTokenStartRefresh() {
|
|
1494
1843
|
return localStorage.getItem(this.REFRESH_TOKEN_FLAG);
|
|
1495
1844
|
}
|
|
1845
|
+
/** Выставляет флаг «рефреш начат» в localStorage. */
|
|
1496
1846
|
setIsTokenStartRefresh() {
|
|
1497
|
-
localStorage.setItem(this.REFRESH_TOKEN_FLAG, true);
|
|
1847
|
+
localStorage.setItem(this.REFRESH_TOKEN_FLAG, String(true));
|
|
1498
1848
|
}
|
|
1849
|
+
/** Снимает флаг «рефреш начат» из localStorage. */
|
|
1499
1850
|
removeIsTokenStartRefresh() {
|
|
1500
1851
|
localStorage.removeItem(this.REFRESH_TOKEN_FLAG);
|
|
1501
1852
|
}
|
|
1853
|
+
/**
|
|
1854
|
+
* Возвращает текущие учётные данные (с учётом importCredentials и проверки истечения JWT).
|
|
1855
|
+
*
|
|
1856
|
+
* @param isCatchCallbackProcess - флаг процесса обработки ошибки (отключает проверку истечения).
|
|
1857
|
+
* @param callback - необязательный колбэк, получающий итоговые учётные данные.
|
|
1858
|
+
* @returns Промис с учётными данными.
|
|
1859
|
+
*/
|
|
1502
1860
|
async getCredentials(isCatchCallbackProcess, callback) {
|
|
1503
1861
|
let credentials = await this.getCredentialsByOuter();
|
|
1504
1862
|
if (typeof this.importCredentials === "function") credentials = await this.importCredentials(credentials);
|
|
1505
|
-
|
|
1506
|
-
const token =
|
|
1863
|
+
const credObj = getIsOnlyAnObject(credentials) ? credentials : {};
|
|
1864
|
+
const token = credObj.token || null;
|
|
1507
1865
|
if (token && !isCatchCallbackProcess) {
|
|
1508
1866
|
let decoded;
|
|
1509
1867
|
try {
|
|
@@ -1512,11 +1870,18 @@ var CredentialsProcessing = class {
|
|
|
1512
1870
|
decoded = null;
|
|
1513
1871
|
}
|
|
1514
1872
|
const currentTime = Date.now() / 1e3;
|
|
1515
|
-
if (decoded !== null && Number(decoded.exp) < currentTime)
|
|
1873
|
+
if (decoded !== null && Number(decoded.exp) < currentTime) credObj.isNeedRefresh = true;
|
|
1516
1874
|
}
|
|
1517
|
-
if (callback) await callback({ ...
|
|
1518
|
-
return { ...
|
|
1875
|
+
if (callback) await callback({ ...credObj, isCatchCallbackProcess });
|
|
1876
|
+
return { ...credObj, isCatchCallbackProcess };
|
|
1519
1877
|
}
|
|
1878
|
+
/**
|
|
1879
|
+
* Выполняет рефреш учётных данных (внешним методом либо дефолтным OAuth-флоу).
|
|
1880
|
+
*
|
|
1881
|
+
* @param currentCredentials - текущие учётные данные.
|
|
1882
|
+
* @param callback - необязательный колбэк сохранения новых учётных данных.
|
|
1883
|
+
* @returns Промис с новыми учётными данными.
|
|
1884
|
+
*/
|
|
1520
1885
|
async refreshCredentials(currentCredentials, callback) {
|
|
1521
1886
|
const CONTEXT = this;
|
|
1522
1887
|
async function finalize(cred) {
|
|
@@ -1529,11 +1894,10 @@ var CredentialsProcessing = class {
|
|
|
1529
1894
|
if (!currentCredentials?.token || !currentCredentials?.refreshToken) return finalize(CONTEXT.DEFAULT_CREDENTIALS);
|
|
1530
1895
|
async function refreshCredentialsByDefault() {
|
|
1531
1896
|
const { token, refreshToken } = currentCredentials;
|
|
1532
|
-
const headers = new Headers();
|
|
1533
|
-
headers.append(...Object.entries(CONTEXT.getHeadersForAuthorize(token)));
|
|
1897
|
+
const headers = new Headers(Object.entries(CONTEXT.getHeadersForAuthorize(token || "")).map(([key, value]) => [key, `${value}`]));
|
|
1534
1898
|
const body = new FormData();
|
|
1535
1899
|
body.append("grant_type", "refresh_token");
|
|
1536
|
-
body.append("refresh_token", refreshToken);
|
|
1900
|
+
body.append("refresh_token", refreshToken || "");
|
|
1537
1901
|
body.append("client_id", "oauth");
|
|
1538
1902
|
body.append("client_secret", "secret");
|
|
1539
1903
|
body.append("access_type", "offline");
|
|
@@ -1546,8 +1910,14 @@ var CredentialsProcessing = class {
|
|
|
1546
1910
|
});
|
|
1547
1911
|
}
|
|
1548
1912
|
const newCredentials = typeof CONTEXT.refreshCredentialsByOuter === "function" ? await CONTEXT.refreshCredentialsByOuter(currentCredentials) : await refreshCredentialsByDefault();
|
|
1549
|
-
return finalize(newCredentials);
|
|
1913
|
+
return finalize(getIsOnlyAnObject(newCredentials) ? newCredentials : CONTEXT.DEFAULT_CREDENTIALS);
|
|
1550
1914
|
}
|
|
1915
|
+
/**
|
|
1916
|
+
* Ожидает завершения рефреша токена (или запускает его флаг при необходимости).
|
|
1917
|
+
*
|
|
1918
|
+
* @param isNeedRefresh - выставить ли флаг «рефреш начат» при отсутствии активного рефреша.
|
|
1919
|
+
* @returns Промис, который резолвится по завершении ожидания.
|
|
1920
|
+
*/
|
|
1551
1921
|
async waitRefresh(isNeedRefresh) {
|
|
1552
1922
|
return new Promise((resolve) => {
|
|
1553
1923
|
if (!this.getIsTokenStartRefresh()) {
|
|
@@ -1563,10 +1933,16 @@ var CredentialsProcessing = class {
|
|
|
1563
1933
|
}
|
|
1564
1934
|
});
|
|
1565
1935
|
}
|
|
1936
|
+
/**
|
|
1937
|
+
* Обрабатывает учётные данные: при необходимости рефрешит токен и возвращает актуальные данные.
|
|
1938
|
+
*
|
|
1939
|
+
* @param cred - текущие учётные данные.
|
|
1940
|
+
* @returns Промис с актуальными учётными данными (с флагом isRefreshFailed при неудаче).
|
|
1941
|
+
*/
|
|
1566
1942
|
async processCredentials(cred) {
|
|
1567
1943
|
if (!cred.isNeedRefresh && !cred.isCatchCallbackProcess) return cred;
|
|
1568
1944
|
const CONTEXT = this;
|
|
1569
|
-
return CONTEXT.refreshCredentials(cred, (response) => CONTEXT.saveCredentials(response)).then(() => {
|
|
1945
|
+
return CONTEXT.refreshCredentials(cred, (response) => CONTEXT.saveCredentials?.(response)).then(() => {
|
|
1570
1946
|
return new Promise((resolve) => {
|
|
1571
1947
|
setTimeout(async () => {
|
|
1572
1948
|
const newCredentials = await CONTEXT.getCredentials();
|
|
@@ -1584,11 +1960,15 @@ var CredentialsProcessing = class {
|
|
|
1584
1960
|
};
|
|
1585
1961
|
var CredentialsProcessing_default = CredentialsProcessing;
|
|
1586
1962
|
|
|
1587
|
-
// src/Classes/RESTAPI/index.
|
|
1963
|
+
// src/Classes/RESTAPI/index.ts
|
|
1588
1964
|
function returnTheContext() {
|
|
1589
1965
|
return this;
|
|
1590
1966
|
}
|
|
1591
1967
|
var RESTAPI = class extends ApiBase_default {
|
|
1968
|
+
/** Функция показа сообщений пользователю (или null, если информирование отключено). */
|
|
1969
|
+
sendMessage = null;
|
|
1970
|
+
/** Обработчик учётных данных (создаётся при наличии настройки credentialsProcessing). */
|
|
1971
|
+
credentialsProcessing;
|
|
1592
1972
|
constructor(settings) {
|
|
1593
1973
|
super(settings);
|
|
1594
1974
|
const { sendMessage, credentialsProcessing } = settings || {};
|
|
@@ -1598,7 +1978,14 @@ var RESTAPI = class extends ApiBase_default {
|
|
|
1598
1978
|
this.credentialsProcessing.getRESTAPIContext = returnTheContext.bind(this);
|
|
1599
1979
|
}
|
|
1600
1980
|
}
|
|
1601
|
-
|
|
1981
|
+
/**
|
|
1982
|
+
* Основной (базовый) метод API: выполняет мультизапрос (или одиночный запрос).
|
|
1983
|
+
*
|
|
1984
|
+
* @param inputRequests - путь, объект описания запроса или их массив.
|
|
1985
|
+
* @param settings - общие настройки запроса (формат ответа, тосты, сообщения и т.п.).
|
|
1986
|
+
* @returns Промис с результатом (форма зависит от isResponseAsObject).
|
|
1987
|
+
*/
|
|
1988
|
+
// ! Основной (базовый) метод API, мультизапросы
|
|
1602
1989
|
async doRequest(inputRequests, settings) {
|
|
1603
1990
|
if (typeof inputRequests !== "string" && typeof inputRequests !== "object") {
|
|
1604
1991
|
return Promise.reject(new Error(this.BAD_REQUEST_DATA_TEXT));
|
|
@@ -1622,24 +2009,29 @@ var RESTAPI = class extends ApiBase_default {
|
|
|
1622
2009
|
throw new Error("It is impossible to make a request!");
|
|
1623
2010
|
}
|
|
1624
2011
|
instance.setIsResponseAsObject(isResponseAsObject ?? true);
|
|
1625
|
-
if (callback) instance.setCallback(callback);
|
|
2012
|
+
if (typeof callback === "function") instance.setCallback(callback);
|
|
1626
2013
|
function getRequests() {
|
|
1627
2014
|
let output;
|
|
1628
2015
|
if (typeof inputRequests === "string") output = [{ path: inputRequests }];
|
|
1629
2016
|
else output = Array.isArray(inputRequests) ? inputRequests : [inputRequests];
|
|
1630
2017
|
function getCallback(item, mesageOptions) {
|
|
1631
|
-
const
|
|
2018
|
+
const getBodyAs = typeof item.getBodyAs === "string" ? item.getBodyAs : void 0;
|
|
1632
2019
|
const finalIsGetBody = typeof item.isGetBody === "boolean" || typeof item.isGetBody === "string" ? item.isGetBody : isGetBody;
|
|
1633
2020
|
const finalIsGetBodyFirst = finalIsGetBody === "first";
|
|
1634
|
-
const checkResponseCallback = finalIsGetBodyFirst ? async (res,
|
|
1635
|
-
const
|
|
1636
|
-
|
|
2021
|
+
const checkResponseCallback = finalIsGetBodyFirst ? async (res, options) => API_CONTEXT.getResponseBody(await API_CONTEXT.checkResponseCode(res, options), getBodyAs) : async (res, options) => API_CONTEXT.checkResponseCode(res, options);
|
|
2022
|
+
const itemCallback = item.callback;
|
|
2023
|
+
const callbackFn = typeof itemCallback === "function" ? async (res) => itemCallback(await checkResponseCallback(res, mesageOptions)) : async (res) => checkResponseCallback(res, mesageOptions);
|
|
2024
|
+
return finalIsGetBody && !finalIsGetBodyFirst ? async (res) => API_CONTEXT.getResponseBody(await callbackFn(res), getBodyAs) : callbackFn;
|
|
1637
2025
|
}
|
|
1638
2026
|
async function getRequestItem(item, idx) {
|
|
1639
|
-
const
|
|
2027
|
+
const itemObj = getIsOnlyAnObject(item) ? item : { path: item };
|
|
2028
|
+
const { type, ...partialRestFirst } = itemObj;
|
|
1640
2029
|
const itemAfterRequestCreating = await (async () => {
|
|
1641
|
-
const key = `createRequest_${type
|
|
1642
|
-
|
|
2030
|
+
const key = `createRequest_${typeof type === "string" ? type : "default"}`;
|
|
2031
|
+
const creator = key in API_CONTEXT ? API_CONTEXT[key] : void 0;
|
|
2032
|
+
const result = typeof creator === "function" ? creator.call(API_CONTEXT, partialRestFirst, "doRequestMapping") : API_CONTEXT.createRequest_default(partialRestFirst, "doRequestMapping");
|
|
2033
|
+
const awaited = await result;
|
|
2034
|
+
return getIsOnlyAnObject(awaited) ? awaited : {};
|
|
1643
2035
|
})();
|
|
1644
2036
|
const { fullPath, api, path, query, queryParameters, ...partialRestSecond } = itemAfterRequestCreating;
|
|
1645
2037
|
const {
|
|
@@ -1655,23 +2047,25 @@ var RESTAPI = class extends ApiBase_default {
|
|
|
1655
2047
|
isNoToast,
|
|
1656
2048
|
...rest
|
|
1657
2049
|
} = partialRestSecond;
|
|
2050
|
+
const successMessagesArr = Array.isArray(successMessages) ? successMessages : void 0;
|
|
2051
|
+
const errorMessagesArr = Array.isArray(errorMessages) ? errorMessages : void 0;
|
|
1658
2052
|
const useSuccessMessageFlag = Boolean(
|
|
1659
|
-
successMess || commonSuccessMessage ||
|
|
2053
|
+
successMess || commonSuccessMessage || successMessagesArr?.[idx] || CSMfromSettings || isToastResult || isToastFromSettings
|
|
1660
2054
|
);
|
|
1661
2055
|
const isUseSuccessToast = useSuccessMessageFlag && !isNoToast && !isNoToastFromSettings && !isNoToastSuccess && !isNTSFromSettings;
|
|
1662
2056
|
const isUseErrorToast = !isNoToast && !isNoToastFromSettings && !isNoToastError && !isNTEFromSettings;
|
|
1663
2057
|
const mesageOptions = {
|
|
1664
|
-
successMess: successMess || commonSuccessMessage ||
|
|
2058
|
+
successMess: successMess || commonSuccessMessage || successMessagesArr?.[idx] || CSMfromSettings,
|
|
1665
2059
|
successMessageType: successMessageType || SMTfromSettings,
|
|
1666
|
-
errorMess: errorMess || commonErrorMessage ||
|
|
2060
|
+
errorMess: errorMess || commonErrorMessage || errorMessagesArr?.[idx] || CEMfromSettings,
|
|
1667
2061
|
isUseSuccessToast,
|
|
1668
2062
|
isUseErrorToast,
|
|
1669
2063
|
toastOptions: toastOptions || TOFomSettings
|
|
1670
2064
|
};
|
|
1671
2065
|
return {
|
|
1672
2066
|
...rest,
|
|
1673
|
-
path: `${fullPath || await API_CONTEXT.getRootPath(
|
|
1674
|
-
|
|
2067
|
+
path: `${fullPath || await API_CONTEXT.getRootPath() + (typeof path === "string" ? path : "")}`,
|
|
2068
|
+
// ? Запускаем самовызывающуюся асинхронную ф-ю, ждем резолва промиса от нее
|
|
1675
2069
|
queryParameters: await (async () => {
|
|
1676
2070
|
const queryParams = query || queryParameters || "";
|
|
1677
2071
|
const preparedQueryParams = await API_CONTEXT.processQueryParams(queryParams);
|
|
@@ -1681,16 +2075,25 @@ var RESTAPI = class extends ApiBase_default {
|
|
|
1681
2075
|
callback: getCallback(itemAfterRequestCreating, mesageOptions)
|
|
1682
2076
|
};
|
|
1683
2077
|
}
|
|
1684
|
-
return output
|
|
2078
|
+
return output.map((item, idx) => getRequestItem(item, idx));
|
|
1685
2079
|
}
|
|
1686
2080
|
return instance.request(await Promise.all(getRequests()));
|
|
1687
2081
|
}
|
|
1688
|
-
|
|
2082
|
+
/**
|
|
2083
|
+
* Метод API для одиночных запросов: применяет крейтер по `type` и делегирует в {@link RESTAPI.doRequest}.
|
|
2084
|
+
*
|
|
2085
|
+
* @param requestSettings - объект описания одиночного запроса (с необязательным `type`).
|
|
2086
|
+
* @returns Промис с результатом запроса.
|
|
2087
|
+
*/
|
|
2088
|
+
// ! Метод API для одиночных запросов
|
|
1689
2089
|
async doMonoRequest(requestSettings) {
|
|
1690
2090
|
if (!getIsOnlyAnObject(requestSettings)) throw new Error(`${this.BAD_REQUEST_DATA_TEXT} [RESTAPI.doMonoRequest]`);
|
|
1691
2091
|
const { type, ...requestSettingsRest } = requestSettings;
|
|
1692
|
-
const
|
|
1693
|
-
|
|
2092
|
+
const key = `createRequest_${typeof type === "string" ? type : ""}`;
|
|
2093
|
+
const creator = type && key in this ? this[key] : void 0;
|
|
2094
|
+
const created = typeof creator === "function" ? await creator.call(this, requestSettingsRest) : await this.createRequest_default(requestSettingsRest);
|
|
2095
|
+
const doRequestArgs = Array.isArray(created) ? created : [created];
|
|
2096
|
+
return this.doRequest(doRequestArgs[0], doRequestArgs[1]);
|
|
1694
2097
|
}
|
|
1695
2098
|
};
|
|
1696
2099
|
var RESTAPI_default = RESTAPI;
|
|
@@ -23032,17 +23435,6 @@ var safeValue = {
|
|
|
23032
23435
|
notNullValue
|
|
23033
23436
|
};
|
|
23034
23437
|
var safeValue_default = safeValue;
|
|
23035
|
-
//! При получении экземпляра, если sendMessage не является ф-ей,
|
|
23036
|
-
//! то это воспринимается как отключение шага информирования об ошибке запроса как такового
|
|
23037
|
-
//! Планируемая структура { headers, queryParameters, options }, где
|
|
23038
|
-
//! - headers и options - объекты,
|
|
23039
|
-
//! - queryParameters - строка, массив или объект
|
|
23040
|
-
//! ВНИМАНИЕ! Данный механизм рефреша принят на проекте finturfreactfrontend (админка)
|
|
23041
|
-
//! На кабинете он ТОЧНО НЕ ТАКОЙ
|
|
23042
|
-
//! currentCredentials передаются в формате класса! ({ token, refreshToken, expires })
|
|
23043
|
-
//! Наличие credentialsProcessing подключает ДОБАВЛЕНИЕ ТОКЕНОВ В ЗАПРОСЫ,
|
|
23044
|
-
//! НО по умолчанию НЕ добавляет флоу рефреша токенов
|
|
23045
|
-
//! (флоу рефреша подключается пропой isUseRefreshTokensPropcessing из credentialsProcessing)
|
|
23046
23438
|
//! Важно! Если придет велью с количеством дробных разрядов БОЛЬШИМ
|
|
23047
23439
|
//! чем указано в quantity - округлит по правилам округления
|
|
23048
23440
|
//! чем указано в decimalPlaces - округлит по правилам округления
|