@iblai/web-utils 1.6.2 → 1.6.3

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/index.js CHANGED
@@ -3093,6 +3093,7 @@ function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure,
3093
3093
  if (isProtectedRoute && storageService) {
3094
3094
  const dmTokenInLocalStorage = await storageService.getItem(LOCAL_STORAGE_KEYS.DM_TOKEN_KEY);
3095
3095
  console.log("[auth-redirect] local storage keys ", LOCAL_STORAGE_KEYS);
3096
+ console.log("[auth-redirect] local storage ", JSON.stringify(localStorage));
3096
3097
  const dmTokenExpired = await isDmTokenExpired(storageService);
3097
3098
  if (!dmTokenInLocalStorage || dmTokenExpired) {
3098
3099
  if (!!dmTokenInLocalStorage) {
@@ -13744,44 +13745,71 @@ const getHeaders = async (service) => {
13744
13745
  }
13745
13746
  return token ? { Authorization: `${prefix} ${token}` } : undefined;
13746
13747
  };
13748
+ /** Status codes that should not be retried for queryFn endpoints. */
13749
+ const QUERYFN_NON_RETRYABLE_STATUSES = [401, 403, 500];
13750
+ /** Default max retries for queryFn endpoints. */
13751
+ const QUERYFN_MAX_RETRIES = 5;
13752
+ /** Base delay in ms for exponential backoff. */
13753
+ const QUERYFN_BASE_DELAY_MS = 1000;
13747
13754
  /**
13748
13755
  * Build a generic RTK Query endpoint from a service function.
13756
+ * Includes built-in retry with exponential backoff (since RTK Query
13757
+ * skips baseQuery retry for queryFn endpoints).
13749
13758
  */
13750
- const buildEndpointFromService = (service, serviceFn) => {
13759
+ const buildEndpointFromService = (service, serviceFn, options) => {
13760
+ var _a;
13761
+ const maxRetries = (_a = void 0 ) !== null && _a !== void 0 ? _a : QUERYFN_MAX_RETRIES;
13751
13762
  return {
13752
13763
  async queryFn(args) {
13753
- try {
13754
- iblaiApi.OpenAPI.BASE = getServiceUrl(service);
13755
- iblaiApi.OpenAPI.HEADERS = await getHeaders(service);
13756
- iblaiApi.OpenAPI.CREDENTIALS = service === SERVICES.LEGACY_LMS ? 'include' : 'omit';
13757
- // API request initiated
13758
- const data = await serviceFn(args);
13759
- // API response received
13760
- return { data };
13761
- }
13762
- catch (err) {
13763
- console.error('[data-layer] API error:', JSON.stringify(err, Object.getOwnPropertyNames(err)));
13764
- if (Object.prototype.hasOwnProperty.call(Config.httpErrorHandlers, err === null || err === void 0 ? void 0 : err.status)) {
13765
- Config.httpErrorHandlers[err === null || err === void 0 ? void 0 : err.status]({ ...((err === null || err === void 0 ? void 0 : err.data) || {}) });
13764
+ let lastError;
13765
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
13766
+ try {
13767
+ iblaiApi.OpenAPI.BASE = getServiceUrl(service);
13768
+ iblaiApi.OpenAPI.HEADERS = await getHeaders(service);
13769
+ iblaiApi.OpenAPI.CREDENTIALS = service === SERVICES.LEGACY_LMS ? 'include' : 'omit';
13770
+ const data = await serviceFn(args);
13771
+ return { data };
13766
13772
  }
13767
- return {
13768
- error: {
13769
- status: (err === null || err === void 0 ? void 0 : err.status) || 500,
13770
- data: (err === null || err === void 0 ? void 0 : err.body) || (err === null || err === void 0 ? void 0 : err.data) || (err === null || err === void 0 ? void 0 : err.message) || 'Unknown error',
13771
- },
13772
- };
13773
+ catch (err) {
13774
+ lastError = err;
13775
+ const status = err === null || err === void 0 ? void 0 : err.status;
13776
+ // Don't retry auth errors
13777
+ if (QUERYFN_NON_RETRYABLE_STATUSES.includes(status)) {
13778
+ break;
13779
+ }
13780
+ // If we have retries left, wait with exponential backoff
13781
+ if (attempt < maxRetries) {
13782
+ const delay = QUERYFN_BASE_DELAY_MS * Math.pow(2, attempt);
13783
+ console.warn(`[data-layer] Retry ${attempt + 1}/${maxRetries}:`, `service=${service}, fn=${serviceFn.name || 'anonymous'}`);
13784
+ await new Promise((resolve) => setTimeout(resolve, delay));
13785
+ continue;
13786
+ }
13787
+ }
13788
+ }
13789
+ // All retries exhausted or non-retryable error
13790
+ console.error('[data-layer] API error:', `service=${service}, fn=${serviceFn.name || 'anonymous'}`, JSON.stringify(lastError, Object.getOwnPropertyNames(lastError)));
13791
+ if (Object.prototype.hasOwnProperty.call(Config.httpErrorHandlers, lastError === null || lastError === void 0 ? void 0 : lastError.status)) {
13792
+ Config.httpErrorHandlers[lastError === null || lastError === void 0 ? void 0 : lastError.status]({
13793
+ ...((lastError === null || lastError === void 0 ? void 0 : lastError.data) || {}),
13794
+ });
13773
13795
  }
13796
+ return {
13797
+ error: {
13798
+ status: (lastError === null || lastError === void 0 ? void 0 : lastError.status) || 500,
13799
+ data: (lastError === null || lastError === void 0 ? void 0 : lastError.body) || (lastError === null || lastError === void 0 ? void 0 : lastError.data) || (lastError === null || lastError === void 0 ? void 0 : lastError.message) || 'Unknown error',
13800
+ },
13801
+ };
13774
13802
  },
13775
13803
  };
13776
13804
  };
13777
13805
  /**
13778
13806
  * Shortcut for building an endpoint using the DM service.
13779
13807
  */
13780
- const buildEndpointFromDmService = (serviceFn) => buildEndpointFromService(SERVICES.DM, serviceFn);
13808
+ const buildEndpointFromDmService = (serviceFn, options) => buildEndpointFromService(SERVICES.DM, serviceFn);
13781
13809
  /**
13782
13810
  * Shortcut for building an endpoint using the AXD service.
13783
13811
  */
13784
- const buildEndpointFromAxdService = (serviceFn) => buildEndpointFromService(SERVICES.AXD, serviceFn);
13812
+ const buildEndpointFromAxdService = (serviceFn, options) => buildEndpointFromService(SERVICES.AXD, serviceFn);
13785
13813
  const isErrorObject = (data) => {
13786
13814
  return (typeof data === 'object' &&
13787
13815
  data !== null &&
@@ -13913,40 +13941,57 @@ const iblFetchBaseQuery = async (args, api, extraOptions) => {
13913
13941
  }
13914
13942
  };
13915
13943
  /**
13916
- * Build a generic RTK Query endpoint from a service function.
13944
+ * Build a generic RTK Query endpoint from a service function (legacy variant).
13945
+ * Includes built-in retry with exponential backoff.
13917
13946
  */
13918
- const buildEndpointFromServiceLegacy = (service, serviceFn) => {
13947
+ const buildEndpointFromServiceLegacy = (service, serviceFn, options) => {
13948
+ var _a;
13949
+ const maxRetries = (_a = void 0 ) !== null && _a !== void 0 ? _a : QUERYFN_MAX_RETRIES;
13919
13950
  return {
13920
13951
  async queryFn(args) {
13921
- try {
13922
- iblaiApi.OpenAPI.BASE = getServiceUrl(service);
13923
- iblaiApi.OpenAPI.HEADERS = await getHeaders(service);
13924
- iblaiApi.OpenAPI.CREDENTIALS = service === SERVICES.LEGACY_LMS ? 'include' : 'omit';
13925
- const data = await serviceFn(...args);
13926
- return { data };
13927
- }
13928
- catch (err) {
13929
- if (Object.prototype.hasOwnProperty.call(Config.httpErrorHandlers, err === null || err === void 0 ? void 0 : err.status)) {
13930
- Config.httpErrorHandlers[err === null || err === void 0 ? void 0 : err.status]({
13931
- status: err === null || err === void 0 ? void 0 : err.status,
13932
- body: err === null || err === void 0 ? void 0 : err.body,
13933
- message: err === null || err === void 0 ? void 0 : err.message,
13934
- });
13952
+ let lastError;
13953
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
13954
+ try {
13955
+ iblaiApi.OpenAPI.BASE = getServiceUrl(service);
13956
+ iblaiApi.OpenAPI.HEADERS = await getHeaders(service);
13957
+ iblaiApi.OpenAPI.CREDENTIALS = service === SERVICES.LEGACY_LMS ? 'include' : 'omit';
13958
+ const data = await serviceFn(...args);
13959
+ return { data };
13960
+ }
13961
+ catch (err) {
13962
+ lastError = err;
13963
+ const status = err === null || err === void 0 ? void 0 : err.status;
13964
+ if (QUERYFN_NON_RETRYABLE_STATUSES.includes(status)) {
13965
+ break;
13966
+ }
13967
+ if (attempt < maxRetries) {
13968
+ const delay = QUERYFN_BASE_DELAY_MS * Math.pow(2, attempt);
13969
+ console.warn(`[data-layer] Retry ${attempt + 1}/${maxRetries}:`, `service=${service}, fn=${serviceFn.name || 'anonymous'}`);
13970
+ await new Promise((resolve) => setTimeout(resolve, delay));
13971
+ continue;
13972
+ }
13935
13973
  }
13936
- return {
13937
- error: {
13938
- status: (err === null || err === void 0 ? void 0 : err.status) || 500,
13939
- data: (err === null || err === void 0 ? void 0 : err.body) || (err === null || err === void 0 ? void 0 : err.message) || 'Unknown error',
13940
- },
13941
- };
13942
13974
  }
13975
+ if (Object.prototype.hasOwnProperty.call(Config.httpErrorHandlers, lastError === null || lastError === void 0 ? void 0 : lastError.status)) {
13976
+ Config.httpErrorHandlers[lastError === null || lastError === void 0 ? void 0 : lastError.status]({
13977
+ status: lastError === null || lastError === void 0 ? void 0 : lastError.status,
13978
+ body: lastError === null || lastError === void 0 ? void 0 : lastError.body,
13979
+ message: lastError === null || lastError === void 0 ? void 0 : lastError.message,
13980
+ });
13981
+ }
13982
+ return {
13983
+ error: {
13984
+ status: (lastError === null || lastError === void 0 ? void 0 : lastError.status) || 500,
13985
+ data: (lastError === null || lastError === void 0 ? void 0 : lastError.body) || (lastError === null || lastError === void 0 ? void 0 : lastError.message) || 'Unknown error',
13986
+ },
13987
+ };
13943
13988
  },
13944
13989
  };
13945
13990
  };
13946
13991
  /**
13947
13992
  * Shortcut for building an endpoint using the DM service.
13948
13993
  */
13949
- const buildEndpointFromDmServiceLegacy = (serviceFn) => buildEndpointFromServiceLegacy(SERVICES.DM, serviceFn);
13994
+ const buildEndpointFromDmServiceLegacy = (serviceFn, options) => buildEndpointFromServiceLegacy(SERVICES.DM, serviceFn);
13950
13995
 
13951
13996
  createApi({
13952
13997
  reducerPath: 'apiKeysApiSlice',