@iblai/web-utils 1.6.2 → 1.6.4

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.
@@ -17,20 +17,28 @@ export declare const getHeaders: (service: SERVICES) => Promise<{
17
17
  } | undefined>;
18
18
  /**
19
19
  * Build a generic RTK Query endpoint from a service function.
20
+ * Includes built-in retry with exponential backoff (since RTK Query
21
+ * skips baseQuery retry for queryFn endpoints).
20
22
  */
21
- export declare const buildEndpointFromService: <Args extends Record<string, unknown>, Result>(service: SERVICES, serviceFn: (args: Args) => Promise<Result>) => {
23
+ export declare const buildEndpointFromService: <Args extends Record<string, unknown>, Result>(service: SERVICES, serviceFn: (args: Args) => Promise<Result>, options?: {
24
+ maxRetries?: number;
25
+ }) => {
22
26
  queryFn: BaseQueryFn<Args, Result, FetchBaseQueryError | CustomError>;
23
27
  };
24
28
  /**
25
29
  * Shortcut for building an endpoint using the DM service.
26
30
  */
27
- export declare const buildEndpointFromDmService: <Args extends Record<string, unknown>, Result>(serviceFn: (args: Args) => Promise<Result>) => {
31
+ export declare const buildEndpointFromDmService: <Args extends Record<string, unknown>, Result>(serviceFn: (args: Args) => Promise<Result>, options?: {
32
+ maxRetries?: number;
33
+ }) => {
28
34
  queryFn: BaseQueryFn<Args, Result, FetchBaseQueryError | CustomError>;
29
35
  };
30
36
  /**
31
37
  * Shortcut for building an endpoint using the AXD service.
32
38
  */
33
- export declare const buildEndpointFromAxdService: <Args extends Record<string, unknown>, Result>(serviceFn: (args: Args) => Promise<Result>) => {
39
+ export declare const buildEndpointFromAxdService: <Args extends Record<string, unknown>, Result>(serviceFn: (args: Args) => Promise<Result>, options?: {
40
+ maxRetries?: number;
41
+ }) => {
34
42
  queryFn: BaseQueryFn<Args, Result, FetchBaseQueryError | CustomError>;
35
43
  };
36
44
  export interface CustomQueryArgs extends Omit<FetchArgs, 'url'> {
@@ -50,20 +58,27 @@ export type ExtendedFetchBaseQueryError = FetchBaseQueryError & {
50
58
  };
51
59
  export declare const iblFetchBaseQuery: BaseQueryFn<CustomQueryArgs, unknown, ExtendedFetchBaseQueryError, Record<string, unknown>, FetchBaseQueryMeta>;
52
60
  /**
53
- * Build a generic RTK Query endpoint from a service function.
61
+ * Build a generic RTK Query endpoint from a service function (legacy variant).
62
+ * Includes built-in retry with exponential backoff.
54
63
  */
55
- export declare const buildEndpointFromServiceLegacy: <Args extends any[], Result>(service: SERVICES, serviceFn: (...args: Args) => Promise<Result>) => {
64
+ export declare const buildEndpointFromServiceLegacy: <Args extends any[], Result>(service: SERVICES, serviceFn: (...args: Args) => Promise<Result>, options?: {
65
+ maxRetries?: number;
66
+ }) => {
56
67
  queryFn: BaseQueryFn<Args, Result, FetchBaseQueryError | CustomError>;
57
68
  };
58
69
  /**
59
70
  * Shortcut for building an endpoint using the DM service.
60
71
  */
61
- export declare const buildEndpointFromDmServiceLegacy: <Args extends any[], Result>(serviceFn: (...args: Args) => Promise<Result>) => {
72
+ export declare const buildEndpointFromDmServiceLegacy: <Args extends any[], Result>(serviceFn: (...args: Args) => Promise<Result>, options?: {
73
+ maxRetries?: number;
74
+ }) => {
62
75
  queryFn: BaseQueryFn<Args, Result, FetchBaseQueryError | CustomError>;
63
76
  };
64
77
  /**
65
78
  * Shortcut for building an endpoint using the AXD service.
66
79
  */
67
- export declare const buildEndpointFromAxdServiceLegacy: <Args extends any[], Result>(serviceFn: (...args: Args) => Promise<Result>) => {
80
+ export declare const buildEndpointFromAxdServiceLegacy: <Args extends any[], Result>(serviceFn: (...args: Args) => Promise<Result>, options?: {
81
+ maxRetries?: number;
82
+ }) => {
68
83
  queryFn: BaseQueryFn<Args, Result, FetchBaseQueryError | CustomError>;
69
84
  };
package/dist/index.d.ts CHANGED
@@ -1575,7 +1575,7 @@ type Props$2 = {
1575
1575
  * 4. Handles redirects to auth SPA when needed
1576
1576
  * 5. Manages public route access state
1577
1577
  */
1578
- declare function AuthProvider({ children, fallback, middleware, onAuthSuccess, onAuthFailure, redirectToAuthSpa, hasNonExpiredAuthToken, username, pathname, storageService, token, enableStorageSync, skip, }: Props$2): string | number | bigint | boolean | react_jsx_runtime.JSX.Element | Iterable<React__default.ReactNode> | Promise<string | number | bigint | boolean | React__default.ReactPortal | React__default.ReactElement<unknown, string | React__default.JSXElementConstructor<any>> | Iterable<React__default.ReactNode> | null | undefined> | null | undefined;
1578
+ declare function AuthProvider({ children, fallback, middleware, onAuthSuccess, onAuthFailure, redirectToAuthSpa, hasNonExpiredAuthToken, username, pathname, storageService, token, enableStorageSync, skip, }: Props$2): string | number | bigint | boolean | Iterable<React__default.ReactNode> | Promise<string | number | bigint | boolean | React__default.ReactPortal | React__default.ReactElement<unknown, string | React__default.JSXElementConstructor<any>> | Iterable<React__default.ReactNode> | null | undefined> | react_jsx_runtime.JSX.Element | null | undefined;
1579
1579
 
1580
1580
  /**
1581
1581
  * Props for the MentorProvider component
@@ -1608,7 +1608,7 @@ type Props$1 = {
1608
1608
  * 3. Manages redirection based on mentor availability
1609
1609
  * 4. Integrates with tenant context for access control
1610
1610
  */
1611
- declare function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redirectToAuthSpa, redirectToMentor, onLoadMentorsPermissions, redirectToNoMentorsPage, redirectToCreateMentor, username, isAdmin, mainTenantKey, requestedMentorId, handleMentorNotFound, forceDetermineMentor, onComplete, skip, }: Props$1): string | number | bigint | boolean | react_jsx_runtime.JSX.Element | Iterable<React__default.ReactNode> | Promise<string | number | bigint | boolean | React__default.ReactPortal | React__default.ReactElement<unknown, string | React__default.JSXElementConstructor<any>> | Iterable<React__default.ReactNode> | null | undefined> | null | undefined;
1611
+ declare function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redirectToAuthSpa, redirectToMentor, onLoadMentorsPermissions, redirectToNoMentorsPage, redirectToCreateMentor, username, isAdmin, mainTenantKey, requestedMentorId, handleMentorNotFound, forceDetermineMentor, onComplete, skip, }: Props$1): string | number | bigint | boolean | Iterable<React__default.ReactNode> | Promise<string | number | bigint | boolean | React__default.ReactPortal | React__default.ReactElement<unknown, string | React__default.JSXElementConstructor<any>> | Iterable<React__default.ReactNode> | null | undefined> | react_jsx_runtime.JSX.Element | null | undefined;
1612
1612
 
1613
1613
  /**
1614
1614
  * Type definition for the tenant context
@@ -1672,7 +1672,7 @@ type Props = {
1672
1672
  * 4. Handles tenant-specific domain redirects
1673
1673
  * 5. Maintains tenant access state
1674
1674
  */
1675
- declare function TenantProvider({ children, fallback, onAuthSuccess, onAuthFailure, currentTenant, requestedTenant, saveCurrentTenant, saveUserTenants, handleTenantSwitch, saveVisitingTenant, removeVisitingTenant, saveUserTokens, saveTenant, onAutoJoinUserToTenant, redirectToAuthSpa, username, isIframed, setUseMentorProvider, skip, onLoadPlatformPermissions, skipCustomDomainCheck, onTenantMismatch, }: Props): string | number | bigint | boolean | react_jsx_runtime.JSX.Element | Iterable<React__default.ReactNode> | Promise<string | number | bigint | boolean | React__default.ReactPortal | React__default.ReactElement<unknown, string | React__default.JSXElementConstructor<any>> | Iterable<React__default.ReactNode> | null | undefined> | null | undefined;
1675
+ declare function TenantProvider({ children, fallback, onAuthSuccess, onAuthFailure, currentTenant, requestedTenant, saveCurrentTenant, saveUserTenants, handleTenantSwitch, saveVisitingTenant, removeVisitingTenant, saveUserTokens, saveTenant, onAutoJoinUserToTenant, redirectToAuthSpa, username, isIframed, setUseMentorProvider, skip, onLoadPlatformPermissions, skipCustomDomainCheck, onTenantMismatch, }: Props): string | number | bigint | boolean | Iterable<React__default.ReactNode> | Promise<string | number | bigint | boolean | React__default.ReactPortal | React__default.ReactElement<unknown, string | React__default.JSXElementConstructor<any>> | Iterable<React__default.ReactNode> | null | undefined> | react_jsx_runtime.JSX.Element | null | undefined;
1676
1676
 
1677
1677
  /**
1678
1678
  * Chat area size constants
package/dist/index.esm.js CHANGED
@@ -3073,7 +3073,10 @@ function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure,
3073
3073
  if (isProtectedRoute && storageService) {
3074
3074
  const dmTokenInLocalStorage = await storageService.getItem(LOCAL_STORAGE_KEYS.DM_TOKEN_KEY);
3075
3075
  console.log("[auth-redirect] local storage keys ", LOCAL_STORAGE_KEYS);
3076
+ console.log("[auth-redirect] local storage ", JSON.stringify(localStorage));
3077
+ console.log("[auth-redirect] dmTokenInLocalStorage ", dmTokenInLocalStorage);
3076
3078
  const dmTokenExpired = await isDmTokenExpired(storageService);
3079
+ console.log("[auth-redirect] dmTokenExpired ", dmTokenExpired);
3077
3080
  if (!dmTokenInLocalStorage || dmTokenExpired) {
3078
3081
  if (!!dmTokenInLocalStorage) {
3079
3082
  console.log("[auth-redirect] DM token doesn't exists");
@@ -13724,44 +13727,71 @@ const getHeaders = async (service) => {
13724
13727
  }
13725
13728
  return token ? { Authorization: `${prefix} ${token}` } : undefined;
13726
13729
  };
13730
+ /** Status codes that should not be retried for queryFn endpoints. */
13731
+ const QUERYFN_NON_RETRYABLE_STATUSES = [401, 403, 500];
13732
+ /** Default max retries for queryFn endpoints. */
13733
+ const QUERYFN_MAX_RETRIES = 5;
13734
+ /** Base delay in ms for exponential backoff. */
13735
+ const QUERYFN_BASE_DELAY_MS = 1000;
13727
13736
  /**
13728
13737
  * Build a generic RTK Query endpoint from a service function.
13738
+ * Includes built-in retry with exponential backoff (since RTK Query
13739
+ * skips baseQuery retry for queryFn endpoints).
13729
13740
  */
13730
- const buildEndpointFromService = (service, serviceFn) => {
13741
+ const buildEndpointFromService = (service, serviceFn, options) => {
13742
+ var _a;
13743
+ const maxRetries = (_a = void 0 ) !== null && _a !== void 0 ? _a : QUERYFN_MAX_RETRIES;
13731
13744
  return {
13732
13745
  async queryFn(args) {
13733
- try {
13734
- OpenAPI.BASE = getServiceUrl(service);
13735
- OpenAPI.HEADERS = await getHeaders(service);
13736
- OpenAPI.CREDENTIALS = service === SERVICES.LEGACY_LMS ? 'include' : 'omit';
13737
- // API request initiated
13738
- const data = await serviceFn(args);
13739
- // API response received
13740
- return { data };
13741
- }
13742
- catch (err) {
13743
- console.error('[data-layer] API error:', JSON.stringify(err, Object.getOwnPropertyNames(err)));
13744
- if (Object.prototype.hasOwnProperty.call(Config.httpErrorHandlers, err === null || err === void 0 ? void 0 : err.status)) {
13745
- Config.httpErrorHandlers[err === null || err === void 0 ? void 0 : err.status]({ ...((err === null || err === void 0 ? void 0 : err.data) || {}) });
13746
+ let lastError;
13747
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
13748
+ try {
13749
+ OpenAPI.BASE = getServiceUrl(service);
13750
+ OpenAPI.HEADERS = await getHeaders(service);
13751
+ OpenAPI.CREDENTIALS = service === SERVICES.LEGACY_LMS ? 'include' : 'omit';
13752
+ const data = await serviceFn(args);
13753
+ return { data };
13746
13754
  }
13747
- return {
13748
- error: {
13749
- status: (err === null || err === void 0 ? void 0 : err.status) || 500,
13750
- 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',
13751
- },
13752
- };
13755
+ catch (err) {
13756
+ lastError = err;
13757
+ const status = err === null || err === void 0 ? void 0 : err.status;
13758
+ // Don't retry auth errors
13759
+ if (QUERYFN_NON_RETRYABLE_STATUSES.includes(status)) {
13760
+ break;
13761
+ }
13762
+ // If we have retries left, wait with exponential backoff
13763
+ if (attempt < maxRetries) {
13764
+ const delay = QUERYFN_BASE_DELAY_MS * Math.pow(2, attempt);
13765
+ console.warn(`[data-layer] Retry ${attempt + 1}/${maxRetries}:`, `service=${service}, fn=${serviceFn.name || 'anonymous'}`);
13766
+ await new Promise((resolve) => setTimeout(resolve, delay));
13767
+ continue;
13768
+ }
13769
+ }
13770
+ }
13771
+ // All retries exhausted or non-retryable error
13772
+ console.error('[data-layer] API error:', `service=${service}, fn=${serviceFn.name || 'anonymous'}`, JSON.stringify(lastError, Object.getOwnPropertyNames(lastError)));
13773
+ if (Object.prototype.hasOwnProperty.call(Config.httpErrorHandlers, lastError === null || lastError === void 0 ? void 0 : lastError.status)) {
13774
+ Config.httpErrorHandlers[lastError === null || lastError === void 0 ? void 0 : lastError.status]({
13775
+ ...((lastError === null || lastError === void 0 ? void 0 : lastError.data) || {}),
13776
+ });
13753
13777
  }
13778
+ return {
13779
+ error: {
13780
+ status: (lastError === null || lastError === void 0 ? void 0 : lastError.status) || 500,
13781
+ 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',
13782
+ },
13783
+ };
13754
13784
  },
13755
13785
  };
13756
13786
  };
13757
13787
  /**
13758
13788
  * Shortcut for building an endpoint using the DM service.
13759
13789
  */
13760
- const buildEndpointFromDmService = (serviceFn) => buildEndpointFromService(SERVICES.DM, serviceFn);
13790
+ const buildEndpointFromDmService = (serviceFn, options) => buildEndpointFromService(SERVICES.DM, serviceFn);
13761
13791
  /**
13762
13792
  * Shortcut for building an endpoint using the AXD service.
13763
13793
  */
13764
- const buildEndpointFromAxdService = (serviceFn) => buildEndpointFromService(SERVICES.AXD, serviceFn);
13794
+ const buildEndpointFromAxdService = (serviceFn, options) => buildEndpointFromService(SERVICES.AXD, serviceFn);
13765
13795
  const isErrorObject = (data) => {
13766
13796
  return (typeof data === 'object' &&
13767
13797
  data !== null &&
@@ -13893,40 +13923,57 @@ const iblFetchBaseQuery = async (args, api, extraOptions) => {
13893
13923
  }
13894
13924
  };
13895
13925
  /**
13896
- * Build a generic RTK Query endpoint from a service function.
13926
+ * Build a generic RTK Query endpoint from a service function (legacy variant).
13927
+ * Includes built-in retry with exponential backoff.
13897
13928
  */
13898
- const buildEndpointFromServiceLegacy = (service, serviceFn) => {
13929
+ const buildEndpointFromServiceLegacy = (service, serviceFn, options) => {
13930
+ var _a;
13931
+ const maxRetries = (_a = void 0 ) !== null && _a !== void 0 ? _a : QUERYFN_MAX_RETRIES;
13899
13932
  return {
13900
13933
  async queryFn(args) {
13901
- try {
13902
- OpenAPI.BASE = getServiceUrl(service);
13903
- OpenAPI.HEADERS = await getHeaders(service);
13904
- OpenAPI.CREDENTIALS = service === SERVICES.LEGACY_LMS ? 'include' : 'omit';
13905
- const data = await serviceFn(...args);
13906
- return { data };
13907
- }
13908
- catch (err) {
13909
- if (Object.prototype.hasOwnProperty.call(Config.httpErrorHandlers, err === null || err === void 0 ? void 0 : err.status)) {
13910
- Config.httpErrorHandlers[err === null || err === void 0 ? void 0 : err.status]({
13911
- status: err === null || err === void 0 ? void 0 : err.status,
13912
- body: err === null || err === void 0 ? void 0 : err.body,
13913
- message: err === null || err === void 0 ? void 0 : err.message,
13914
- });
13934
+ let lastError;
13935
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
13936
+ try {
13937
+ OpenAPI.BASE = getServiceUrl(service);
13938
+ OpenAPI.HEADERS = await getHeaders(service);
13939
+ OpenAPI.CREDENTIALS = service === SERVICES.LEGACY_LMS ? 'include' : 'omit';
13940
+ const data = await serviceFn(...args);
13941
+ return { data };
13942
+ }
13943
+ catch (err) {
13944
+ lastError = err;
13945
+ const status = err === null || err === void 0 ? void 0 : err.status;
13946
+ if (QUERYFN_NON_RETRYABLE_STATUSES.includes(status)) {
13947
+ break;
13948
+ }
13949
+ if (attempt < maxRetries) {
13950
+ const delay = QUERYFN_BASE_DELAY_MS * Math.pow(2, attempt);
13951
+ console.warn(`[data-layer] Retry ${attempt + 1}/${maxRetries}:`, `service=${service}, fn=${serviceFn.name || 'anonymous'}`);
13952
+ await new Promise((resolve) => setTimeout(resolve, delay));
13953
+ continue;
13954
+ }
13915
13955
  }
13916
- return {
13917
- error: {
13918
- status: (err === null || err === void 0 ? void 0 : err.status) || 500,
13919
- data: (err === null || err === void 0 ? void 0 : err.body) || (err === null || err === void 0 ? void 0 : err.message) || 'Unknown error',
13920
- },
13921
- };
13922
13956
  }
13957
+ if (Object.prototype.hasOwnProperty.call(Config.httpErrorHandlers, lastError === null || lastError === void 0 ? void 0 : lastError.status)) {
13958
+ Config.httpErrorHandlers[lastError === null || lastError === void 0 ? void 0 : lastError.status]({
13959
+ status: lastError === null || lastError === void 0 ? void 0 : lastError.status,
13960
+ body: lastError === null || lastError === void 0 ? void 0 : lastError.body,
13961
+ message: lastError === null || lastError === void 0 ? void 0 : lastError.message,
13962
+ });
13963
+ }
13964
+ return {
13965
+ error: {
13966
+ status: (lastError === null || lastError === void 0 ? void 0 : lastError.status) || 500,
13967
+ data: (lastError === null || lastError === void 0 ? void 0 : lastError.body) || (lastError === null || lastError === void 0 ? void 0 : lastError.message) || 'Unknown error',
13968
+ },
13969
+ };
13923
13970
  },
13924
13971
  };
13925
13972
  };
13926
13973
  /**
13927
13974
  * Shortcut for building an endpoint using the DM service.
13928
13975
  */
13929
- const buildEndpointFromDmServiceLegacy = (serviceFn) => buildEndpointFromServiceLegacy(SERVICES.DM, serviceFn);
13976
+ const buildEndpointFromDmServiceLegacy = (serviceFn, options) => buildEndpointFromServiceLegacy(SERVICES.DM, serviceFn);
13930
13977
 
13931
13978
  createApi({
13932
13979
  reducerPath: 'apiKeysApiSlice',