@iblai/web-utils 1.2.8 → 1.2.9

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.esm.js CHANGED
@@ -2754,22 +2754,22 @@ async function getUserName(storageService) {
2754
2754
  * @param storageService - Storage service to access localStorage
2755
2755
  * @returns boolean indicating if token has expired
2756
2756
  */
2757
- async function isJwtTokenExpired(storageService) {
2757
+ async function isDmTokenExpired(storageService) {
2758
2758
  try {
2759
2759
  const dmTokenExpires = await storageService.getItem(LOCAL_STORAGE_KEYS.DM_TOKEN_EXPIRES);
2760
2760
  if (!dmTokenExpires) {
2761
- return false; // not expired if dm_token_expires not found
2761
+ return true;
2762
2762
  }
2763
2763
  const expiryTime = new Date(dmTokenExpires).getTime();
2764
2764
  const currentTime = Date.now();
2765
2765
  if (currentTime >= expiryTime) {
2766
- console.warn("[AuthProvider] JWT token has expired");
2766
+ console.warn("[AuthProvider] DM token has expired");
2767
2767
  return true;
2768
2768
  }
2769
2769
  return false;
2770
2770
  }
2771
2771
  catch (error) {
2772
- console.error("[AuthProvider] Error checking JWT token expiry:", error);
2772
+ console.error("[AuthProvider] Error checking DM token expiry:", error);
2773
2773
  return true; // Treat as expired on error
2774
2774
  }
2775
2775
  }
@@ -2988,12 +2988,12 @@ function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure,
2988
2988
  }
2989
2989
  // Check JWT token expiry and force logout for protected routes
2990
2990
  if (isProtectedRoute && storageService) {
2991
- const jwtExpired = await isJwtTokenExpired(storageService);
2992
- if (jwtExpired) {
2993
- console.log("[auth-redirect] JWT token has expired, forcing logout");
2991
+ const dmTokenExpired = await isDmTokenExpired(storageService);
2992
+ if (dmTokenExpired) {
2993
+ console.log("[auth-redirect] DM token has expired, forcing logout");
2994
2994
  // Clear all auth-related storage keys
2995
2995
  clearAuthCookies();
2996
- const reason = "JWT token expired";
2996
+ const reason = "DM token expired";
2997
2997
  onAuthFailure === null || onAuthFailure === void 0 ? void 0 : onAuthFailure(reason);
2998
2998
  safeRedirectToAuthSpa(undefined, undefined, true);
2999
2999
  return;
@@ -13591,6 +13591,7 @@ const buildEndpointFromService = (service, serviceFn) => {
13591
13591
  return { data };
13592
13592
  }
13593
13593
  catch (err) {
13594
+ console.error('[data-layer] API error:', JSON.stringify(err, Object.getOwnPropertyNames(err)));
13594
13595
  if (Object.prototype.hasOwnProperty.call(Config.httpErrorHandlers, err === null || err === void 0 ? void 0 : err.status)) {
13595
13596
  Config.httpErrorHandlers[err === null || err === void 0 ? void 0 : err.status]({ ...((err === null || err === void 0 ? void 0 : err.data) || {}) });
13596
13597
  }
@@ -13661,7 +13662,7 @@ const invokeHttpErrorHandler = (status, error) => {
13661
13662
  }
13662
13663
  };
13663
13664
  /** HTTP status codes that should not be retried (e.g., 402 Payment Required). */
13664
- const NON_RETRYABLE_STATUS_CODES = [402];
13665
+ const NON_RETRYABLE_STATUS_CODES = [402, 401];
13665
13666
  /**
13666
13667
  * Wraps a base query to skip retries for non-retryable HTTP status codes.
13667
13668
  * Uses `retry.fail()` to immediately bail out of the retry loop.
@@ -13716,7 +13717,6 @@ const iblFetchBaseQuery = async (args, api, extraOptions) => {
13716
13717
  error: e,
13717
13718
  }));
13718
13719
  // Extract status from error and invoke HTTP error handlers
13719
- console.log('[MONETIZATION e]', { e });
13720
13720
  const err = e;
13721
13721
  const errorStatus = typeof e === 'object' && e !== null && 'status' in e
13722
13722
  ? e.status
@@ -14399,7 +14399,7 @@ createApi({
14399
14399
  });
14400
14400
 
14401
14401
  const featureTags = {
14402
- PLATFORM_USERS: "PLATFORM_USERS",
14402
+ PLATFORM_USERS: 'PLATFORM_USERS',
14403
14403
  };
14404
14404
 
14405
14405
  createApi({
@@ -14711,10 +14711,10 @@ createApi({
14711
14711
  credentials: 'omit',
14712
14712
  });
14713
14713
  if (!response.ok) {
14714
- const error = new Error('Failed to fetch RBAC group details');
14715
- error.status = response.status;
14716
- error.body = await response.text();
14717
- throw error;
14714
+ throw Object.assign(new Error('Failed to fetch RBAC group details'), {
14715
+ status: response.status,
14716
+ body: await response.text(),
14717
+ });
14718
14718
  }
14719
14719
  return response.json();
14720
14720
  }),
@@ -14748,10 +14748,10 @@ createApi({
14748
14748
  credentials: 'omit',
14749
14749
  });
14750
14750
  if (!response.ok) {
14751
- const error = new Error('Failed to fetch RBAC policy details');
14752
- error.status = response.status;
14753
- error.body = await response.text();
14754
- throw error;
14751
+ throw Object.assign(new Error('Failed to fetch RBAC policy details'), {
14752
+ status: response.status,
14753
+ body: await response.text(),
14754
+ });
14755
14755
  }
14756
14756
  return response.json();
14757
14757
  }),
@@ -14789,15 +14789,33 @@ createApi({
14789
14789
  credentials: 'omit',
14790
14790
  });
14791
14791
  if (!response.ok) {
14792
- const error = new Error('Failed to fetch RBAC role details');
14793
- error.status = response.status;
14794
- error.body = await response.text();
14795
- throw error;
14792
+ throw Object.assign(new Error('Failed to fetch RBAC role details'), {
14793
+ status: response.status,
14794
+ body: await response.text(),
14795
+ });
14796
14796
  }
14797
14797
  return response.json();
14798
14798
  }),
14799
14799
  providesTags: ['RbacRoles'],
14800
14800
  }),
14801
+ getDepartmentMemberCheck: builder.query({
14802
+ ...buildEndpointFromService(SERVICES.DM, async (args) => {
14803
+ const queryParams = new URLSearchParams({ platform_key: args.platform_key });
14804
+ const url = `${OpenAPI.BASE}/api/core/departments/members/check/?${queryParams.toString()}`;
14805
+ const response = await fetch(url, {
14806
+ method: 'GET',
14807
+ headers: OpenAPI.HEADERS,
14808
+ credentials: 'omit',
14809
+ });
14810
+ if (!response.ok) {
14811
+ throw Object.assign(new Error('Failed to fetch department member check'), {
14812
+ status: response.status,
14813
+ body: await response.text(),
14814
+ });
14815
+ }
14816
+ return response.json();
14817
+ }),
14818
+ }),
14801
14819
  getRbacMentorAccessList: builder.query({
14802
14820
  ...buildEndpointFromDmService(CoreService.coreRbacMentorAccessList),
14803
14821
  }),
@@ -16072,6 +16090,7 @@ createApi({
16072
16090
  'catalog-roles',
16073
16091
  'catalog-invitations-course',
16074
16092
  'catalog-invitations-program',
16093
+ 'user-assigned-programs',
16075
16094
  ],
16076
16095
  endpoints: (builder) => ({
16077
16096
  getUserReportedSkills: builder.query({
@@ -16179,15 +16198,56 @@ createApi({
16179
16198
  credentials: 'omit',
16180
16199
  });
16181
16200
  if (!response.ok) {
16182
- const error = new Error('Failed to fetch program invitations');
16183
- error.status = response.status;
16184
- error.body = await response.text();
16185
- throw error;
16201
+ throw Object.assign(new Error('Failed to fetch program invitations'), {
16202
+ status: response.status,
16203
+ body: await response.text(),
16204
+ });
16186
16205
  }
16187
16206
  return response.json();
16188
16207
  }),
16189
16208
  providesTags: ['catalog-invitations-program'],
16190
16209
  }),
16210
+ getUserCatalogPathways: builder.query({
16211
+ ...buildEndpointFromService(SERVICES.DM, async (args) => {
16212
+ const params = new URLSearchParams({
16213
+ username: args.username,
16214
+ platform_key: args.platform_key,
16215
+ });
16216
+ const url = `${OpenAPI.BASE}/api/catalog/pathways/?${params.toString()}`;
16217
+ const response = await fetch(url, {
16218
+ method: 'GET',
16219
+ headers: OpenAPI.HEADERS,
16220
+ credentials: 'omit',
16221
+ });
16222
+ if (!response.ok) {
16223
+ throw Object.assign(new Error('Failed to fetch user catalog pathways'), {
16224
+ status: response.status,
16225
+ body: await response.text(),
16226
+ });
16227
+ }
16228
+ return response.json();
16229
+ }),
16230
+ providesTags: ['user-catalog-pathways'],
16231
+ }),
16232
+ getAssignedPrograms: builder.query({
16233
+ ...buildEndpointFromService(SERVICES.DM, async (args) => {
16234
+ const params = new URLSearchParams({ user_id: String(args.user_id) });
16235
+ const url = `${OpenAPI.BASE}/api/catalog/suggestions/program/user/?${params.toString()}`;
16236
+ const response = await fetch(url, {
16237
+ method: 'GET',
16238
+ headers: OpenAPI.HEADERS,
16239
+ credentials: 'omit',
16240
+ });
16241
+ if (!response.ok) {
16242
+ throw Object.assign(new Error('Failed to fetch assigned programs'), {
16243
+ status: response.status,
16244
+ body: await response.text(),
16245
+ });
16246
+ }
16247
+ return response.json();
16248
+ }),
16249
+ providesTags: ['user-assigned-programs'],
16250
+ }),
16191
16251
  }),
16192
16252
  });
16193
16253
 
@@ -16209,6 +16269,114 @@ createApi({
16209
16269
  }),
16210
16270
  });
16211
16271
 
16272
+ createApi({
16273
+ reducerPath: 'coursesApiSlice',
16274
+ baseQuery: iblFetchBaseQuery,
16275
+ tagTypes: ['user-enrolled-courses', 'user-assigned-courses'],
16276
+ endpoints: (builder) => ({
16277
+ getUserEnrolledCourses: builder.query({
16278
+ query: ({ username, query }) => {
16279
+ const params = new URLSearchParams();
16280
+ params.set('username', username);
16281
+ if (query) {
16282
+ for (const [k, v] of Object.entries(query)) {
16283
+ if (v !== undefined && v !== null)
16284
+ params.set(k, String(v));
16285
+ }
16286
+ }
16287
+ return {
16288
+ url: `/api/catalog/enrollment/courses/search/?${params.toString()}`,
16289
+ service: SERVICES.DM,
16290
+ method: 'GET',
16291
+ };
16292
+ },
16293
+ providesTags: ['user-enrolled-courses'],
16294
+ }),
16295
+ getUserAssignedCourses: builder.query({
16296
+ query: ({ user_id, query }) => {
16297
+ const params = new URLSearchParams();
16298
+ params.set('user_id', String(user_id));
16299
+ if (query) {
16300
+ for (const [k, v] of Object.entries(query)) {
16301
+ if (v !== undefined && v !== null)
16302
+ params.set(k, String(v));
16303
+ }
16304
+ }
16305
+ return {
16306
+ url: `/api/catalog/suggestions/course/user/?${params.toString()}`,
16307
+ service: SERVICES.DM,
16308
+ method: 'GET',
16309
+ };
16310
+ },
16311
+ providesTags: ['user-assigned-courses'],
16312
+ }),
16313
+ }),
16314
+ });
16315
+
16316
+ createApi({
16317
+ reducerPath: 'courseMetadataApiSlice',
16318
+ baseQuery: iblFetchBaseQuery,
16319
+ endpoints: (builder) => ({
16320
+ getCourseMetaData: builder.query({
16321
+ query: ({ courseKey }) => ({
16322
+ url: `/api/ibl/v1/course_metadata?course_key=${encodeURIComponent(courseKey)}`,
16323
+ service: SERVICES.LMS,
16324
+ method: 'GET',
16325
+ }),
16326
+ }),
16327
+ getCourseCompletionOutlines: builder.query({
16328
+ query: ({ courseKey }) => ({
16329
+ url: `/api/ibl/completion/course_outline/${courseKey}?course_id=${encodeURIComponent(courseKey)}`,
16330
+ service: SERVICES.LMS,
16331
+ method: 'GET',
16332
+ }),
16333
+ }),
16334
+ getCourseEligibility: builder.query({
16335
+ query: ({ courseKey }) => ({
16336
+ url: `/api/ibl/enrollment/enroll_status?course_id=${encodeURIComponent(courseKey)}`,
16337
+ service: SERVICES.LMS,
16338
+ method: 'GET',
16339
+ }),
16340
+ }),
16341
+ createCourseEnrollment: builder.mutation({
16342
+ query: (body) => ({
16343
+ url: `/api/enrollment/v1/enrollment`,
16344
+ service: SERVICES.LMS,
16345
+ method: 'POST',
16346
+ body,
16347
+ }),
16348
+ }),
16349
+ getCourseProgress: builder.query({
16350
+ query: ({ courseKey }) => ({
16351
+ url: `/api/course_home/progress/${courseKey}`,
16352
+ service: SERVICES.LMS,
16353
+ method: 'GET',
16354
+ }),
16355
+ }),
16356
+ getCourseCompletion: builder.query({
16357
+ query: ({ courseKey, userID }) => ({
16358
+ url: `/api/catalog/milestones/completions/course/manage/?course_id=${courseKey}&user_id=${userID}`,
16359
+ service: SERVICES.DM,
16360
+ method: 'GET',
16361
+ }),
16362
+ }),
16363
+ }),
16364
+ });
16365
+
16366
+ createApi({
16367
+ reducerPath: 'edxSsoApiSlice',
16368
+ baseQuery: iblFetchBaseQuery,
16369
+ endpoints: (builder) => ({
16370
+ getEdxSSOToken: builder.query({
16371
+ query: ({ username, redirectUrl }) => ({
16372
+ url: `/ibl/ai/sso/backend/edx/sso-auth-token/generate?username=${encodeURIComponent(username)}&redirect_url=${encodeURIComponent(redirectUrl)}`,
16373
+ service: SERVICES.LMS,
16374
+ method: 'GET',
16375
+ }),
16376
+ }),
16377
+ }),
16378
+ });
16379
+
16212
16380
  createApi({
16213
16381
  reducerPath: 'searchApiSlice',
16214
16382
  baseQuery: iblFakeBaseQuery,
@@ -16882,6 +17050,7 @@ const MEMORY_QUERY_KEYS = {
16882
17050
  MEMSEARCH_MENTOR_MEMORIES: () => ['MEMSEARCH_MENTOR_MEMORIES'],
16883
17051
  MEMSEARCH_MEMORY_CATEGORIES: () => ['MEMSEARCH_MEMORY_CATEGORIES'],
16884
17052
  MEMSEARCH_PLATFORM_CONFIG: () => ['MEMSEARCH_PLATFORM_CONFIG'],
17053
+ MEMSEARCH_STATUS: () => ['MEMSEARCH_STATUS'],
16885
17054
  };
16886
17055
  const MEMSEARCH_ENDPOINTS = {
16887
17056
  // User Memory Settings
@@ -16949,6 +17118,11 @@ const MEMSEARCH_ENDPOINTS = {
16949
17118
  service: SERVICES.AXD,
16950
17119
  path: (org, userId) => `/api/ai-mentor/orgs/${org}/users/${userId}/memsearch-config/`,
16951
17120
  },
17121
+ // Memsearch Status (available to students and admins)
17122
+ GET_MEMSEARCH_STATUS: {
17123
+ service: SERVICES.AXD,
17124
+ path: (org, userId) => `/api/ai-mentor/orgs/${org}/users/${userId}/memsearch-status/`,
17125
+ },
16952
17126
  };
16953
17127
 
16954
17128
  createApi({
@@ -16959,6 +17133,7 @@ createApi({
16959
17133
  ...MEMORY_QUERY_KEYS.MEMSEARCH_MENTOR_MEMORIES(),
16960
17134
  ...MEMORY_QUERY_KEYS.MEMSEARCH_MEMORY_CATEGORIES(),
16961
17135
  ...MEMORY_QUERY_KEYS.MEMSEARCH_PLATFORM_CONFIG(),
17136
+ ...MEMORY_QUERY_KEYS.MEMSEARCH_STATUS(),
16962
17137
  ],
16963
17138
  baseQuery: iblFetchBaseQuery,
16964
17139
  endpoints: (builder) => ({
@@ -17091,6 +17266,14 @@ createApi({
17091
17266
  }),
17092
17267
  invalidatesTags: MEMORY_QUERY_KEYS.MEMSEARCH_PLATFORM_CONFIG(),
17093
17268
  }),
17269
+ // Memsearch Status (student + admin accessible)
17270
+ getMemsearchStatus: builder.query({
17271
+ query: (args) => ({
17272
+ url: MEMSEARCH_ENDPOINTS.GET_MEMSEARCH_STATUS.path(args.org, args.userId),
17273
+ service: MEMSEARCH_ENDPOINTS.GET_MEMSEARCH_STATUS.service,
17274
+ }),
17275
+ providesTags: MEMORY_QUERY_KEYS.MEMSEARCH_STATUS(),
17276
+ }),
17094
17277
  }),
17095
17278
  });
17096
17279
 
@@ -18071,6 +18254,33 @@ createApi({
18071
18254
  }),
18072
18255
  });
18073
18256
 
18257
+ const AUDIT_LOGS_REDUCER_PATH = 'auditLogsApiSlice';
18258
+ const AUDIT_LOGS_QUERY_KEYS = {
18259
+ GET_AUDIT_LOGS: () => ['AUDIT_LOGS'],
18260
+ };
18261
+ const AUDIT_LOGS_ENDPOINTS = {
18262
+ GET_AUDIT_LOGS: {
18263
+ service: SERVICES.AXD,
18264
+ path: (org, userId) => `/api/ai-mentor/orgs/${org}/users/${userId}/mentors/audit-logs/`,
18265
+ },
18266
+ };
18267
+
18268
+ createApi({
18269
+ reducerPath: AUDIT_LOGS_REDUCER_PATH,
18270
+ tagTypes: [...AUDIT_LOGS_QUERY_KEYS.GET_AUDIT_LOGS()],
18271
+ baseQuery: iblFetchBaseQuery,
18272
+ endpoints: (builder) => ({
18273
+ getAuditLogs: builder.query({
18274
+ query: (args) => ({
18275
+ url: AUDIT_LOGS_ENDPOINTS.GET_AUDIT_LOGS.path(args.org, args.userId),
18276
+ service: AUDIT_LOGS_ENDPOINTS.GET_AUDIT_LOGS.service,
18277
+ params: args.params,
18278
+ }),
18279
+ providesTags: AUDIT_LOGS_QUERY_KEYS.GET_AUDIT_LOGS(),
18280
+ }),
18281
+ }),
18282
+ });
18283
+
18074
18284
  function useMentorSettings({ mentorId, tenantKey, username, isPublicRoute, }) {
18075
18285
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
18076
18286
  const isLoggedIn = username !== ANONYMOUS_USERNAME;