@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.
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var toolkit = require('@reduxjs/toolkit');
4
- var slice = require('./slice-BZ9cHcE8.js');
4
+ var slice = require('./slice-Bu9L_cVR.js');
5
5
  var slice$1 = require('./slice-CkWobkWw.js');
6
6
 
7
7
  // This file exists just so TypeScript has a module at ./store for IDEs/build.
@@ -11,4 +11,4 @@ var slice$1 = require('./slice-CkWobkWw.js');
11
11
  const rootReducer = toolkit.combineSlices(slice.cartSlice, slice$1.authSlice, slice.authApi, slice.contentApi, slice.paymentApi, slice.productsApi, slice.ordersApi);
12
12
 
13
13
  exports.rootReducer = rootReducer;
14
- //# sourceMappingURL=shared-BB1LJXHU.js.map
14
+ //# sourceMappingURL=shared-l1zCzYJr.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shared-BB1LJXHU.js","sources":["../../../lib/store/shared.ts"],"sourcesContent":[null],"names":["combineSlices","cartSlice","authSlice","authApi","contentApi","paymentApi","productsApi","ordersApi"],"mappings":";;;;;;AAAA;AACA;AAUA;AAEA;MACa,WAAW,GAAGA,qBAAa,CACtCC,eAAS,EACTC,iBAAS,EACTC,aAAO,EACPC,gBAAU,EACVC,gBAAU,EACVC,iBAAW,EACXC,eAAS;;;;"}
1
+ {"version":3,"file":"shared-l1zCzYJr.js","sources":["../../../lib/store/shared.ts"],"sourcesContent":[null],"names":["combineSlices","cartSlice","authSlice","authApi","contentApi","paymentApi","productsApi","ordersApi"],"mappings":";;;;;;AAAA;AACA;AAUA;AAEA;MACa,WAAW,GAAGA,qBAAa,CACtCC,eAAS,EACTC,iBAAS,EACTC,aAAO,EACPC,gBAAU,EACVC,gBAAU,EACVC,iBAAW,EACXC,eAAS;;;;"}
@@ -5196,7 +5196,19 @@ const APP_ES_SCHEDULE_INDEX$1 = getEnvVar$1('NEXT_PUBLIC_APP_ES_SCHEDULE_INDEX')
5196
5196
  const APP_ES_CHALLENGES_INDEX$1 = getEnvVar$1('NEXT_PUBLIC_APP_ES_CHALLENGES_INDEX');
5197
5197
  const APP_ES_CHALLENGE_DAYS_INDEX$1 = getEnvVar$1('NEXT_PUBLIC_APP_ES_CHALLENGE_DAYS_INDEX');
5198
5198
  // Platform identifier
5199
- const PLATFORM$1 = 'web';
5199
+ const PLATFORM$2 = 'web';
5200
+ /**
5201
+ * Return the Cognito app client ID the web app is configured to use.
5202
+ * Prefers the passwordless client when set (passwordless sessions present a
5203
+ * refresh token minted by that client); falls back to the regular client.
5204
+ * Used by the shared refresh-token flow so Cognito can match the refresh
5205
+ * token's original app client.
5206
+ */
5207
+ function getCognitoAppClientId$2() {
5208
+ return (getEnvVar$1('NEXT_PUBLIC_AWS_COGNITO_PASSWORDLESS_CLIENT_ID') ||
5209
+ getEnvVar$1('NEXT_PUBLIC_AWS_COGNITO_CLIENT_ID') ||
5210
+ undefined);
5211
+ }
5200
5212
 
5201
5213
  var webConfig = /*#__PURE__*/Object.freeze({
5202
5214
  __proto__: null,
@@ -5219,7 +5231,8 @@ var webConfig = /*#__PURE__*/Object.freeze({
5219
5231
  APP_ES_SETTINGS_INDEX: APP_ES_SETTINGS_INDEX$1,
5220
5232
  APP_ES_VIDEOS_INDEX: APP_ES_VIDEOS_INDEX$1,
5221
5233
  APP_ES_WORKOUTS_INDEX: APP_ES_WORKOUTS_INDEX$1,
5222
- PLATFORM: PLATFORM$1
5234
+ PLATFORM: PLATFORM$2,
5235
+ getCognitoAppClientId: getCognitoAppClientId$2
5223
5236
  });
5224
5237
 
5225
5238
  /**
@@ -5263,7 +5276,16 @@ const APP_ES_SCHEDULE_INDEX = getEnvVar('APP_ES_SCHEDULE_INDEX');
5263
5276
  const APP_ES_CHALLENGES_INDEX = getEnvVar('APP_ES_CHALLENGES_INDEX');
5264
5277
  const APP_ES_CHALLENGE_DAYS_INDEX = getEnvVar('APP_ES_CHALLENGE_DAYS_INDEX');
5265
5278
  // Platform identifier
5266
- const PLATFORM = 'native';
5279
+ const PLATFORM$1 = 'native';
5280
+ /**
5281
+ * Return the Cognito app client ID the app is configured to use.
5282
+ * On native the env var is `AWS_COGNITO_CLIENT_ID` (react-native-config).
5283
+ * Used by the shared refresh-token flow so Cognito can match the refresh
5284
+ * token's original app client.
5285
+ */
5286
+ function getCognitoAppClientId$1() {
5287
+ return getEnvVar('AWS_COGNITO_CLIENT_ID') || undefined;
5288
+ }
5267
5289
 
5268
5290
  var nativeConfig = /*#__PURE__*/Object.freeze({
5269
5291
  __proto__: null,
@@ -5286,7 +5308,8 @@ var nativeConfig = /*#__PURE__*/Object.freeze({
5286
5308
  APP_ES_SETTINGS_INDEX: APP_ES_SETTINGS_INDEX,
5287
5309
  APP_ES_VIDEOS_INDEX: APP_ES_VIDEOS_INDEX,
5288
5310
  APP_ES_WORKOUTS_INDEX: APP_ES_WORKOUTS_INDEX,
5289
- PLATFORM: PLATFORM
5311
+ PLATFORM: PLATFORM$1,
5312
+ getCognitoAppClientId: getCognitoAppClientId$1
5290
5313
  });
5291
5314
 
5292
5315
  /**
@@ -5328,7 +5351,16 @@ apiConfig.APP_ES_WORKOUTS_INDEX;
5328
5351
  apiConfig.APP_ES_SCHEDULE_INDEX;
5329
5352
  apiConfig.APP_ES_CHALLENGES_INDEX;
5330
5353
  apiConfig.APP_ES_CHALLENGE_DAYS_INDEX;
5331
- apiConfig.PLATFORM;
5354
+ const PLATFORM = apiConfig.PLATFORM;
5355
+ /**
5356
+ * Platform-specific accessor for the currently-configured Cognito app client ID.
5357
+ * Delegates to native or web config so the refresh-token flow can forward the
5358
+ * clientId to the backend (Cognito refresh tokens are bound to their minting
5359
+ * app client).
5360
+ */
5361
+ function getCognitoAppClientId() {
5362
+ return apiConfig.getCognitoAppClientId?.();
5363
+ }
5332
5364
 
5333
5365
  /**
5334
5366
  * Mutex to prevent multiple concurrent refresh attempts.
@@ -5384,11 +5416,21 @@ async function attemptTokenRefresh(api) {
5384
5416
  ? `${process.env.NEXT_PUBLIC_API_PREFIX}/auth/refresh-token`
5385
5417
  : `${API_AUTH_PREFIX || ''}/user/refreshtoken`;
5386
5418
  try {
5419
+ // Cognito refresh tokens are bound to the app client that minted them.
5420
+ // We read the client ID from the platform-specific env wrapper and pass it
5421
+ // to the backend so Cognito InitiateAuth is invoked with the matching
5422
+ // ClientId. Without this, pools with multiple app clients (e.g. separate
5423
+ // "Mobile App Client" and "ms-auth server" clients) fail refresh with
5424
+ // "Refresh Token has different Client".
5425
+ const clientId = getCognitoAppClientId();
5387
5426
  const response = await fetch(refreshUrl, {
5388
5427
  method: 'POST',
5389
5428
  headers: { 'Content-Type': 'application/json' },
5390
5429
  credentials: 'include',
5391
- body: JSON.stringify({ refreshtoken: refreshToken }),
5430
+ body: JSON.stringify({
5431
+ refreshtoken: refreshToken,
5432
+ ...(clientId ? { clientId } : {}),
5433
+ }),
5392
5434
  });
5393
5435
  if (!response.ok) {
5394
5436
  const errorBody = await response.text().catch(() => 'unable to read body');
@@ -5507,6 +5549,24 @@ function getAuthHeaders(getState) {
5507
5549
  return { accessToken, idToken };
5508
5550
  }
5509
5551
 
5552
+ /**
5553
+ * Build a per-platform URL for user-scoped data endpoints.
5554
+ *
5555
+ * Native apps call the backend API Gateway directly and must use the canonical
5556
+ * path shape: `/data/user/{sub}/{endpoint}`.
5557
+ *
5558
+ * Web apps route library requests through their own Next.js `/api/user/*`
5559
+ * proxy layer, which then forwards to the same canonical backend path. That
5560
+ * proxy expects the legacy `/user/{endpoint}?sub=X` shape.
5561
+ */
5562
+ const userDataPath = (sub, endpoint, query) => {
5563
+ if (PLATFORM === 'native') {
5564
+ const suffix = query ? `?${query}` : '';
5565
+ return `/data/user/${sub}/${endpoint}${suffix}`;
5566
+ }
5567
+ const suffix = query ? `&${query}` : '';
5568
+ return `/user/${endpoint}?sub=${sub}${suffix}`;
5569
+ };
5510
5570
  // Create a dynamic baseQuery that resolves URL at request time and unwraps standard responses
5511
5571
  const createAuthBaseQuery = () => {
5512
5572
  const baseUrl = typeof process !== 'undefined' && process.env?.NEXT_PUBLIC_API_AUTH_PREFIX
@@ -5672,14 +5732,14 @@ const authApi = createApi({
5672
5732
  // Dashboard data endpoints
5673
5733
  getStreak: builder.query({
5674
5734
  query: (sub) => ({
5675
- url: `/user/streak?sub=${sub}`,
5735
+ url: userDataPath(sub, 'streak'),
5676
5736
  method: 'GET',
5677
5737
  }),
5678
5738
  providesTags: ['Streak'],
5679
5739
  }),
5680
5740
  getWeeklyProgress: builder.query({
5681
5741
  query: (sub) => ({
5682
- url: `/user/weekly-progress?sub=${sub}`,
5742
+ url: userDataPath(sub, 'weekly-progress'),
5683
5743
  method: 'GET',
5684
5744
  }),
5685
5745
  providesTags: ['WeeklyProgress'],
@@ -5694,35 +5754,35 @@ const authApi = createApi({
5694
5754
  }),
5695
5755
  getWatchProgress: builder.query({
5696
5756
  query: ({ sub, limit = 1 }) => ({
5697
- url: `/user/watch-progress?sub=${sub}&limit=${limit}`,
5757
+ url: userDataPath(sub, 'watch-progress', `limit=${limit}`),
5698
5758
  method: 'GET',
5699
5759
  }),
5700
5760
  providesTags: ['WatchProgress'],
5701
5761
  }),
5702
5762
  getRecommendations: builder.query({
5703
5763
  query: ({ sub, limit = 8 }) => ({
5704
- url: `/user/recommendations?sub=${sub}&limit=${limit}`,
5764
+ url: userDataPath(sub, 'recommendations', `limit=${limit}`),
5705
5765
  method: 'GET',
5706
5766
  }),
5707
5767
  providesTags: ['Recommendations'],
5708
5768
  }),
5709
5769
  getActivityStats: builder.query({
5710
5770
  query: ({ sub, period = 'this-month' }) => ({
5711
- url: `/user/activity-stats?sub=${sub}&period=${period}`,
5771
+ url: userDataPath(sub, 'activity-stats', `period=${period}`),
5712
5772
  method: 'GET',
5713
5773
  }),
5714
5774
  providesTags: ['ActivityStats'],
5715
5775
  }),
5716
5776
  getActiveChallenges: builder.query({
5717
5777
  query: (sub) => ({
5718
- url: `/user/active-challenges?sub=${sub}`,
5778
+ url: userDataPath(sub, 'active-challenges'),
5719
5779
  method: 'GET',
5720
5780
  }),
5721
5781
  providesTags: ['UserData'],
5722
5782
  }),
5723
5783
  getChallengeProgress: builder.query({
5724
5784
  query: ({ sub, challengeId }) => ({
5725
- url: `/user/challenge-progress/${challengeId}?sub=${sub}`,
5785
+ url: userDataPath(sub, `challenge-progress/${challengeId}`),
5726
5786
  method: 'GET',
5727
5787
  }),
5728
5788
  providesTags: ['UserData'],
@@ -5730,7 +5790,8 @@ const authApi = createApi({
5730
5790
  // Activity logging — invalidates dashboard caches
5731
5791
  logActivity: builder.mutation({
5732
5792
  query: (data) => ({
5733
- url: '/activity',
5793
+ // Native hits the backend directly at /data/activity; web proxies via /activity → /data/activity
5794
+ url: PLATFORM === 'native' ? '/data/activity' : '/activity',
5734
5795
  method: 'POST',
5735
5796
  body: data,
5736
5797
  }),
@@ -6273,4 +6334,4 @@ exports.useVerifyUserAttributesQuery = useVerifyUserAttributesQuery;
6273
6334
  exports.useVerifyUserQuery = useVerifyUserQuery;
6274
6335
  exports.useVerifyUserResendQuery = useVerifyUserResendQuery;
6275
6336
  exports.withReauth = withReauth;
6276
- //# sourceMappingURL=slice-BZ9cHcE8.js.map
6337
+ //# sourceMappingURL=slice-Bu9L_cVR.js.map