intelicoreact 2.0.9 → 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/classes.cjs CHANGED
@@ -420,7 +420,11 @@ var AnimatedHandler = class {
420
420
  };
421
421
  var AnimatedHandler_default = AnimatedHandler;
422
422
 
423
- // src/Classes/RESTAPI/partials/AbortableFetch.js
423
+ // src/Classes/RESTAPI/partials/AbortableFetch.ts
424
+ var HTTP_METHODS = ["GET", "HEAD", "POST", "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE", "PATCH"];
425
+ function isHttpMethod(value) {
426
+ return HTTP_METHODS.includes(value);
427
+ }
424
428
  var RESPONSE_AS_OBJECT_ALWAYS_VALUE2 = "always";
425
429
  var AbortableFetch2 = class {
426
430
  #pathPrefix = null;
@@ -433,6 +437,8 @@ var AbortableFetch2 = class {
433
437
  #catchCallback = null;
434
438
  #everyPromiseCallback = null;
435
439
  #isResponseAsObject = false;
440
+ // ? Последний вход request() — используется repeatRequest() для повторного запроса той же пачки.
441
+ requestInput = [];
436
442
  constructor(input) {
437
443
  if (input && !getIsOnlyAnObject(input)) throw new Error("Not valid input value!");
438
444
  this.getPathPrefix = this.getPathPrefix.bind(this);
@@ -463,20 +469,30 @@ var AbortableFetch2 = class {
463
469
  this.repeatRequest = this.repeatRequest.bind(this);
464
470
  this.setProps(input || {});
465
471
  }
472
+ /**
473
+ * Выполняет один или несколько HTTP-запросов (нативный fetch) с возможностью отмены.
474
+ *
475
+ * Метод `abort()` навешивается на прототип возвращаемого промиса (как в исходной реализации),
476
+ * что позволяет отменить всю цепочку запросов вызовом `abort()` на возвращённом промисе.
477
+ *
478
+ * @param props - путь, объект описания запроса или их массив.
479
+ * @returns Промис с результатом (форма зависит от isResponseAsObject); на прототипе доступен `abort()`.
480
+ */
466
481
  async request(props) {
467
482
  if (!getIsOnlyAnObject(props) && !Array.isArray(props) && typeof props !== "string") throw new Error("Not valid props value!");
468
- const stringifyBody = (b) => b?.constructor === FormData ? b : JSON.stringify(b);
483
+ const stringifyBody = (b) => b instanceof FormData ? b : JSON.stringify(b);
469
484
  this.requestInput = props;
470
485
  const requests = getRequestsArray.call(this, props);
471
486
  const ABORTABLE_FETCH_CONTEXT = this;
472
487
  const abortController = new AbortController();
473
488
  const addProps = (response, request) => {
474
- response.request = request;
475
- if (ABORTABLE_FETCH_CONTEXT.#isResponseAsObject) response.name = getIsOnlyAnObject(request) ? request.name || "" : "";
476
- return response;
489
+ return Object.assign(response, {
490
+ request,
491
+ ...ABORTABLE_FETCH_CONTEXT.#isResponseAsObject ? { name: getIsOnlyAnObject(request) ? request.name || "" : "" } : {}
492
+ });
477
493
  };
478
- let externalRequest = Promise.all(
479
- requests.map(async (item) => {
494
+ const externalRequest = Promise.all(
495
+ requests.map((item) => {
480
496
  const safelyQuery = item.path.includes("?") ? `&${item.queryParameters.replace(/\?/g, "")}` : item.queryParameters;
481
497
  const internalRequest = fetch(`${item.pathPrefix}${item.path}${safelyQuery}`, {
482
498
  ...item.options,
@@ -487,12 +503,15 @@ var AbortableFetch2 = class {
487
503
  }).then(async (response) => addProps(response, item)).catch(async (response) => {
488
504
  if (response instanceof Response) return Promise.resolve(addProps(response, item));
489
505
  return Promise.resolve(
490
- addProps({
491
- ok: false,
492
- status: 0,
493
- statusText: response,
494
- request: item
495
- })
506
+ addProps(
507
+ {
508
+ ok: false,
509
+ status: 0,
510
+ statusText: response,
511
+ request: item
512
+ },
513
+ item
514
+ )
496
515
  );
497
516
  }).then(async (res) => {
498
517
  return typeof ABORTABLE_FETCH_CONTEXT.#everyPromiseCallback === "function" && !item.isSkipEveryPromiseCallback ? await ABORTABLE_FETCH_CONTEXT.#everyPromiseCallback(res) : res;
@@ -501,7 +520,8 @@ var AbortableFetch2 = class {
501
520
  }).then(async (res) => {
502
521
  return { request: item, response: res, ...item.name ? { name: item.name } : {} };
503
522
  });
504
- internalRequest.__proto__.abort = () => abortController.abort();
523
+ const internalProto = Object.getPrototypeOf(internalRequest);
524
+ internalProto.abort = () => abortController.abort();
505
525
  return internalRequest;
506
526
  })
507
527
  ).then(async (resArr) => {
@@ -509,16 +529,17 @@ var AbortableFetch2 = class {
509
529
  return ABORTABLE_FETCH_CONTEXT.#isResponseAsObject ? {} : [];
510
530
  }
511
531
  if (ABORTABLE_FETCH_CONTEXT.#isResponseAsObject === RESPONSE_AS_OBJECT_ALWAYS_VALUE2) {
512
- return resArr.reduce((ac, item) => ({ ...ac, [item.name]: item.response }), {});
532
+ return resArr.reduce((ac, item) => ({ ...ac, [String(item.name)]: item.response }), {});
513
533
  }
514
534
  if (resArr.length === 1) return resArr[0].response;
515
- return ABORTABLE_FETCH_CONTEXT.#isResponseAsObject === true ? resArr.reduce((ac, item) => ({ ...ac, [item.name]: item.response }), {}) : resArr.map((item) => item.response);
535
+ return ABORTABLE_FETCH_CONTEXT.#isResponseAsObject === true ? resArr.reduce((ac, item) => ({ ...ac, [String(item.name)]: item.response }), {}) : resArr.map((item) => item.response);
516
536
  }).then(async (res) => {
517
537
  return typeof ABORTABLE_FETCH_CONTEXT.#callback === "function" ? await ABORTABLE_FETCH_CONTEXT.#callback(res) : res;
518
538
  }).catch(async (res) => {
519
539
  return typeof ABORTABLE_FETCH_CONTEXT.#catchCallback === "function" ? await ABORTABLE_FETCH_CONTEXT.#catchCallback(res) : res;
520
540
  });
521
- externalRequest.__proto__.abort = () => abortController.abort();
541
+ const externalProto = Object.getPrototypeOf(externalRequest);
542
+ externalProto.abort = () => abortController.abort();
522
543
  return externalRequest;
523
544
  function getRequestsArray(input) {
524
545
  const requestsArray = (() => {
@@ -543,15 +564,17 @@ var AbortableFetch2 = class {
543
564
  callback: omitCallback,
544
565
  mergeProps: omitMergeProps,
545
566
  ...optionsRest
546
- } = options || {};
567
+ } = getIsOnlyAnObject(options) ? options : {};
568
+ const localMethod = typeof method === "string" && isHttpMethod(method) ? method : null;
569
+ const localCallback = typeof callback === "function" ? (res) => callback(res) : void 0;
547
570
  return [
548
571
  ...ac,
549
572
  {
550
573
  path,
551
574
  pathPrefix: getMergeProps("pathPrefix") === "onlyLocal" || isNoPathPrefix ? "" : this.#pathPrefix || "",
552
575
  method: (() => {
553
- if (getMergeProps("method") === "onlyLocal") return method || "GET";
554
- return getMergeProps("method") === "onlyGlobal" ? this.#method || "GET" : method || this.#method || "GET";
576
+ if (getMergeProps("method") === "onlyLocal") return localMethod || "GET";
577
+ return getMergeProps("method") === "onlyGlobal" ? this.#method || "GET" : localMethod || this.#method || "GET";
555
578
  })(),
556
579
  queryParameters: (() => {
557
580
  if ((getMergeProps("queryParameters") ?? getMergeProps("query")) === "onlyLocal") {
@@ -560,31 +583,34 @@ var AbortableFetch2 = class {
560
583
  return (getMergeProps("queryParameters") ?? getMergeProps("query")) === "onlyGlobal" ? this.getQueryString(this.getQueryArray(this.#queryParameters)) : this.getQueryString([...this.getQueryArray(this.#queryParameters), ...this.getQueryArray(queryParameters)]);
561
584
  })(),
562
585
  headers: (() => {
563
- if (getMergeProps("headers") === "onlyLocal") return this.getHeadersObj(headers || {});
586
+ if (getMergeProps("headers") === "onlyLocal") return this.getHeadersObj(getIsOnlyAnObject(headers) ? headers : {});
564
587
  return getMergeProps("headers") === "onlyGlobal" ? this.getHeadersObj({ ...this.#headers || {} }) : this.getHeadersObj({
565
588
  ...this.#headers || {},
566
- ...headers || {}
589
+ ...getIsOnlyAnObject(headers) ? headers : {}
567
590
  });
568
591
  })(),
569
592
  body: (() => {
570
593
  if (getMergeProps("body") === "onlyLocal") return body || null;
571
594
  if (getMergeProps("body") === "onlyGlobal") return this.#body || null;
572
595
  if (body && this.#body && typeof body === typeof this.#body && typeof body === "object") {
573
- return Array.isArray(body) ? [...this.#body, ...body] : { ...this.#body, ...body };
574
- } else return body || this.#body || null;
596
+ return Array.isArray(body) ? [...Array.isArray(this.#body) ? this.#body : [], ...body] : { ...getIsOnlyAnObject(this.#body) ? this.#body : {}, ...getIsOnlyAnObject(body) ? body : {} };
597
+ } else {
598
+ return body || this.#body || null;
599
+ }
575
600
  })(),
576
601
  options: (() => {
577
- if (getMergeProps("options") === "onlyLocal") return { ...optionsRest || {} };
578
- return getMergeProps("options") === "onlyGlobal" ? { ...this.#options || {} } : { ...this.#options || {}, ...optionsRest || {} };
602
+ if (getMergeProps("options") === "onlyLocal") return { ...optionsRest };
603
+ return getMergeProps("options") === "onlyGlobal" ? { ...this.#options || {} } : { ...this.#options || {}, ...optionsRest };
579
604
  })(),
580
- callback,
581
- isSkipEveryPromiseCallback,
605
+ callback: localCallback,
606
+ isSkipEveryPromiseCallback: Boolean(isSkipEveryPromiseCallback),
582
607
  ...this.getIsResponseAsObject() ? { name: name && typeof name === "string" ? name : index } : {}
583
608
  }
584
609
  ];
585
610
  }, []);
586
611
  }
587
612
  }
613
+ /** Повторяет последний выполненный запрос (ту же пачку). */
588
614
  repeatRequest() {
589
615
  return this.request(this.requestInput);
590
616
  }
@@ -600,19 +626,23 @@ var AbortableFetch2 = class {
600
626
  return this.#method;
601
627
  }
602
628
  setMethod(value) {
603
- const methods = ["GET", "HEAD", "POST", "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE", "PATCH"];
604
- if (value && !methods.includes(value)) throw new Error("Not valid method value!");
629
+ if (value && !isHttpMethod(value)) throw new Error("Not valid method value!");
605
630
  this.#method = value || null;
606
631
  }
607
632
  getQueryParameters() {
608
633
  return this.#queryParameters;
609
634
  }
610
635
  getQueryArray(value) {
611
- if (typeof value === "string") return (value[0] === "?" ? value.slice(1) : value).split("&");
612
- else if (Array.isArray(value)) return value;
613
- else if (typeof value === "object" && value !== null) {
614
- return Object.keys(value).filter((key) => Boolean(key) && Boolean(value[key])).map((key) => `${key}=${value[key]}`);
615
- } else return [];
636
+ if (typeof value === "string") {
637
+ return (value[0] === "?" ? value.slice(1) : value).split("&");
638
+ } else if (Array.isArray(value)) {
639
+ return value.map((item) => `${item}`);
640
+ } else if (typeof value === "object" && value !== null) {
641
+ const record = getIsOnlyAnObject(value) ? value : {};
642
+ return Object.keys(record).filter((key) => Boolean(key) && Boolean(record[key])).map((key) => `${key}=${record[key]}`);
643
+ } else {
644
+ return [];
645
+ }
616
646
  }
617
647
  getQueryString(value) {
618
648
  if (!value) return "";
@@ -631,7 +661,7 @@ var AbortableFetch2 = class {
631
661
  if (!obj) return headers;
632
662
  if (typeof obj !== "object" || Array.isArray(obj)) throw new Error("Not valid headers value!");
633
663
  Object.keys(obj).forEach((key) => {
634
- headers.append(key, obj[key]);
664
+ headers.append(key, `${obj[key]}`);
635
665
  });
636
666
  return headers;
637
667
  }
@@ -707,39 +737,64 @@ var AbortableFetch2 = class {
707
737
  // isAnywayRunCallback,
708
738
  isResponseAsObject
709
739
  } = input;
710
- if (pathPrefix) this.setPathPrefix(pathPrefix);
711
- if (method) this.setMethod(method);
740
+ if (pathPrefix) this.setPathPrefix(typeof pathPrefix === "string" ? pathPrefix : null);
741
+ if (method) this.setMethod(typeof method === "string" && isHttpMethod(method) ? method : null);
712
742
  if (queryParameters) this.setQueryParameters(this.getQueryArray(queryParameters));
713
- if (headers) this.setHeaders(headers);
743
+ if (headers) this.setHeaders(getIsOnlyAnObject(headers) ? headers : null);
714
744
  if (body) this.setBody(body);
715
- if (options) this.setOptions(options);
716
- if (callback) this.setCallback(callback);
717
- if (catchCallback) this.setCatchCallback(catchCallback);
718
- if (everyPromiseCallback) this.setEveryPromiseCallback(everyPromiseCallback);
745
+ if (options) this.setOptions(getIsOnlyAnObject(options) ? options : null);
746
+ if (callback && typeof callback === "function") {
747
+ const fn = callback;
748
+ this.setCallback(function wrappedCallback(response) {
749
+ return fn.call(this, response);
750
+ });
751
+ }
752
+ if (catchCallback && typeof catchCallback === "function") {
753
+ const fn = catchCallback;
754
+ this.setCatchCallback(function wrappedCatchCallback(response) {
755
+ return fn.call(this, response);
756
+ });
757
+ }
758
+ if (everyPromiseCallback && typeof everyPromiseCallback === "function") {
759
+ const fn = everyPromiseCallback;
760
+ this.setEveryPromiseCallback(function wrappedEveryPromiseCallback(response) {
761
+ return fn.call(this, response);
762
+ });
763
+ }
719
764
  if (isResponseAsObject !== void 0) this.setIsResponseAsObject(isResponseAsObject);
720
765
  }
721
766
  };
722
767
  var AbortableFetch_default2 = AbortableFetch2;
723
768
 
724
- // src/Classes/RESTAPI/partials/_utils.js
769
+ // src/Classes/RESTAPI/partials/_utils.ts
725
770
  function getIsOnlyAnObject(input) {
726
- return typeof input === "object" && // "отбивает" примитивы и функции
727
- input instanceof Object && // "отбивает" null
728
- !Array.isArray(input) && // "отбивает" массивы
729
- !(input instanceof Set) && // "отбивает" сеты
730
- !(input instanceof Map);
771
+ return typeof input === "object" && input instanceof Object && !Array.isArray(input) && !(input instanceof Set) && !(input instanceof Map);
731
772
  }
732
- var clone = (input) => {
773
+ function clone(input) {
733
774
  if (input === null || typeof input !== "object") return input;
734
- const data = input instanceof Array ? [] : {};
735
- for (const i in input) data[i] = clone(input[i]);
775
+ if (Array.isArray(input)) return input.map((item) => clone(item));
776
+ const source = getIsOnlyAnObject(input) ? input : {};
777
+ const data = {};
778
+ Object.keys(source).forEach((key) => {
779
+ data[key] = clone(source[key]);
780
+ });
736
781
  return data;
737
- };
738
- var omitKeys = (obj = {}, keys = []) => keys.reduce((acc, key) => {
739
- const { [key]: omit, ...rest } = acc;
740
- return rest;
741
- }, obj);
742
- var getResponseClone = async (res) => typeof res?.clone === "function" ? await res.clone() : clone(res);
782
+ }
783
+ function omitKeys(obj, keys = []) {
784
+ const source = obj ?? {};
785
+ const keySet = new Set(keys);
786
+ const result = {};
787
+ Object.keys(source).forEach((key) => {
788
+ if (!keySet.has(key)) result[key] = source[key];
789
+ });
790
+ return result;
791
+ }
792
+ async function getResponseClone(res) {
793
+ if (res && typeof res === "object" && "clone" in res && typeof res.clone === "function") {
794
+ return res.clone();
795
+ }
796
+ return clone(res);
797
+ }
743
798
  function addCustomMethods(data, prefix) {
744
799
  const preparedPrefix = (prefix || "").toString();
745
800
  Object.keys(data).forEach((key) => {
@@ -753,7 +808,7 @@ async function getInstanceOfFetchSystem(isGetBody) {
753
808
  let credentials = {};
754
809
  if (CREDENTIALS_CONTEXT) {
755
810
  const cred = await CREDENTIALS_CONTEXT.getCredentials();
756
- credentials = CREDENTIALS_CONTEXT.isUseRefreshTokensPropcessing ? await CREDENTIALS_CONTEXT.waitRefresh(cred.isNeedRefresh && !CREDENTIALS_CONTEXT.getIsTokenStartRefresh()).then(
811
+ credentials = CREDENTIALS_CONTEXT.isUseRefreshTokensPropcessing ? await CREDENTIALS_CONTEXT.waitRefresh(Boolean(cred.isNeedRefresh) && !CREDENTIALS_CONTEXT.getIsTokenStartRefresh()).then(
757
812
  async () => CREDENTIALS_CONTEXT.processCredentials(await CREDENTIALS_CONTEXT.getCredentials())
758
813
  ) : cred;
759
814
  }
@@ -771,52 +826,57 @@ async function getInstanceOfFetchSystem(isGetBody) {
771
826
  }
772
827
  return (CREDENTIALS_CONTEXT?.isUseRefreshTokensPropcessing ? CREDENTIALS_CONTEXT.waitRefresh() : Promise.resolve()).then(
773
828
  async () => new AbortableFetch_default2({
774
- //? Метод по умолчанию
829
+ // ? Метод по умолчанию
775
830
  method: "GET",
776
- //? Заголовки по умолчанию
831
+ // ? Заголовки по умолчанию
777
832
  headers: {
778
833
  ...headersToAbortableFetchInstance,
779
- //? (*) Тут обрабатываются кейсы
780
- //? - когда нет this.credentialsProcessing
781
- //? (мы НЕ хотим добавлять токены в принципе, не зашли в верхнюю if-ку)
782
- //? - когда есть this.credentialsProcessing, но нет credentials.token (не авторизованы)
783
- //? (зашли в верхнюю if-ку, попробовали получить/обновить креды)
834
+ // ? (*) Тут обрабатываются кейсы
835
+ // ? - когда нет this.credentialsProcessing
836
+ // ? (мы НЕ хотим добавлять токены в принципе, не зашли в верхнюю if-ку)
837
+ // ? - когда есть this.credentialsProcessing, но нет credentials.token (не авторизованы)
838
+ // ? (зашли в верхнюю if-ку, попробовали получить/обновить креды)
784
839
  ...credentials.token ? CREDENTIALS_CONTEXT?.getHeadersForAuthorize?.(credentials.token) || {} : {}
785
840
  },
786
841
  queryParameters: await API_CONTEXT.processQueryParams(queryParamsToAbortableFetchInstance),
787
- //? Опции по умолчанию
842
+ // ? Опции по умолчанию
788
843
  options: {
789
844
  mode: "cors",
790
845
  redirect: "follow",
791
846
  ...optionsToAbortableFetchInstance
792
847
  },
793
- //? Каждый запрос (каждый запрос мультизапроса), сделаный методом request этого экземпляра выполнит этот колбек
848
+ // ? Каждый запрос (каждый запрос мультизапроса), сделаный методом request этого экземпляра выполнит этот колбек
794
849
  everyPromiseCallback: async function everyPromiseCallback(response) {
795
850
  const ABORTABLE_FETCH_INSTANCE = this;
796
851
  if (!response.status) {
797
- const request = ABORTABLE_FETCH_INSTANCE.requestInput.find((item) => item?.path === response?.request?.path);
798
- const isUseErrorToast = request?.mesageOptions?.isUseErrorToast;
852
+ const reqInput = ABORTABLE_FETCH_INSTANCE.requestInput;
853
+ const responseRequest = getIsOnlyAnObject(response.request) ? response.request : {};
854
+ const request = Array.isArray(reqInput) ? reqInput.find((item) => getIsOnlyAnObject(item) && item.path === responseRequest.path) : void 0;
855
+ const mesageOptions = getIsOnlyAnObject(request) && getIsOnlyAnObject(request.mesageOptions) ? request.mesageOptions : void 0;
856
+ const isUseErrorToast = mesageOptions?.isUseErrorToast;
799
857
  if (isUseErrorToast) {
800
- API_CONTEXT.sendMessage?.(API_CONTEXT.NO_INET, request.mesageOptions, response);
858
+ API_CONTEXT.sendMessage?.(API_CONTEXT.NO_INET, mesageOptions, response);
801
859
  }
802
860
  }
803
- return API_CONTEXT.REJECT_CODES.includes(response.status) || CREDENTIALS_CONTEXT?.isUseRefreshTokensPropcessing && CREDENTIALS_CONTEXT?.CODES_USING_THE_REFRESH_ATTEMPT?.includes?.(response.status) ? Promise.reject(new Error(`status:${response.status}`)) : Promise.resolve(!isGetBody ? response : await API_CONTEXT.getResponseBody(response));
861
+ 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));
804
862
  },
805
- //? Если хоть один запрос из пачки будет зареджекчен, зареджектится вся пачка.
806
- //? В этом случае будет выполнен этот колбэк
863
+ // ? Если хоть один запрос из пачки будет зареджекчен, зареджектится вся пачка.
864
+ // ? В этом случае будет выполнен этот колбэк
807
865
  catchCallback: async function catchCallback(res) {
808
866
  const ABORTABLE_FETCH_INSTANCE = this;
809
- const code = Number(res.message.split(":")[1]);
810
- if (CREDENTIALS_CONTEXT?.CODES_USING_THE_REFRESH_ATTEMPT?.includes?.(code)) {
811
- const isDoRefresh = !CREDENTIALS_CONTEXT?.getIsTokenStartRefresh?.();
812
- return CREDENTIALS_CONTEXT?.waitRefresh(isDoRefresh).then(async () => {
813
- const newCredentials = await CREDENTIALS_CONTEXT?.processCredentials({
814
- ...await CREDENTIALS_CONTEXT?.getCredentials(true),
867
+ if (!CREDENTIALS_CONTEXT) return Promise.reject(res);
868
+ const code = Number(res instanceof Error ? res.message.split(":")[1] : "");
869
+ if (CREDENTIALS_CONTEXT.CODES_USING_THE_REFRESH_ATTEMPT?.includes(code)) {
870
+ const isDoRefresh = !CREDENTIALS_CONTEXT.getIsTokenStartRefresh();
871
+ return CREDENTIALS_CONTEXT.waitRefresh(isDoRefresh).then(async () => {
872
+ const newCredentials = await CREDENTIALS_CONTEXT.processCredentials({
873
+ ...await CREDENTIALS_CONTEXT.getCredentials(true),
815
874
  isCatchCallbackProcess: isDoRefresh
816
875
  });
876
+ const currentHeaders = ABORTABLE_FETCH_INSTANCE.getHeaders();
817
877
  ABORTABLE_FETCH_INSTANCE.setHeaders({
818
- ...ABORTABLE_FETCH_INSTANCE.getHeaders(),
819
- ...newCredentials?.token ? { Authorization: `Bearer ${newCredentials?.token}` } : {}
878
+ ...getIsOnlyAnObject(currentHeaders) ? currentHeaders : {},
879
+ ...newCredentials.token ? { Authorization: `Bearer ${newCredentials.token}` } : {}
820
880
  });
821
881
  if (newCredentials.token) return ABORTABLE_FETCH_INSTANCE.repeatRequest();
822
882
  return Promise.reject(res);
@@ -828,13 +888,23 @@ async function getInstanceOfFetchSystem(isGetBody) {
828
888
  );
829
889
  }
830
890
 
831
- // src/Classes/RESTAPI/partials/Utils.js
891
+ // src/Classes/RESTAPI/partials/Utils.ts
832
892
  var Utils = class {
833
- //! Могут содержаться НЕасинхронные методы!
834
- //? Ф-я normalizeQueryParams является нормализатором сложных квери
835
- //? Например: &key1=&&&===&&&key2====&&&&&&&&key3=....
836
- //? Для корректной работы на вход нужно подавать НЕ кодированные значения
837
- //? По умолчанию выходные значения квери-параметров НЕ кодируются
893
+ // ! Могут содержаться НЕасинхронные методы!
894
+ /**
895
+ * Нормализатор сложных query-параметров.
896
+ *
897
+ * Например: `&key1=&&&===&&&key2====&&&&&&&&key3=...`. Для корректной работы на вход нужно подавать
898
+ * НЕ кодированные значения. По умолчанию выходные значения query-параметров НЕ кодируются.
899
+ *
900
+ * @param queryParams - query в виде строки, массива или объекта.
901
+ * @param settings - формат вывода (`array` | `string` | `object`) и флаг кодирования.
902
+ * @returns Нормализованные query-параметры в выбранном формате.
903
+ */
904
+ // ? Ф-я normalizeQueryParams является нормализатором сложных квери
905
+ // ? Например: &key1=&&&===&&&key2====&&&&&&&&key3=....
906
+ // ? Для корректной работы на вход нужно подавать НЕ кодированные значения
907
+ // ? По умолчанию выходные значения квери-параметров НЕ кодируются
838
908
  normalizeQueryParams(queryParams, settings) {
839
909
  if (settings && !getIsOnlyAnObject(settings)) {
840
910
  throw new Error("Bad settings [class Utils, normalizeQueryParams]");
@@ -853,9 +923,13 @@ var Utils = class {
853
923
  if (index === -1) return [item];
854
924
  return [item.slice(0, index), item.slice(index + 1)];
855
925
  }).filter(([key]) => Boolean(key)).map(([key, value]) => prepareParam(key, value));
856
- } else if (getIsOnlyAnObject(input)) return Object.keys(input).map((key) => prepareParam(key, input[key]));
857
- else if (typeof input === "string") return (input[0] === "?" ? input.slice(1) : input).split("&");
858
- else return [];
926
+ } else if (getIsOnlyAnObject(input)) {
927
+ return Object.keys(input).map((key) => prepareParam(key, input[key]));
928
+ } else if (typeof input === "string") {
929
+ return (input[0] === "?" ? input.slice(1) : input).split("&");
930
+ } else {
931
+ return [];
932
+ }
859
933
  };
860
934
  const { isEncode = false, outputAs = "array" } = settings || {};
861
935
  const initialStructure = getInitialArr(queryParams);
@@ -872,7 +946,9 @@ var Utils = class {
872
946
  if (index !== -1 && index !== 0) {
873
947
  const key = str.slice(0, index);
874
948
  acc.result.push(`${key}=${encodeURIComponent(str.slice(index + 1))}`);
875
- } else acc.toJoin = str;
949
+ } else {
950
+ acc.toJoin = str;
951
+ }
876
952
  if (idx === initialStructure.length - 1 && typeof acc.toJoin === "string") processToJoin(acc.toJoin);
877
953
  return acc;
878
954
  },
@@ -880,7 +956,7 @@ var Utils = class {
880
956
  ).result;
881
957
  const outputStructure = normalizedStructure.map((item) => {
882
958
  const [key, value] = item.split("=");
883
- return [key, !isEncode ? decodeURIComponent(value) : value];
959
+ return [key, !isEncode ? decodeURIComponent(value ?? "") : value ?? ""];
884
960
  });
885
961
  switch (outputAs) {
886
962
  case "string":
@@ -894,16 +970,25 @@ var Utils = class {
894
970
  };
895
971
  var Utils_default = Utils;
896
972
 
897
- // src/Classes/RESTAPI/partials/ApiUtils.js
973
+ // src/Classes/RESTAPI/partials/ApiUtils.ts
898
974
  var ApiUtils = class extends Utils_default {
975
+ /** Корневой путь API (раскладывается в ApiBase из constants.API_PATH). */
976
+ API_PATH;
899
977
  constructor(settings) {
900
978
  super();
901
979
  const { utils } = settings || {};
902
980
  if (getIsOnlyAnObject(utils)) addCustomMethods.call(this, utils);
903
981
  }
904
- //? Планируется, что метод будет использоваться неизменно, однако технически его можно перегрузить на экземпляре
905
- //? Метод не планировался как асинхронный,
906
- //? однако ввиду того что он может быть перегружен на экземпляре асинхронность предусматривается
982
+ /**
983
+ * Разбирает единый объект параметров запроса на части в зависимости от варианта использования.
984
+ *
985
+ * @param apiParams - объединённые параметры запроса.
986
+ * @param variant - `'doRequestMapping'` для мультизапроса либо `undefined` для одиночного.
987
+ * @returns Для `doRequestMapping` — объект параметров; иначе кортеж `[параметры, настройки]`.
988
+ */
989
+ // ? Планируется, что метод будет использоваться неизменно, однако технически его можно перегрузить на экземпляре
990
+ // ? Метод не планировался как асинхронный,
991
+ // ? однако ввиду того что он может быть перегружен на экземпляре асинхронность предусматривается
907
992
  async splitProperties(apiParams, variant) {
908
993
  const {
909
994
  isResponseAsObject,
@@ -962,79 +1047,224 @@ var ApiUtils = class extends Utils_default {
962
1047
  ];
963
1048
  }
964
1049
  }
965
- //! Обработчик пропы api из объекта описания запроса
966
- //? Планируется, что метод будет перегружаться на экземпляре,
967
- //? т.к. на разных проектах могут быть разные интерпретации пропы api
968
- //? Метод не планировался как асинхронный,
969
- //? однако ввиду того что он может быть перегружен на экземпляре асинхронность предусматривается
1050
+ /**
1051
+ * Обработчик пропы `api` из объекта описания запроса — возвращает корневой путь API.
1052
+ *
1053
+ * @returns Корневой путь (по умолчанию — API_PATH).
1054
+ */
1055
+ // ! Обработчик пропы api из объекта описания запроса
1056
+ // ? Планируется, что метод будет перегружаться на экземпляре,
1057
+ // ? т.к. на разных проектах могут быть разные интерпретации пропы api
1058
+ // ? Метод не планировался как асинхронный,
1059
+ // ? однако ввиду того что он может быть перегружен на экземпляре асинхронность предусматривается
970
1060
  async getRootPath() {
971
1061
  return this.API_PATH;
972
1062
  }
973
- //? Планируется, что метод будет использоваться неизменно, однако технически его можно перегрузить на экземпляре
974
- //? Метод планировался как асинхронный
1063
+ /**
1064
+ * Извлекает тело ответа в нужном виде (json/blob/text/arrayBuffer/formData) либо по content-type.
1065
+ *
1066
+ * @param response - объект Response (иначе значение возвращается как есть).
1067
+ * @param getBodyAs - желаемый способ извлечения тела.
1068
+ * @returns Промис с телом ответа (или исходным значением / null при ошибке).
1069
+ */
1070
+ // ? Планируется, что метод будет использоваться неизменно, однако технически его можно перегрузить на экземпляре
1071
+ // ? Метод планировался как асинхронный
975
1072
  async getResponseBody(response, getBodyAs) {
976
1073
  if (!(response instanceof Response)) return response;
977
1074
  const contentType = response.headers.get("content-type");
978
1075
  if (!contentType) return "";
979
- const executor = (() => {
980
- if (typeof getBodyAs === "string" && getBodyAs in response && typeof response[getBodyAs] === "function") {
981
- return response[getBodyAs];
982
- }
983
- if (typeof contentType === "string" && contentType.includes("text/csv")) {
984
- return response.blob;
985
- }
986
- return typeof contentType === "string" && contentType.includes("json") ? response.json : response.text;
987
- })();
1076
+ const bodyReaders = {
1077
+ json: (r) => r.json(),
1078
+ blob: (r) => r.blob(),
1079
+ text: (r) => r.text(),
1080
+ arrayBuffer: (r) => r.arrayBuffer(),
1081
+ formData: (r) => r.formData()
1082
+ };
1083
+ const isBodyKey = (key) => key in bodyReaders;
1084
+ const reader = typeof getBodyAs === "string" && isBodyKey(getBodyAs) ? bodyReaders[getBodyAs] : contentType.includes("text/csv") ? bodyReaders.blob : contentType.includes("json") ? bodyReaders.json : bodyReaders.text;
988
1085
  try {
989
- return await executor.call(response);
1086
+ return await reader(response);
990
1087
  } catch {
991
1088
  console.log("Failed to extract the body");
992
1089
  return null;
993
1090
  }
994
1091
  }
995
- //! Обработчик структуры для ошибки (не рендер месседжа, а имеено формирование ошибки),
996
- //? Планируется, что метод будет перегружаться на экземпляре,
997
- //? т.к. на разных проектах могут быть разные структуры тела ответа для ошибки
998
- //? Метод не планировался как асинхронный,
999
- //? однако ввиду того что он может быть перегружен на экземпляре асинхронность предусматривается
1000
- //? res - уже тело ответа
1092
+ /**
1093
+ * Формирует структуру ошибки из тела ответа (точка расширения под формат бэкенда).
1094
+ *
1095
+ * @param res - уже извлечённое тело ответа.
1096
+ * @returns Структура сообщения об ошибке.
1097
+ */
1098
+ // ! Обработчик структуры для ошибки (не рендер месседжа, а имеено формирование ошибки),
1099
+ // ? Планируется, что метод будет перегружаться на экземпляре,
1100
+ // ? т.к. на разных проектах могут быть разные структуры тела ответа для ошибки
1101
+ // ? Метод не планировался как асинхронный,
1102
+ // ? однако ввиду того что он может быть перегружен на экземпляре асинхронность предусматривается
1103
+ // ? res - уже тело ответа
1001
1104
  async getErrorMessage(res) {
1002
1105
  return res;
1003
1106
  }
1004
- //? Планируется, что метод будет использоваться неизменно, однако технически его можно перегрузить на экземпляре
1005
- //? Метод планировался как асинхронный
1107
+ /**
1108
+ * Проверяет код ответа и (если задан sendMessage) информирует пользователя об успехе/ошибке.
1109
+ *
1110
+ * @param res - объект Response (или совместимый с полем `ok`).
1111
+ * @param settings - сообщения и настройки тостов для данного запроса.
1112
+ * @returns Исходный `res` (метод не меняет ответ, только сигналит сообщением).
1113
+ */
1114
+ // ? Планируется, что метод будет использоваться неизменно, однако технически его можно перегрузить на экземпляре
1115
+ // ? Метод планировался как асинхронный
1006
1116
  async checkResponseCode(res, settings) {
1007
- if (typeof this.sendMessage !== "function") return res;
1117
+ const send = this.sendMessage;
1118
+ if (typeof send !== "function") return res;
1008
1119
  const { successMess, errorMess } = settings || {};
1009
- const message = res.ok ? successMess || this.DEFAULT_SUCCESS_MESSAGE : errorMess || await this.getErrorMessage(await this.getResponseBody(await getResponseClone(res)));
1120
+ const isOk = getIsOnlyAnObject(res) ? Boolean(res.ok) : false;
1121
+ const message = isOk ? successMess || this.DEFAULT_SUCCESS_MESSAGE : errorMess || await this.getErrorMessage(await this.getResponseBody(await getResponseClone(res)));
1010
1122
  try {
1011
- this.sendMessage(message, settings, await getResponseClone(res));
1012
- } catch (_error) {
1123
+ send(message, settings, await getResponseClone(res));
1124
+ } catch {
1013
1125
  }
1014
1126
  return res;
1015
1127
  }
1016
- //? Суть метода:
1017
- //? передать из вне структуры, которые будут использоваться для КАЖДОГО запроса сделанного экземпляром RESTAPI
1018
- //! Данные затрут прочие настройки КРОМЕ данных по логике авторизации
1019
- //? Планируется, что метод будет перегружаться на экземпляре
1020
- //? Метод не планировался как асинхронный,
1021
- //? однако ввиду того что он может быть перегружен на экземпляре асинхронность предусматривается
1128
+ /**
1129
+ * Структуры, которые будут использоваться для КАЖДОГО запроса, сделанного экземпляром RESTAPI.
1130
+ *
1131
+ * @returns Объект `{ headers, queryParameters, options }` (по умолчанию пустой).
1132
+ */
1133
+ // ? Суть метода:
1134
+ // ? передать из вне структуры, которые будут использоваться для КАЖДОГО запроса сделанного экземпляром RESTAPI
1135
+ // ! Данные затрут прочие настройки КРОМЕ данных по логике авторизации
1136
+ // ? Планируется, что метод будет перегружаться на экземпляре
1137
+ // ? Метод не планировался как асинхронный,
1138
+ // ? однако ввиду того что он может быть перегружен на экземпляре асинхронность предусматривается
1022
1139
  async addAsCommon() {
1023
1140
  return {};
1024
1141
  }
1025
- //! Обработчик квери-параметров для общего процессинга,
1026
- //! Например для кодирования decodeURIComponent или/и приведения в формат массива
1027
- //? Планируется, что метод будет перегружаться на экземпляре,
1028
- //? т.к. на разных проектах могут быть разные договоренности по форматам
1029
- //? Метод не планировался как асинхронный,
1030
- //? однако ввиду того что он может быть перегружен на экземпляре асинхронность предусматривается
1142
+ /**
1143
+ * Общий обработчик query-параметров (точка расширения, напр. кодирование/приведение к массиву).
1144
+ *
1145
+ * @param queryParams - входные query-параметры.
1146
+ * @returns Обработанные query-параметры (по умолчанию — без изменений).
1147
+ */
1148
+ // ! Обработчик квери-параметров для общего процессинга,
1149
+ // ! Например для кодирования decodeURIComponent или/и приведения в формат массива
1150
+ // ? Планируется, что метод будет перегружаться на экземпляре,
1151
+ // ? т.к. на разных проектах могут быть разные договоренности по форматам
1152
+ // ? Метод не планировался как асинхронный,
1153
+ // ? однако ввиду того что он может быть перегружен на экземпляре асинхронность предусматривается
1031
1154
  async processQueryParams(queryParams) {
1032
1155
  return queryParams;
1033
1156
  }
1034
1157
  };
1035
1158
  var ApiUtils_default = ApiUtils;
1036
1159
 
1037
- // src/Classes/RESTAPI/partials/ApiRequestCreators.js
1160
+ // src/Classes/RESTAPI/partials/sse.ts
1161
+ function parseSSEEvent(block) {
1162
+ if (typeof block !== "string") return null;
1163
+ const event = { event: "message", data: "", id: void 0, retry: void 0 };
1164
+ const dataLines = [];
1165
+ let hasField = false;
1166
+ block.split("\n").forEach((line) => {
1167
+ if (line === "" || line[0] === ":") return;
1168
+ const colonIdx = line.indexOf(":");
1169
+ const field = colonIdx === -1 ? line : line.slice(0, colonIdx);
1170
+ let value = colonIdx === -1 ? "" : line.slice(colonIdx + 1);
1171
+ if (value[0] === " ") value = value.slice(1);
1172
+ switch (field) {
1173
+ case "event":
1174
+ event.event = value;
1175
+ hasField = true;
1176
+ break;
1177
+ case "data":
1178
+ dataLines.push(value);
1179
+ hasField = true;
1180
+ break;
1181
+ case "id":
1182
+ event.id = value;
1183
+ hasField = true;
1184
+ break;
1185
+ case "retry":
1186
+ if (/^\d+$/.test(value)) {
1187
+ event.retry = Number(value);
1188
+ hasField = true;
1189
+ }
1190
+ break;
1191
+ default:
1192
+ break;
1193
+ }
1194
+ });
1195
+ if (!hasField) return null;
1196
+ event.data = dataLines.join("\n");
1197
+ return event;
1198
+ }
1199
+ function safeCall(fn, ...args) {
1200
+ if (typeof fn !== "function") return;
1201
+ try {
1202
+ fn(...args);
1203
+ } catch {
1204
+ }
1205
+ }
1206
+ async function readSSE(response, { onEvent, onChunk, handlers, parseJson } = {}) {
1207
+ const events = [];
1208
+ const stream = response.body;
1209
+ if (!stream) return events;
1210
+ const reader = stream.getReader();
1211
+ const decoder = new TextDecoder("utf-8");
1212
+ let buffer = "";
1213
+ let pendingCR = "";
1214
+ const normalize = (chunk) => chunk.replace(/\r\n|\r/g, "\n");
1215
+ const flush = (rawBlock) => {
1216
+ const event = parseSSEEvent(rawBlock);
1217
+ if (!event) return;
1218
+ if (parseJson && typeof event.data === "string" && event.data !== "") {
1219
+ try {
1220
+ event.data = JSON.parse(event.data);
1221
+ } catch {
1222
+ }
1223
+ }
1224
+ events.push(event);
1225
+ safeCall(onEvent, event);
1226
+ safeCall(onChunk, event.data, event);
1227
+ if (handlers) safeCall(handlers[event.event], event.data, event);
1228
+ };
1229
+ try {
1230
+ while (true) {
1231
+ const { done, value } = await reader.read();
1232
+ if (done) break;
1233
+ let chunk = pendingCR + decoder.decode(value, { stream: true });
1234
+ pendingCR = "";
1235
+ if (chunk.endsWith("\r")) {
1236
+ pendingCR = "\r";
1237
+ chunk = chunk.slice(0, -1);
1238
+ }
1239
+ buffer += normalize(chunk);
1240
+ let sepIdx;
1241
+ while ((sepIdx = buffer.indexOf("\n\n")) !== -1) {
1242
+ const rawBlock = buffer.slice(0, sepIdx);
1243
+ buffer = buffer.slice(sepIdx + 2);
1244
+ flush(rawBlock);
1245
+ }
1246
+ }
1247
+ buffer += normalize(pendingCR + decoder.decode());
1248
+ buffer = buffer.replace(/\n+$/g, "");
1249
+ if (buffer !== "") flush(buffer);
1250
+ } catch (error) {
1251
+ const name = error && typeof error === "object" && "name" in error ? error.name : void 0;
1252
+ if (name !== "AbortError") throw error;
1253
+ } finally {
1254
+ try {
1255
+ reader.releaseLock?.();
1256
+ } catch {
1257
+ }
1258
+ }
1259
+ return events;
1260
+ }
1261
+
1262
+ // src/Classes/RESTAPI/partials/ApiRequestCreators.ts
1263
+ function isStreamResponse(value) {
1264
+ if (!getIsOnlyAnObject(value) || !value.ok) return false;
1265
+ const body = value.body;
1266
+ return typeof body === "object" && body !== null && "getReader" in body && typeof body.getReader === "function";
1267
+ }
1038
1268
  var PREFIX_OF_CLASS_UTILS = "createRequest_";
1039
1269
  var ApiRequestCreators = class extends ApiUtils_default {
1040
1270
  constructor(settings) {
@@ -1042,8 +1272,14 @@ var ApiRequestCreators = class extends ApiUtils_default {
1042
1272
  const { requestsCreators } = settings || {};
1043
1273
  if (getIsOnlyAnObject(requestsCreators)) addCustomMethods.call(this, requestsCreators, PREFIX_OF_CLASS_UTILS);
1044
1274
  }
1045
- //? При типе toJson пользовательский callback на вход получит тело ответа реализованное методом Response.json()
1046
- //? независимо от насторойки isGetBody
1275
+ /**
1276
+ * Крейтер типа `toJson`: пользовательский callback получит тело ответа (Response.json()).
1277
+ *
1278
+ * @param props - объект описания запроса.
1279
+ * @param variant - вариант обработки splitProperties.
1280
+ */
1281
+ // ? При типе toJson пользовательский callback на вход получит тело ответа реализованное методом Response.json()
1282
+ // ? независимо от насторойки isGetBody
1047
1283
  async createRequest_toJson(props, variant) {
1048
1284
  const safelyProps = omitKeys(props, ["getBodyAs"]);
1049
1285
  return this.splitProperties(
@@ -1052,15 +1288,21 @@ var ApiRequestCreators = class extends ApiUtils_default {
1052
1288
  isGetBody: false,
1053
1289
  callback: async (res) => {
1054
1290
  const output = await this.getResponseBody(res, "json");
1055
- return await (safelyProps.callback?.(output) ?? output);
1291
+ return await (props.callback?.(output) ?? output);
1056
1292
  }
1057
1293
  },
1058
1294
  variant
1059
1295
  );
1060
1296
  }
1061
- //? При типе toJsonAdvanced пользовательский callback на вход получит структуру { response, result },
1062
- //? где response - объект Response, result - тело ответа реализованное методом Response.json()
1063
- //? независимо от насторойки isGetBody
1297
+ /**
1298
+ * Крейтер типа `toJsonAdvanced`: callback получит структуру `{ response, result }`.
1299
+ *
1300
+ * @param props - объект описания запроса.
1301
+ * @param variant - вариант обработки splitProperties.
1302
+ */
1303
+ // ? При типе toJsonAdvanced пользовательский callback на вход получит структуру { response, result },
1304
+ // ? где response - объект Response, result - тело ответа реализованное методом Response.json()
1305
+ // ? независимо от насторойки isGetBody
1064
1306
  async createRequest_toJsonAdvanced(props, variant) {
1065
1307
  const safelyProps = omitKeys(props, ["getBodyAs"]);
1066
1308
  return this.splitProperties(
@@ -1072,14 +1314,20 @@ var ApiRequestCreators = class extends ApiUtils_default {
1072
1314
  response: res,
1073
1315
  result: await this.getResponseBody(await getResponseClone(res), "json")
1074
1316
  };
1075
- return await (safelyProps.callback?.(output) ?? output);
1317
+ return await (props.callback?.(output) ?? output);
1076
1318
  }
1077
1319
  },
1078
1320
  variant
1079
1321
  );
1080
1322
  }
1081
- //? При типе blob пользовательский callback на вход получит тело ответа реализованное методом Response.blob(),
1082
- //? независимо от насторойки isGetBody
1323
+ /**
1324
+ * Крейтер типа `blob`: callback получит тело ответа (Response.blob()).
1325
+ *
1326
+ * @param props - объект описания запроса.
1327
+ * @param variant - вариант обработки splitProperties.
1328
+ */
1329
+ // ? При типе blob пользовательский callback на вход получит тело ответа реализованное методом Response.blob(),
1330
+ // ? независимо от насторойки isGetBody
1083
1331
  async createRequest_blob(props, variant) {
1084
1332
  const safelyProps = omitKeys(props, ["getBodyAs"]);
1085
1333
  return this.splitProperties(
@@ -1088,14 +1336,67 @@ var ApiRequestCreators = class extends ApiUtils_default {
1088
1336
  isGetBody: false,
1089
1337
  callback: async (res) => {
1090
1338
  const output = await this.getResponseBody(await getResponseClone(res), "blob");
1091
- return await (safelyProps.callback?.(output) ?? output);
1339
+ return await (props.callback?.(output) ?? output);
1092
1340
  }
1093
1341
  },
1094
1342
  variant
1095
1343
  );
1096
1344
  }
1097
- //? При типе testBadResponse пользовательский callback на вход получит объект Response в 401-м статусе
1098
- //? независимо независимо вообще ни от чего
1345
+ /**
1346
+ * Крейтер типа `sse`: обрабатывает ответ как поток Server-Sent Events (text/event-stream).
1347
+ *
1348
+ * Дополнительные пропы объекта описания запроса: `onEvent`, `onChunk`, `handlers`, `parseJson`.
1349
+ * По умолчанию добавляется заголовок `Accept: text/event-stream`. Метод doRequest резолвится
1350
+ * массивом всех событий ПОСЛЕ закрытия потока; отмена — методом `.abort()` возвращённого промиса.
1351
+ *
1352
+ * @param props - объект описания запроса (плюс onEvent/onChunk/handlers/parseJson).
1353
+ * @param variant - вариант обработки splitProperties.
1354
+ */
1355
+ // ? При типе sse запрос обрабатывается как поток Server-Sent Events (text/event-stream).
1356
+ // ? Дополнительные пропы объекта описания запроса:
1357
+ // ? - onEvent(event) — вызывается на каждое распарсенное событие { event, data, id, retry };
1358
+ // ? - onChunk(data, event) — вызывается на полезную нагрузку (поле data) каждого события;
1359
+ // ? - handlers — карта { имяСобытия: cb } для типизированной обработки по полю event
1360
+ // ? (например { delta, status, done }); cb получает (data, event);
1361
+ // ? - parseJson — если true, поле data каждого события прогоняется через JSON.parse.
1362
+ // ? По умолчанию добавляется заголовок Accept: text/event-stream (его можно переопределить через headers).
1363
+ // ? Пользовательский callback (если передан) на вход получит итоговый массив всех событий.
1364
+ // ? Метод doRequest резолвится массивом всех событий ПОСЛЕ закрытия потока;
1365
+ // ? отмена потока выполняется методом .abort() возвращённого промиса (через встроенный AbortController).
1366
+ async createRequest_sse(props, variant) {
1367
+ const safelyProps = omitKeys(props, ["getBodyAs", "onChunk", "onEvent", "handlers", "parseJson"]);
1368
+ const { onChunk, onEvent, handlers, parseJson } = props;
1369
+ const sseOptions = {
1370
+ onChunk: typeof onChunk === "function" ? (data, event) => onChunk(data, event) : void 0,
1371
+ onEvent: typeof onEvent === "function" ? (event) => onEvent(event) : void 0,
1372
+ parseJson: Boolean(parseJson),
1373
+ handlers: getIsOnlyAnObject(handlers) ? Object.keys(handlers).reduce((acc, key) => {
1374
+ const fn = handlers[key];
1375
+ acc[key] = typeof fn === "function" ? (data, event) => fn(data, event) : void 0;
1376
+ return acc;
1377
+ }, {}) : void 0
1378
+ };
1379
+ return this.splitProperties(
1380
+ {
1381
+ ...safelyProps,
1382
+ headers: { Accept: "text/event-stream", ...getIsOnlyAnObject(safelyProps.headers) ? safelyProps.headers : {} },
1383
+ isGetBody: false,
1384
+ callback: async (res) => {
1385
+ const output = isStreamResponse(res) ? await readSSE(res, sseOptions) : res;
1386
+ return await (props.callback?.(output) ?? output);
1387
+ }
1388
+ },
1389
+ variant
1390
+ );
1391
+ }
1392
+ /**
1393
+ * Крейтер типа `testBadResponse`: callback получит синтетический Response со статусом 401.
1394
+ *
1395
+ * @param props - объект описания запроса.
1396
+ * @param variant - вариант обработки splitProperties.
1397
+ */
1398
+ // ? При типе testBadResponse пользовательский callback на вход получит объект Response в 401-м статусе
1399
+ // ? независимо независимо вообще ни от чего
1099
1400
  async createRequest_testBadResponse(props, variant) {
1100
1401
  return this.splitProperties(
1101
1402
  {
@@ -1115,17 +1416,33 @@ var ApiRequestCreators = class extends ApiUtils_default {
1115
1416
  variant
1116
1417
  );
1117
1418
  }
1118
- //? По умолчанию пользовательский callback на вход получит
1119
- //? - либо объект Response
1120
- //? - либо тело ответа (в случае isGetBody: 'first') полученное методом getResponseBody (смотри класс ApiUtils)
1419
+ /**
1420
+ * Крейтер по умолчанию: callback получит объект Response (или тело ответа при isGetBody: 'first').
1421
+ *
1422
+ * @param props - объект описания запроса.
1423
+ * @param variant - вариант обработки splitProperties.
1424
+ */
1425
+ // ? По умолчанию пользовательский callback на вход получит
1426
+ // ? - либо объект Response
1427
+ // ? - либо тело ответа (в случае isGetBody: 'first') полученное методом getResponseBody (смотри класс ApiUtils)
1121
1428
  async createRequest_default(props, variant) {
1122
1429
  return this.splitProperties(props, variant);
1123
1430
  }
1124
1431
  };
1125
1432
  var ApiRequestCreators_default = ApiRequestCreators;
1126
1433
 
1127
- // src/Classes/RESTAPI/partials/ApiBase.js
1434
+ // src/Classes/RESTAPI/partials/ApiBase.ts
1128
1435
  var ApiBase = class extends ApiRequestCreators_default {
1436
+ /** Текст ошибки невалидных данных запроса. */
1437
+ BAD_REQUEST_DATA_TEXT;
1438
+ /** Текст сообщения об успехе по умолчанию. */
1439
+ DEFAULT_SUCCESS_MESSAGE;
1440
+ /** Текст сообщения об ошибке по умолчанию. */
1441
+ DEFAULT_ERROR_MESSAGE;
1442
+ /** Текст сообщения об отсутствии сети. */
1443
+ NO_INET;
1444
+ /** Коды ответа, по которым запрос считается отклонённым. */
1445
+ REJECT_CODES;
1129
1446
  constructor(settings) {
1130
1447
  super(settings);
1131
1448
  const {
@@ -1154,49 +1471,76 @@ var ApiBase = class extends ApiRequestCreators_default {
1154
1471
  };
1155
1472
  var ApiBase_default = ApiBase;
1156
1473
 
1157
- // src/Classes/RESTAPI/partials/CredentialsProcessing.js
1474
+ // src/Classes/RESTAPI/partials/CredentialsProcessing.ts
1158
1475
  function decodeJWT(token) {
1159
1476
  try {
1160
- const payload = token.split(".")[1];
1161
- return JSON.parse(atob(payload));
1162
- } catch (e) {
1477
+ const payload = token.split(".")[1] ?? "";
1478
+ const decoded = JSON.parse(atob(payload));
1479
+ return getIsOnlyAnObject(decoded) ? decoded : null;
1480
+ } catch {
1163
1481
  return null;
1164
1482
  }
1165
1483
  }
1166
1484
  var CredentialsProcessing = class {
1485
+ /** Включён ли флоу рефреша токенов. */
1486
+ isUseRefreshTokensPropcessing = false;
1487
+ /** Учётные данные по умолчанию (пустые). */
1488
+ DEFAULT_CREDENTIALS = {};
1489
+ /** Внешний метод получения учётных данных. */
1490
+ getCredentialsByOuter;
1491
+ /** Внешний метод формирования заголовков авторизации по токену. */
1492
+ getHeadersForAuthorize;
1493
+ /** Необязательный преобразователь учётных данных после getCredentials. */
1494
+ importCredentials;
1495
+ /** Необязательный метод сохранения учётных данных (обязателен для флоу рефреша). */
1496
+ saveCredentials;
1497
+ /** Внешний метод рефреша учётных данных. */
1498
+ refreshCredentialsByOuter;
1499
+ /** Полный путь до эндпоинта рефреша токена. */
1500
+ REFRESH_TOKEN_PATH;
1501
+ /** Коды ответа, по которым триггерится попытка рефреша. */
1502
+ CODES_USING_THE_REFRESH_ATTEMPT;
1503
+ /** Ключ флага «рефреш начат» в localStorage. */
1504
+ REFRESH_TOKEN_FLAG = "refreshTokenFlag";
1505
+ /** Интервал опроса флага обновления токена, мс. */
1506
+ INTERVAL_FOR_CHECKING_TOKEN_UPDATE = 50;
1507
+ /** Колбэк, вызываемый после неудачного рефреша. */
1508
+ callbackAfterRejectRefresh;
1509
+ /** Доступ к верхнему контексту RESTAPI (навешивается из конструктора RESTAPI). */
1510
+ getRESTAPIContext;
1167
1511
  constructor(settings) {
1168
1512
  const { credentialsProcessing } = settings;
1169
1513
  const {
1170
- //? Для корректной работы установки токенов в запросы от API
1171
- //? нужно передавать методы getCredentials и getHeadersForAuthorize
1514
+ // ? Для корректной работы установки токенов в запросы от API
1515
+ // ? нужно передавать методы getCredentials и getHeadersForAuthorize
1172
1516
  getCredentials,
1173
1517
  getHeadersForAuthorize,
1174
- //? На вход получит токен, должна вернуть объект для коструктора Headers
1175
- //? Так же опционально можно передавать
1518
+ // ? На вход получит токен, должна вернуть объект для коструктора Headers
1519
+ // ? Так же опционально можно передавать
1176
1520
  importCredentials,
1177
- //? если он передается, то он будет применяться к выводу от вызова getCredentials
1521
+ // ? если он передается, то он будет применяться к выводу от вызова getCredentials
1178
1522
  saveCredentials,
1179
- //? можно будет найти в объекте credentialsProcessing, чтобы использовать кастомными методами
1180
- //! Либо вызов getCredentials, либо цепочка вызовов importCredentials(getCredentials())
1181
- //! должна возвращать требуемую классом структуру
1182
- //! Класс требует структуры
1183
- //! - { token }, если флоу рефреш токена НЕ используется
1184
- //! - { token, refreshToken, expires }, если используется флоу рефреш токена
1523
+ // ? можно будет найти в объекте credentialsProcessing, чтобы использовать кастомными методами
1524
+ // ! Либо вызов getCredentials, либо цепочка вызовов importCredentials(getCredentials())
1525
+ // ! должна возвращать требуемую классом структуру
1526
+ // ! Класс требует структуры
1527
+ // ! - { token }, если флоу рефреш токена НЕ используется
1528
+ // ! - { token, refreshToken, expires }, если используется флоу рефреш токена
1185
1529
  // *********
1186
- //? Подключает флоу рефреша токенов
1530
+ // ? Подключает флоу рефреша токенов
1187
1531
  isUseRefreshTokensPropcessing = false,
1188
- //! Для корректной работы флоу рефреша токенов передача метода saveCredentials становится ОБЯЗАТЕЛЬНОЙ
1189
- //? Так же для корректной работы флоу рефреша токенов нужно
1190
- //? - либо
1532
+ // ! Для корректной работы флоу рефреша токенов передача метода saveCredentials становится ОБЯЗАТЕЛЬНОЙ
1533
+ // ? Так же для корректной работы флоу рефреша токенов нужно
1534
+ // ? - либо
1191
1535
  refreshCredentials,
1192
- //! метод должен возвращать такую же структуру как и метод getCredentials,
1193
- //? на вход получит текущие креды, к выходу будет применен importCredentials, если этот метод передавался
1194
- //? - либо
1536
+ // ! метод должен возвращать такую же структуру как и метод getCredentials,
1537
+ // ? на вход получит текущие креды, к выходу будет применен importCredentials, если этот метод передавался
1538
+ // ? - либо
1195
1539
  REFRESH_TOKEN_PATH,
1196
- //! REFRESH_TOKEN_PATH передается ПОЛНОСТЬЮ (глобальная адресация)!
1540
+ // ! REFRESH_TOKEN_PATH передается ПОЛНОСТЬЮ (глобальная адресация)!
1197
1541
  CODES_USING_THE_REFRESH_ATTEMPT,
1198
- //? указывает по каким кодам ответа триггериться рефреш, массив чисел
1199
- //? Опционально
1542
+ // ? указывает по каким кодам ответа триггериться рефреш, массив чисел
1543
+ // ? Опционально
1200
1544
  REFRESH_TOKEN_FLAG = "refreshTokenFlag",
1201
1545
  INTERVAL_FOR_CHECKING_TOKEN_UPDATE = 50,
1202
1546
  // ms
@@ -1204,40 +1548,44 @@ var CredentialsProcessing = class {
1204
1548
  } = credentialsProcessing || {};
1205
1549
  if (typeof getCredentials !== "function") throw new Error("No getCredentials method [CredentialsProcessing]");
1206
1550
  if (typeof getHeadersForAuthorize !== "function") {
1207
- throw new Error("No getHeadersForAuthorize method [CredentialsProcessing]");
1551
+ throw new TypeError("No getHeadersForAuthorize method [CredentialsProcessing]");
1208
1552
  }
1209
1553
  if (importCredentials && typeof importCredentials !== "function") {
1210
1554
  throw new Error("Bad importCredentials method [CredentialsProcessing]");
1211
1555
  }
1212
- this.isUseRefreshTokensPropcessing = isUseRefreshTokensPropcessing;
1556
+ this.isUseRefreshTokensPropcessing = Boolean(isUseRefreshTokensPropcessing);
1213
1557
  this.DEFAULT_CREDENTIALS = {};
1214
- this.getCredentialsByOuter = getCredentials;
1215
- this.getHeadersForAuthorize = getHeadersForAuthorize;
1216
- this.importCredentials = importCredentials;
1558
+ this.getCredentialsByOuter = () => getCredentials();
1559
+ this.getHeadersForAuthorize = (token) => {
1560
+ const result = getHeadersForAuthorize(token);
1561
+ return getIsOnlyAnObject(result) ? result : {};
1562
+ };
1563
+ if (typeof importCredentials === "function") this.importCredentials = (cred) => importCredentials(cred);
1217
1564
  if (saveCredentials || isUseRefreshTokensPropcessing) {
1218
1565
  if (typeof saveCredentials !== "function") throw new Error("No saveCredentials method [CredentialsProcessing]");
1219
- else this.saveCredentials = saveCredentials;
1566
+ else this.saveCredentials = (cred) => saveCredentials(cred);
1220
1567
  }
1221
1568
  if (isUseRefreshTokensPropcessing) {
1222
- if (typeof refreshCredentials === "function") this.refreshCredentialsByOuter = refreshCredentials;
1223
- else {
1569
+ if (typeof refreshCredentials === "function") {
1570
+ this.refreshCredentialsByOuter = (cred) => refreshCredentials(cred);
1571
+ } else {
1224
1572
  if (typeof this.refreshCredentialsByOuter === "function" && typeof REFRESH_TOKEN_PATH !== "string") {
1225
- throw new Error("No REFRESH_TOKEN_PATH [CredentialsProcessing]");
1573
+ throw new TypeError("No REFRESH_TOKEN_PATH [CredentialsProcessing]");
1226
1574
  }
1227
- this.REFRESH_TOKEN_PATH = REFRESH_TOKEN_PATH;
1575
+ this.REFRESH_TOKEN_PATH = typeof REFRESH_TOKEN_PATH === "string" ? REFRESH_TOKEN_PATH : void 0;
1228
1576
  }
1229
1577
  if (!Array.isArray(CODES_USING_THE_REFRESH_ATTEMPT)) {
1230
- throw new Error("No CODES_USING_THE_REFRESH_ATTEMPT [CredentialsProcessing]");
1578
+ throw new TypeError("No CODES_USING_THE_REFRESH_ATTEMPT [CredentialsProcessing]");
1231
1579
  }
1232
1580
  if (!CODES_USING_THE_REFRESH_ATTEMPT.every((i) => typeof i === "number")) {
1233
1581
  throw new Error("Invalid format of CODES_USING_THE_REFRESH_ATTEMPT elements [CredentialsProcessing]");
1234
1582
  }
1235
1583
  if (typeof REFRESH_TOKEN_FLAG !== "string") throw new Error("Bad REFRESH_TOKEN_FLAG [CredentialsProcessing]");
1236
1584
  if (typeof INTERVAL_FOR_CHECKING_TOKEN_UPDATE !== "number") {
1237
- throw new Error("Bad INTERVAL_FOR_CHECKING_TOKEN_UPDATE [CredentialsProcessing]");
1585
+ throw new TypeError("Bad INTERVAL_FOR_CHECKING_TOKEN_UPDATE [CredentialsProcessing]");
1238
1586
  }
1239
1587
  if (typeof INTERVAL_FOR_CHECKING_TOKEN_UPDATE !== "number") {
1240
- throw new Error("Bad INTERVAL_FOR_CHECKING_TOKEN_UPDATE [CredentialsProcessing]");
1588
+ throw new TypeError("Bad INTERVAL_FOR_CHECKING_TOKEN_UPDATE [CredentialsProcessing]");
1241
1589
  }
1242
1590
  if (callbackAfterRejectRefresh && typeof callbackAfterRejectRefresh !== "function") {
1243
1591
  throw new Error("Bad INTERVAL_FOR_CHECKING_TOKEN_UPDATE [CredentialsProcessing]");
@@ -1245,23 +1593,33 @@ var CredentialsProcessing = class {
1245
1593
  this.CODES_USING_THE_REFRESH_ATTEMPT = CODES_USING_THE_REFRESH_ATTEMPT;
1246
1594
  this.REFRESH_TOKEN_FLAG = REFRESH_TOKEN_FLAG;
1247
1595
  this.INTERVAL_FOR_CHECKING_TOKEN_UPDATE = INTERVAL_FOR_CHECKING_TOKEN_UPDATE;
1248
- if (callbackAfterRejectRefresh) this.callbackAfterRejectRefresh = callbackAfterRejectRefresh;
1596
+ if (typeof callbackAfterRejectRefresh === "function") this.callbackAfterRejectRefresh = () => callbackAfterRejectRefresh();
1249
1597
  }
1250
1598
  }
1599
+ /** Возвращает значение флага «рефреш начат» из localStorage. */
1251
1600
  getIsTokenStartRefresh() {
1252
1601
  return localStorage.getItem(this.REFRESH_TOKEN_FLAG);
1253
1602
  }
1603
+ /** Выставляет флаг «рефреш начат» в localStorage. */
1254
1604
  setIsTokenStartRefresh() {
1255
- localStorage.setItem(this.REFRESH_TOKEN_FLAG, true);
1605
+ localStorage.setItem(this.REFRESH_TOKEN_FLAG, String(true));
1256
1606
  }
1607
+ /** Снимает флаг «рефреш начат» из localStorage. */
1257
1608
  removeIsTokenStartRefresh() {
1258
1609
  localStorage.removeItem(this.REFRESH_TOKEN_FLAG);
1259
1610
  }
1611
+ /**
1612
+ * Возвращает текущие учётные данные (с учётом importCredentials и проверки истечения JWT).
1613
+ *
1614
+ * @param isCatchCallbackProcess - флаг процесса обработки ошибки (отключает проверку истечения).
1615
+ * @param callback - необязательный колбэк, получающий итоговые учётные данные.
1616
+ * @returns Промис с учётными данными.
1617
+ */
1260
1618
  async getCredentials(isCatchCallbackProcess, callback) {
1261
1619
  let credentials = await this.getCredentialsByOuter();
1262
1620
  if (typeof this.importCredentials === "function") credentials = await this.importCredentials(credentials);
1263
- if (!getIsOnlyAnObject(credentials)) credentials = {};
1264
- const token = credentials.token || null;
1621
+ const credObj = getIsOnlyAnObject(credentials) ? credentials : {};
1622
+ const token = credObj.token || null;
1265
1623
  if (token && !isCatchCallbackProcess) {
1266
1624
  let decoded;
1267
1625
  try {
@@ -1270,11 +1628,18 @@ var CredentialsProcessing = class {
1270
1628
  decoded = null;
1271
1629
  }
1272
1630
  const currentTime = Date.now() / 1e3;
1273
- if (decoded !== null && Number(decoded.exp) < currentTime) credentials = { ...credentials, isNeedRefresh: true };
1631
+ if (decoded !== null && Number(decoded.exp) < currentTime) credObj.isNeedRefresh = true;
1274
1632
  }
1275
- if (callback) await callback({ ...credentials, isCatchCallbackProcess });
1276
- return { ...credentials, isCatchCallbackProcess };
1277
- }
1633
+ if (callback) await callback({ ...credObj, isCatchCallbackProcess });
1634
+ return { ...credObj, isCatchCallbackProcess };
1635
+ }
1636
+ /**
1637
+ * Выполняет рефреш учётных данных (внешним методом либо дефолтным OAuth-флоу).
1638
+ *
1639
+ * @param currentCredentials - текущие учётные данные.
1640
+ * @param callback - необязательный колбэк сохранения новых учётных данных.
1641
+ * @returns Промис с новыми учётными данными.
1642
+ */
1278
1643
  async refreshCredentials(currentCredentials, callback) {
1279
1644
  const CONTEXT = this;
1280
1645
  async function finalize(cred) {
@@ -1287,11 +1652,10 @@ var CredentialsProcessing = class {
1287
1652
  if (!currentCredentials?.token || !currentCredentials?.refreshToken) return finalize(CONTEXT.DEFAULT_CREDENTIALS);
1288
1653
  async function refreshCredentialsByDefault() {
1289
1654
  const { token, refreshToken } = currentCredentials;
1290
- const headers = new Headers();
1291
- headers.append(...Object.entries(CONTEXT.getHeadersForAuthorize(token)));
1655
+ const headers = new Headers(Object.entries(CONTEXT.getHeadersForAuthorize(token || "")).map(([key, value]) => [key, `${value}`]));
1292
1656
  const body = new FormData();
1293
1657
  body.append("grant_type", "refresh_token");
1294
- body.append("refresh_token", refreshToken);
1658
+ body.append("refresh_token", refreshToken || "");
1295
1659
  body.append("client_id", "oauth");
1296
1660
  body.append("client_secret", "secret");
1297
1661
  body.append("access_type", "offline");
@@ -1304,8 +1668,14 @@ var CredentialsProcessing = class {
1304
1668
  });
1305
1669
  }
1306
1670
  const newCredentials = typeof CONTEXT.refreshCredentialsByOuter === "function" ? await CONTEXT.refreshCredentialsByOuter(currentCredentials) : await refreshCredentialsByDefault();
1307
- return finalize(newCredentials);
1308
- }
1671
+ return finalize(getIsOnlyAnObject(newCredentials) ? newCredentials : CONTEXT.DEFAULT_CREDENTIALS);
1672
+ }
1673
+ /**
1674
+ * Ожидает завершения рефреша токена (или запускает его флаг при необходимости).
1675
+ *
1676
+ * @param isNeedRefresh - выставить ли флаг «рефреш начат» при отсутствии активного рефреша.
1677
+ * @returns Промис, который резолвится по завершении ожидания.
1678
+ */
1309
1679
  async waitRefresh(isNeedRefresh) {
1310
1680
  return new Promise((resolve) => {
1311
1681
  if (!this.getIsTokenStartRefresh()) {
@@ -1321,10 +1691,16 @@ var CredentialsProcessing = class {
1321
1691
  }
1322
1692
  });
1323
1693
  }
1694
+ /**
1695
+ * Обрабатывает учётные данные: при необходимости рефрешит токен и возвращает актуальные данные.
1696
+ *
1697
+ * @param cred - текущие учётные данные.
1698
+ * @returns Промис с актуальными учётными данными (с флагом isRefreshFailed при неудаче).
1699
+ */
1324
1700
  async processCredentials(cred) {
1325
1701
  if (!cred.isNeedRefresh && !cred.isCatchCallbackProcess) return cred;
1326
1702
  const CONTEXT = this;
1327
- return CONTEXT.refreshCredentials(cred, (response) => CONTEXT.saveCredentials(response)).then(() => {
1703
+ return CONTEXT.refreshCredentials(cred, (response) => CONTEXT.saveCredentials?.(response)).then(() => {
1328
1704
  return new Promise((resolve) => {
1329
1705
  setTimeout(async () => {
1330
1706
  const newCredentials = await CONTEXT.getCredentials();
@@ -1342,11 +1718,15 @@ var CredentialsProcessing = class {
1342
1718
  };
1343
1719
  var CredentialsProcessing_default = CredentialsProcessing;
1344
1720
 
1345
- // src/Classes/RESTAPI/index.js
1721
+ // src/Classes/RESTAPI/index.ts
1346
1722
  function returnTheContext() {
1347
1723
  return this;
1348
1724
  }
1349
1725
  var RESTAPI = class extends ApiBase_default {
1726
+ /** Функция показа сообщений пользователю (или null, если информирование отключено). */
1727
+ sendMessage = null;
1728
+ /** Обработчик учётных данных (создаётся при наличии настройки credentialsProcessing). */
1729
+ credentialsProcessing;
1350
1730
  constructor(settings) {
1351
1731
  super(settings);
1352
1732
  const { sendMessage, credentialsProcessing } = settings || {};
@@ -1356,7 +1736,14 @@ var RESTAPI = class extends ApiBase_default {
1356
1736
  this.credentialsProcessing.getRESTAPIContext = returnTheContext.bind(this);
1357
1737
  }
1358
1738
  }
1359
- //! Основной (базовый) метод API, мультизапросы
1739
+ /**
1740
+ * Основной (базовый) метод API: выполняет мультизапрос (или одиночный запрос).
1741
+ *
1742
+ * @param inputRequests - путь, объект описания запроса или их массив.
1743
+ * @param settings - общие настройки запроса (формат ответа, тосты, сообщения и т.п.).
1744
+ * @returns Промис с результатом (форма зависит от isResponseAsObject).
1745
+ */
1746
+ // ! Основной (базовый) метод API, мультизапросы
1360
1747
  async doRequest(inputRequests, settings) {
1361
1748
  if (typeof inputRequests !== "string" && typeof inputRequests !== "object") {
1362
1749
  return Promise.reject(new Error(this.BAD_REQUEST_DATA_TEXT));
@@ -1380,24 +1767,29 @@ var RESTAPI = class extends ApiBase_default {
1380
1767
  throw new Error("It is impossible to make a request!");
1381
1768
  }
1382
1769
  instance.setIsResponseAsObject(isResponseAsObject ?? true);
1383
- if (callback) instance.setCallback(callback);
1770
+ if (typeof callback === "function") instance.setCallback(callback);
1384
1771
  function getRequests() {
1385
1772
  let output;
1386
1773
  if (typeof inputRequests === "string") output = [{ path: inputRequests }];
1387
1774
  else output = Array.isArray(inputRequests) ? inputRequests : [inputRequests];
1388
1775
  function getCallback(item, mesageOptions) {
1389
- const { getBodyAs } = item;
1776
+ const getBodyAs = typeof item.getBodyAs === "string" ? item.getBodyAs : void 0;
1390
1777
  const finalIsGetBody = typeof item.isGetBody === "boolean" || typeof item.isGetBody === "string" ? item.isGetBody : isGetBody;
1391
1778
  const finalIsGetBodyFirst = finalIsGetBody === "first";
1392
- const checkResponseCallback = finalIsGetBodyFirst ? async (res, mesageOptions2) => API_CONTEXT.getResponseBody(await API_CONTEXT.checkResponseCode(res, mesageOptions2), getBodyAs) : async (res, mesageOptions2) => API_CONTEXT.checkResponseCode(res, mesageOptions2);
1393
- const callback2 = item.callback ? async (res) => item.callback(await checkResponseCallback(res, mesageOptions)) : async (res) => checkResponseCallback(res, mesageOptions);
1394
- return finalIsGetBody && !finalIsGetBodyFirst ? async (res) => API_CONTEXT.getResponseBody(await callback2(res), getBodyAs) : callback2;
1779
+ const checkResponseCallback = finalIsGetBodyFirst ? async (res, options) => API_CONTEXT.getResponseBody(await API_CONTEXT.checkResponseCode(res, options), getBodyAs) : async (res, options) => API_CONTEXT.checkResponseCode(res, options);
1780
+ const itemCallback = item.callback;
1781
+ const callbackFn = typeof itemCallback === "function" ? async (res) => itemCallback(await checkResponseCallback(res, mesageOptions)) : async (res) => checkResponseCallback(res, mesageOptions);
1782
+ return finalIsGetBody && !finalIsGetBodyFirst ? async (res) => API_CONTEXT.getResponseBody(await callbackFn(res), getBodyAs) : callbackFn;
1395
1783
  }
1396
1784
  async function getRequestItem(item, idx) {
1397
- const { type, ...partialRestFirst } = item;
1785
+ const itemObj = getIsOnlyAnObject(item) ? item : { path: item };
1786
+ const { type, ...partialRestFirst } = itemObj;
1398
1787
  const itemAfterRequestCreating = await (async () => {
1399
- const key = `createRequest_${type ?? "default"}`;
1400
- return key in API_CONTEXT ? API_CONTEXT[key](partialRestFirst, "doRequestMapping") : API_CONTEXT.createRequest_default(partialRestFirst, "doRequestMapping");
1788
+ const key = `createRequest_${typeof type === "string" ? type : "default"}`;
1789
+ const creator = key in API_CONTEXT ? API_CONTEXT[key] : void 0;
1790
+ const result = typeof creator === "function" ? creator.call(API_CONTEXT, partialRestFirst, "doRequestMapping") : API_CONTEXT.createRequest_default(partialRestFirst, "doRequestMapping");
1791
+ const awaited = await result;
1792
+ return getIsOnlyAnObject(awaited) ? awaited : {};
1401
1793
  })();
1402
1794
  const { fullPath, api, path, query, queryParameters, ...partialRestSecond } = itemAfterRequestCreating;
1403
1795
  const {
@@ -1413,23 +1805,25 @@ var RESTAPI = class extends ApiBase_default {
1413
1805
  isNoToast,
1414
1806
  ...rest
1415
1807
  } = partialRestSecond;
1808
+ const successMessagesArr = Array.isArray(successMessages) ? successMessages : void 0;
1809
+ const errorMessagesArr = Array.isArray(errorMessages) ? errorMessages : void 0;
1416
1810
  const useSuccessMessageFlag = Boolean(
1417
- successMess || commonSuccessMessage || successMessages?.[idx] || CSMfromSettings || isToastResult || isToastFromSettings
1811
+ successMess || commonSuccessMessage || successMessagesArr?.[idx] || CSMfromSettings || isToastResult || isToastFromSettings
1418
1812
  );
1419
1813
  const isUseSuccessToast = useSuccessMessageFlag && !isNoToast && !isNoToastFromSettings && !isNoToastSuccess && !isNTSFromSettings;
1420
1814
  const isUseErrorToast = !isNoToast && !isNoToastFromSettings && !isNoToastError && !isNTEFromSettings;
1421
1815
  const mesageOptions = {
1422
- successMess: successMess || commonSuccessMessage || successMessages?.[idx] || CSMfromSettings,
1816
+ successMess: successMess || commonSuccessMessage || successMessagesArr?.[idx] || CSMfromSettings,
1423
1817
  successMessageType: successMessageType || SMTfromSettings,
1424
- errorMess: errorMess || commonErrorMessage || errorMessages?.[idx] || CEMfromSettings,
1818
+ errorMess: errorMess || commonErrorMessage || errorMessagesArr?.[idx] || CEMfromSettings,
1425
1819
  isUseSuccessToast,
1426
1820
  isUseErrorToast,
1427
1821
  toastOptions: toastOptions || TOFomSettings
1428
1822
  };
1429
1823
  return {
1430
1824
  ...rest,
1431
- path: `${fullPath || await API_CONTEXT.getRootPath(api) + (path || "")}`,
1432
- //? Запускаем самовызывающуюся асинхронную ф-ю, ждем резолва промиса от нее
1825
+ path: `${fullPath || await API_CONTEXT.getRootPath() + (typeof path === "string" ? path : "")}`,
1826
+ // ? Запускаем самовызывающуюся асинхронную ф-ю, ждем резолва промиса от нее
1433
1827
  queryParameters: await (async () => {
1434
1828
  const queryParams = query || queryParameters || "";
1435
1829
  const preparedQueryParams = await API_CONTEXT.processQueryParams(queryParams);
@@ -1439,28 +1833,26 @@ var RESTAPI = class extends ApiBase_default {
1439
1833
  callback: getCallback(itemAfterRequestCreating, mesageOptions)
1440
1834
  };
1441
1835
  }
1442
- return output?.map((item, idx) => getRequestItem(item, idx));
1836
+ return output.map((item, idx) => getRequestItem(item, idx));
1443
1837
  }
1444
1838
  return instance.request(await Promise.all(getRequests()));
1445
1839
  }
1446
- //! Метод API для одиночных запросов
1840
+ /**
1841
+ * Метод API для одиночных запросов: применяет крейтер по `type` и делегирует в {@link RESTAPI.doRequest}.
1842
+ *
1843
+ * @param requestSettings - объект описания одиночного запроса (с необязательным `type`).
1844
+ * @returns Промис с результатом запроса.
1845
+ */
1846
+ // ! Метод API для одиночных запросов
1447
1847
  async doMonoRequest(requestSettings) {
1448
1848
  if (!getIsOnlyAnObject(requestSettings)) throw new Error(`${this.BAD_REQUEST_DATA_TEXT} [RESTAPI.doMonoRequest]`);
1449
1849
  const { type, ...requestSettingsRest } = requestSettings;
1450
- const doRequestArgs = type && this[`createRequest_${type}`] ? [...await this[`createRequest_${type}`](requestSettingsRest)] : [...await this.createRequest_default(requestSettingsRest)];
1451
- return this.doRequest(...doRequestArgs);
1850
+ const key = `createRequest_${typeof type === "string" ? type : ""}`;
1851
+ const creator = type && key in this ? this[key] : void 0;
1852
+ const created = typeof creator === "function" ? await creator.call(this, requestSettingsRest) : await this.createRequest_default(requestSettingsRest);
1853
+ const doRequestArgs = Array.isArray(created) ? created : [created];
1854
+ return this.doRequest(doRequestArgs[0], doRequestArgs[1]);
1452
1855
  }
1453
1856
  };
1454
1857
  var RESTAPI_default = RESTAPI;
1455
- //! При получении экземпляра, если sendMessage не является ф-ей,
1456
- //! то это воспринимается как отключение шага информирования об ошибке запроса как такового
1457
- //! Планируемая структура { headers, queryParameters, options }, где
1458
- //! - headers и options - объекты,
1459
- //! - queryParameters - строка, массив или объект
1460
- //! ВНИМАНИЕ! Данный механизм рефреша принят на проекте finturfreactfrontend (админка)
1461
- //! На кабинете он ТОЧНО НЕ ТАКОЙ
1462
- //! currentCredentials передаются в формате класса! ({ token, refreshToken, expires })
1463
- //! Наличие credentialsProcessing подключает ДОБАВЛЕНИЕ ТОКЕНОВ В ЗАПРОСЫ,
1464
- //! НО по умолчанию НЕ добавляет флоу рефреша токенов
1465
- //! (флоу рефреша подключается пропой isUseRefreshTokensPropcessing из credentialsProcessing)
1466
1858
  //# sourceMappingURL=classes.cjs.map