@techstuff-dev/foundation-api-utils 2.7.0 → 2.8.0

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/cjs/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var slice = require('./chunks/slice-BZ9cHcE8.js');
3
+ var slice = require('./chunks/slice-Bu9L_cVR.js');
4
4
  var slice$1 = require('./chunks/slice-CkWobkWw.js');
5
5
  var useAuth = require('./chunks/useAuth-BVyDLl6H.js');
6
6
  var jwtDecode = require('jwt-decode');
@@ -2,8 +2,8 @@
2
2
 
3
3
  var toolkit = require('@reduxjs/toolkit');
4
4
  var storage = require('@react-native-async-storage/async-storage');
5
- var slice = require('../chunks/slice-BZ9cHcE8.js');
6
- var shared = require('../chunks/shared-BB1LJXHU.js');
5
+ var slice = require('../chunks/slice-Bu9L_cVR.js');
6
+ var shared = require('../chunks/shared-l1zCzYJr.js');
7
7
  require('../chunks/slice-CkWobkWw.js');
8
8
  require('react-redux');
9
9
  require('react');
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var toolkit = require('@reduxjs/toolkit');
4
- var slice = require('../chunks/slice-BZ9cHcE8.js');
5
- var shared = require('../chunks/shared-BB1LJXHU.js');
4
+ var slice = require('../chunks/slice-Bu9L_cVR.js');
5
+ var shared = require('../chunks/shared-l1zCzYJr.js');
6
6
  require('../chunks/slice-CkWobkWw.js');
7
7
  require('react-redux');
8
8
  require('react');
@@ -1,5 +1,5 @@
1
1
  import { combineSlices } from '@reduxjs/toolkit';
2
- import { P as cartSlice, a as authApi, c as contentApi, p as paymentApi, b as productsApi, o as ordersApi } from './slice-cLf9vXqc.js';
2
+ import { P as cartSlice, a as authApi, c as contentApi, p as paymentApi, b as productsApi, o as ordersApi } from './slice-Z8Lc9U1-.js';
3
3
  import { a as authSlice } from './slice-ChJ8ZvmP.js';
4
4
 
5
5
  // This file exists just so TypeScript has a module at ./store for IDEs/build.
@@ -9,4 +9,4 @@ import { a as authSlice } from './slice-ChJ8ZvmP.js';
9
9
  const rootReducer = combineSlices(cartSlice, authSlice, authApi, contentApi, paymentApi, productsApi, ordersApi);
10
10
 
11
11
  export { rootReducer as r };
12
- //# sourceMappingURL=shared-DOQegy7B.js.map
12
+ //# sourceMappingURL=shared-ChUGjIwE.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shared-DOQegy7B.js","sources":["../../../lib/store/shared.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAAA;AACA;AAUA;AAEA;MACa,WAAW,GAAG,aAAa,CACtC,SAAS,EACT,SAAS,EACT,OAAO,EACP,UAAU,EACV,UAAU,EACV,WAAW,EACX,SAAS;;;;"}
1
+ {"version":3,"file":"shared-ChUGjIwE.js","sources":["../../../lib/store/shared.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAAA;AACA;AAUA;AAEA;MACa,WAAW,GAAG,aAAa,CACtC,SAAS,EACT,SAAS,EACT,OAAO,EACP,UAAU,EACV,UAAU,EACV,WAAW,EACX,SAAS;;;;"}
@@ -5194,7 +5194,19 @@ const APP_ES_SCHEDULE_INDEX$1 = getEnvVar$1('NEXT_PUBLIC_APP_ES_SCHEDULE_INDEX')
5194
5194
  const APP_ES_CHALLENGES_INDEX$1 = getEnvVar$1('NEXT_PUBLIC_APP_ES_CHALLENGES_INDEX');
5195
5195
  const APP_ES_CHALLENGE_DAYS_INDEX$1 = getEnvVar$1('NEXT_PUBLIC_APP_ES_CHALLENGE_DAYS_INDEX');
5196
5196
  // Platform identifier
5197
- const PLATFORM$1 = 'web';
5197
+ const PLATFORM$2 = 'web';
5198
+ /**
5199
+ * Return the Cognito app client ID the web app is configured to use.
5200
+ * Prefers the passwordless client when set (passwordless sessions present a
5201
+ * refresh token minted by that client); falls back to the regular client.
5202
+ * Used by the shared refresh-token flow so Cognito can match the refresh
5203
+ * token's original app client.
5204
+ */
5205
+ function getCognitoAppClientId$2() {
5206
+ return (getEnvVar$1('NEXT_PUBLIC_AWS_COGNITO_PASSWORDLESS_CLIENT_ID') ||
5207
+ getEnvVar$1('NEXT_PUBLIC_AWS_COGNITO_CLIENT_ID') ||
5208
+ undefined);
5209
+ }
5198
5210
 
5199
5211
  var webConfig = /*#__PURE__*/Object.freeze({
5200
5212
  __proto__: null,
@@ -5217,7 +5229,8 @@ var webConfig = /*#__PURE__*/Object.freeze({
5217
5229
  APP_ES_SETTINGS_INDEX: APP_ES_SETTINGS_INDEX$1,
5218
5230
  APP_ES_VIDEOS_INDEX: APP_ES_VIDEOS_INDEX$1,
5219
5231
  APP_ES_WORKOUTS_INDEX: APP_ES_WORKOUTS_INDEX$1,
5220
- PLATFORM: PLATFORM$1
5232
+ PLATFORM: PLATFORM$2,
5233
+ getCognitoAppClientId: getCognitoAppClientId$2
5221
5234
  });
5222
5235
 
5223
5236
  /**
@@ -5261,7 +5274,16 @@ const APP_ES_SCHEDULE_INDEX = getEnvVar('APP_ES_SCHEDULE_INDEX');
5261
5274
  const APP_ES_CHALLENGES_INDEX = getEnvVar('APP_ES_CHALLENGES_INDEX');
5262
5275
  const APP_ES_CHALLENGE_DAYS_INDEX = getEnvVar('APP_ES_CHALLENGE_DAYS_INDEX');
5263
5276
  // Platform identifier
5264
- const PLATFORM = 'native';
5277
+ const PLATFORM$1 = 'native';
5278
+ /**
5279
+ * Return the Cognito app client ID the app is configured to use.
5280
+ * On native the env var is `AWS_COGNITO_CLIENT_ID` (react-native-config).
5281
+ * Used by the shared refresh-token flow so Cognito can match the refresh
5282
+ * token's original app client.
5283
+ */
5284
+ function getCognitoAppClientId$1() {
5285
+ return getEnvVar('AWS_COGNITO_CLIENT_ID') || undefined;
5286
+ }
5265
5287
 
5266
5288
  var nativeConfig = /*#__PURE__*/Object.freeze({
5267
5289
  __proto__: null,
@@ -5284,7 +5306,8 @@ var nativeConfig = /*#__PURE__*/Object.freeze({
5284
5306
  APP_ES_SETTINGS_INDEX: APP_ES_SETTINGS_INDEX,
5285
5307
  APP_ES_VIDEOS_INDEX: APP_ES_VIDEOS_INDEX,
5286
5308
  APP_ES_WORKOUTS_INDEX: APP_ES_WORKOUTS_INDEX,
5287
- PLATFORM: PLATFORM
5309
+ PLATFORM: PLATFORM$1,
5310
+ getCognitoAppClientId: getCognitoAppClientId$1
5288
5311
  });
5289
5312
 
5290
5313
  /**
@@ -5326,7 +5349,16 @@ apiConfig.APP_ES_WORKOUTS_INDEX;
5326
5349
  apiConfig.APP_ES_SCHEDULE_INDEX;
5327
5350
  apiConfig.APP_ES_CHALLENGES_INDEX;
5328
5351
  apiConfig.APP_ES_CHALLENGE_DAYS_INDEX;
5329
- apiConfig.PLATFORM;
5352
+ const PLATFORM = apiConfig.PLATFORM;
5353
+ /**
5354
+ * Platform-specific accessor for the currently-configured Cognito app client ID.
5355
+ * Delegates to native or web config so the refresh-token flow can forward the
5356
+ * clientId to the backend (Cognito refresh tokens are bound to their minting
5357
+ * app client).
5358
+ */
5359
+ function getCognitoAppClientId() {
5360
+ return apiConfig.getCognitoAppClientId?.();
5361
+ }
5330
5362
 
5331
5363
  /**
5332
5364
  * Mutex to prevent multiple concurrent refresh attempts.
@@ -5382,11 +5414,21 @@ async function attemptTokenRefresh(api) {
5382
5414
  ? `${process.env.NEXT_PUBLIC_API_PREFIX}/auth/refresh-token`
5383
5415
  : `${API_AUTH_PREFIX || ''}/user/refreshtoken`;
5384
5416
  try {
5417
+ // Cognito refresh tokens are bound to the app client that minted them.
5418
+ // We read the client ID from the platform-specific env wrapper and pass it
5419
+ // to the backend so Cognito InitiateAuth is invoked with the matching
5420
+ // ClientId. Without this, pools with multiple app clients (e.g. separate
5421
+ // "Mobile App Client" and "ms-auth server" clients) fail refresh with
5422
+ // "Refresh Token has different Client".
5423
+ const clientId = getCognitoAppClientId();
5385
5424
  const response = await fetch(refreshUrl, {
5386
5425
  method: 'POST',
5387
5426
  headers: { 'Content-Type': 'application/json' },
5388
5427
  credentials: 'include',
5389
- body: JSON.stringify({ refreshtoken: refreshToken }),
5428
+ body: JSON.stringify({
5429
+ refreshtoken: refreshToken,
5430
+ ...(clientId ? { clientId } : {}),
5431
+ }),
5390
5432
  });
5391
5433
  if (!response.ok) {
5392
5434
  const errorBody = await response.text().catch(() => 'unable to read body');
@@ -5505,6 +5547,24 @@ function getAuthHeaders(getState) {
5505
5547
  return { accessToken, idToken };
5506
5548
  }
5507
5549
 
5550
+ /**
5551
+ * Build a per-platform URL for user-scoped data endpoints.
5552
+ *
5553
+ * Native apps call the backend API Gateway directly and must use the canonical
5554
+ * path shape: `/data/user/{sub}/{endpoint}`.
5555
+ *
5556
+ * Web apps route library requests through their own Next.js `/api/user/*`
5557
+ * proxy layer, which then forwards to the same canonical backend path. That
5558
+ * proxy expects the legacy `/user/{endpoint}?sub=X` shape.
5559
+ */
5560
+ const userDataPath = (sub, endpoint, query) => {
5561
+ if (PLATFORM === 'native') {
5562
+ const suffix = query ? `?${query}` : '';
5563
+ return `/data/user/${sub}/${endpoint}${suffix}`;
5564
+ }
5565
+ const suffix = query ? `&${query}` : '';
5566
+ return `/user/${endpoint}?sub=${sub}${suffix}`;
5567
+ };
5508
5568
  // Create a dynamic baseQuery that resolves URL at request time and unwraps standard responses
5509
5569
  const createAuthBaseQuery = () => {
5510
5570
  const baseUrl = typeof process !== 'undefined' && process.env?.NEXT_PUBLIC_API_AUTH_PREFIX
@@ -5670,14 +5730,14 @@ const authApi = createApi({
5670
5730
  // Dashboard data endpoints
5671
5731
  getStreak: builder.query({
5672
5732
  query: (sub) => ({
5673
- url: `/user/streak?sub=${sub}`,
5733
+ url: userDataPath(sub, 'streak'),
5674
5734
  method: 'GET',
5675
5735
  }),
5676
5736
  providesTags: ['Streak'],
5677
5737
  }),
5678
5738
  getWeeklyProgress: builder.query({
5679
5739
  query: (sub) => ({
5680
- url: `/user/weekly-progress?sub=${sub}`,
5740
+ url: userDataPath(sub, 'weekly-progress'),
5681
5741
  method: 'GET',
5682
5742
  }),
5683
5743
  providesTags: ['WeeklyProgress'],
@@ -5692,35 +5752,35 @@ const authApi = createApi({
5692
5752
  }),
5693
5753
  getWatchProgress: builder.query({
5694
5754
  query: ({ sub, limit = 1 }) => ({
5695
- url: `/user/watch-progress?sub=${sub}&limit=${limit}`,
5755
+ url: userDataPath(sub, 'watch-progress', `limit=${limit}`),
5696
5756
  method: 'GET',
5697
5757
  }),
5698
5758
  providesTags: ['WatchProgress'],
5699
5759
  }),
5700
5760
  getRecommendations: builder.query({
5701
5761
  query: ({ sub, limit = 8 }) => ({
5702
- url: `/user/recommendations?sub=${sub}&limit=${limit}`,
5762
+ url: userDataPath(sub, 'recommendations', `limit=${limit}`),
5703
5763
  method: 'GET',
5704
5764
  }),
5705
5765
  providesTags: ['Recommendations'],
5706
5766
  }),
5707
5767
  getActivityStats: builder.query({
5708
5768
  query: ({ sub, period = 'this-month' }) => ({
5709
- url: `/user/activity-stats?sub=${sub}&period=${period}`,
5769
+ url: userDataPath(sub, 'activity-stats', `period=${period}`),
5710
5770
  method: 'GET',
5711
5771
  }),
5712
5772
  providesTags: ['ActivityStats'],
5713
5773
  }),
5714
5774
  getActiveChallenges: builder.query({
5715
5775
  query: (sub) => ({
5716
- url: `/user/active-challenges?sub=${sub}`,
5776
+ url: userDataPath(sub, 'active-challenges'),
5717
5777
  method: 'GET',
5718
5778
  }),
5719
5779
  providesTags: ['UserData'],
5720
5780
  }),
5721
5781
  getChallengeProgress: builder.query({
5722
5782
  query: ({ sub, challengeId }) => ({
5723
- url: `/user/challenge-progress/${challengeId}?sub=${sub}`,
5783
+ url: userDataPath(sub, `challenge-progress/${challengeId}`),
5724
5784
  method: 'GET',
5725
5785
  }),
5726
5786
  providesTags: ['UserData'],
@@ -5728,7 +5788,8 @@ const authApi = createApi({
5728
5788
  // Activity logging — invalidates dashboard caches
5729
5789
  logActivity: builder.mutation({
5730
5790
  query: (data) => ({
5731
- url: '/activity',
5791
+ // Native hits the backend directly at /data/activity; web proxies via /activity → /data/activity
5792
+ url: PLATFORM === 'native' ? '/data/activity' : '/activity',
5732
5793
  method: 'POST',
5733
5794
  body: data,
5734
5795
  }),
@@ -6202,4 +6263,4 @@ const selectCartItemsIds = createSelector$1([selectMediaInCart], (items) => {
6202
6263
  cartSlice.reducer;
6203
6264
 
6204
6265
  export { selectCartNetTotal as $, useLazyGetWatchProgressQuery as A, useGetRecommendationsQuery as B, useLazyGetRecommendationsQuery as C, useGetActivityStatsQuery as D, useLazyGetActivityStatsQuery as E, useLogActivityMutation as F, useGetActiveChallengesQuery as G, useGetChallengeProgressQuery as H, useGetProductsQuery as I, useLazyGetProductsQuery as J, usePurchaseProductMutation as K, useFetchOrdersQuery as L, useLazyFetchOrdersQuery as M, useGetOrdersQuery as N, useGetOrderQuery as O, cartSlice as P, setTaxRate as Q, resetTaxRate as R, setPromoCode as S, removePromoCode as T, addToCart as U, updateCart as V, removeFromCart as W, emptyCart as X, toggleCart as Y, selectMediaInCart as Z, selectCartTotal as _, authApi as a, selectCartTaxRate as a0, selectCartTaxAmount as a1, selectCartCount as a2, selectCartStatus as a3, selectPromoCode as a4, selectCartItems as a5, selectCartItemsIds as a6, isWeb as a7, isReactNative as a8, getPlatform as a9, runOnPlatform as aa, onlyUnique as ab, applyCoupon as ac, applyTax as ad, createUnwrappingBaseQuery as ae, withReauth as af, productsApi as b, contentApi as c, useResetPasswordAuthMutation as d, useRegisterMutation as e, useVerifyUserQuery as f, useLazyVerifyUserQuery as g, useGetUserInfoQuery as h, useLazyGetUserInfoQuery as i, useUpdateUserInfoMutation as j, useForgottenPasswordMutation as k, useVerifyUserAttributesQuery as l, useLazyVerifyUserAttributesQuery as m, useVerifyUserResendQuery as n, ordersApi as o, paymentApi as p, useLazyVerifyUserResendQuery as q, useUpdateUserMutation as r, useGetStreakQuery as s, toCamelCaseObject as t, useResetPasswordMutation as u, useLazyGetStreakQuery as v, useGetWeeklyProgressQuery as w, useLazyGetWeeklyProgressQuery as x, useSetWeeklyGoalMutation as y, useGetWatchProgressQuery as z };
6205
- //# sourceMappingURL=slice-cLf9vXqc.js.map
6266
+ //# sourceMappingURL=slice-Z8Lc9U1-.js.map