@faststore/core 4.5.0-dev.4 → 4.5.0-dev.6

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.
@@ -135,6 +135,22 @@ function buildHreflangLinks(
135
135
  return links
136
136
  }
137
137
 
138
+ // With client-side offer enabled, `useOffer` only refreshes price aggregates —
139
+ // it does not rebuild the per-seller array the buy button reads. Keep that array
140
+ // from SSG, but inject the fresh Pricing Fallback token into the best offer so the
141
+ // value sent to the cart respects the token's short validity window.
142
+ const withFreshPriceToken = (
143
+ serverOffers: ServerProductQueryQuery['product']['offers'],
144
+ offer: ReturnType<typeof useOffer>
145
+ ) => ({
146
+ ...offer.offers,
147
+ offers: serverOffers.offers.map((offerItem, index) =>
148
+ index === 0
149
+ ? { ...offerItem, priceToken: offer.priceToken ?? offerItem.priceToken }
150
+ : offerItem
151
+ ),
152
+ })
153
+
138
154
  function Page({
139
155
  data: server,
140
156
  sections,
@@ -198,7 +214,11 @@ function Page({
198
214
  ? (() => {
199
215
  const offer = useOffer({ skuId: product.sku })
200
216
  return {
201
- client: { product: { offers: offer.offers } },
217
+ client: {
218
+ product: {
219
+ offers: withFreshPriceToken(product.offers, offer),
220
+ },
221
+ },
202
222
  isValidating: offer.isValidating,
203
223
  }
204
224
  })()
@@ -388,6 +408,7 @@ const query = gql(`
388
408
  priceValidUntil
389
409
  priceCurrency
390
410
  itemCondition
411
+ priceToken
391
412
  seller {
392
413
  identifier
393
414
  }
@@ -147,9 +147,9 @@ const getServerSidePropsBase: GetServerSideProps<
147
147
 
148
148
  return {
149
149
  props: {
150
- page,
150
+ page: page ?? ({ sections: [], settings: {} } as PageContentType),
151
151
  globalSections: globalSectionsResult,
152
- accountName: account.data.accountProfile.name,
152
+ accountName: account.data?.accountProfile?.name ?? '',
153
153
  },
154
154
  }
155
155
  }
@@ -78,8 +78,9 @@ export const useReorder = () => {
78
78
  seller: {
79
79
  identifier: item.seller,
80
80
  },
81
- price: item.price ?? 0,
82
- listPrice: item.price ?? 0,
81
+ price: item.price,
82
+ listPrice: item.price,
83
+ priceToken: null,
83
84
  itemOffered: {
84
85
  sku: item.id ?? '',
85
86
  image: item.imageUrl
@@ -111,7 +112,7 @@ export const useReorder = () => {
111
112
  orderPayload.orderNumber = currentCart.id
112
113
  }
113
114
 
114
- const { validateCart: validated } = await request<
115
+ const result = await request<
115
116
  ValidateCartMutationMutation,
116
117
  ValidateCartMutationMutationVariables
117
118
  >(ValidateCartMutation, {
@@ -121,6 +122,8 @@ export const useReorder = () => {
121
122
  },
122
123
  })
123
124
 
125
+ const validated = result?.validateCart ?? null
126
+
124
127
  if (!validated) {
125
128
  throw new ReorderError('Failed to add items to cart')
126
129
  }
@@ -132,7 +135,7 @@ export const useReorder = () => {
132
135
  id: getItemId(item),
133
136
  })),
134
137
  messages: validated.messages,
135
- shouldSplitItem: validated.order.shouldSplitItem,
138
+ shouldSplitItem: validated.order.shouldSplitItem ?? undefined,
136
139
  }
137
140
 
138
141
  cartStore.set(updatedCart)
@@ -18,8 +18,9 @@ import { createValidationStore, useStore } from '../useStore'
18
18
 
19
19
  export interface CartItem
20
20
  extends SDKCartItem,
21
- Omit<CartItemFragment, 'isGift'> {
21
+ Omit<CartItemFragment, 'isGift' | 'priceToken'> {
22
22
  isGift?: boolean | null
23
+ priceToken?: string | null
23
24
  }
24
25
 
25
26
  export interface Cart extends SDKCart<CartItem> {
@@ -58,6 +59,7 @@ export const ValidateCartMutation = gql(`
58
59
  listPrice
59
60
  listPriceWithTaxes
60
61
  isGift
62
+ priceToken
61
63
  itemOffered {
62
64
  ...CartProductItem
63
65
  }
@@ -128,12 +130,14 @@ const validateCart = async (cart: Cart): Promise<Cart | null> => {
128
130
  seller,
129
131
  quantity,
130
132
  itemOffered,
133
+ priceToken,
131
134
  }): IStoreOffer => {
132
135
  return {
133
136
  price,
134
137
  listPrice,
135
138
  seller,
136
139
  quantity,
140
+ priceToken,
137
141
  itemOffered: {
138
142
  sku: itemOffered.sku,
139
143
  image: itemOffered.image,
@@ -5,7 +5,7 @@ import { fetcher } from './fetcher'
5
5
  import { bestOfferFirst } from './sort'
6
6
  export { getUrl as getOfferUrl } from './fetcher'
7
7
 
8
- const ERROR_DATA = { offers: {}, isValidating: false }
8
+ const ERROR_DATA = { offers: {}, priceToken: null, isValidating: false }
9
9
 
10
10
  export function useOffer(args: { skuId: string }) {
11
11
  const { data, error, isValidating } = useSWR(args.skuId, fetcher)
@@ -41,5 +41,10 @@ export function useOffer(args: { skuId: string }) {
41
41
 
42
42
  const offers = aggregateOffer(sellers)
43
43
 
44
- return { offers, isValidating }
44
+ // Fresh Pricing Fallback signed price token from the best seller. Fetched
45
+ // directly from Intelligent Search on the client, so it bypasses the SSG/CDN
46
+ // caches and respects the token's short (~30min) validity window.
47
+ const priceToken = sellers[0]?.PriceToken ?? null
48
+
49
+ return { offers, priceToken, isValidating }
45
50
  }
@@ -16,22 +16,23 @@ export async function fetchMyAccountPageContent(
16
16
  context: FetchMyAccountPageContentContext,
17
17
  pagePath: string
18
18
  ) {
19
- const pageContent = await contentService
20
- .getSingleContent<PageContentType>({
21
- contentType,
22
- previewData: context.previewData,
23
- locale: context.locale,
24
- })
25
- .catch((err) => {
26
- console.warn('[MyAccount CMS fallback]', {
19
+ const pageContent =
20
+ (await contentService
21
+ .getSingleContent<PageContentType>({
27
22
  contentType,
23
+ previewData: context.previewData,
28
24
  locale: context.locale,
29
- fallbackReason: err instanceof Error ? err.message : String(err),
30
- page: pagePath,
31
25
  })
26
+ .catch((err) => {
27
+ console.warn('[MyAccount CMS fallback]', {
28
+ contentType,
29
+ locale: context.locale,
30
+ fallbackReason: err instanceof Error ? err.message : String(err),
31
+ page: pagePath,
32
+ })
32
33
 
33
- return { sections: [], settings: {} } as PageContentType
34
- })
34
+ return { sections: [], settings: {} } as PageContentType
35
+ })) ?? ({ sections: [], settings: {} } as PageContentType)
35
36
 
36
37
  const sections = withDefaultMyAccountSections(
37
38
  contentType,