@replohq/sdk 1.3.2 → 1.4.1

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.
@@ -22,6 +22,19 @@ import { createOptimisticSellingPlanAllocation } from "./utils/variant-to-cart-l
22
22
  class CartContextError extends CanopyError {
23
23
  }
24
24
  let cartCreationPromise = null;
25
+ function getOrCreateSharedCart() {
26
+ cartCreationPromise ??= getOrCreateCartAction().then((cart) => {
27
+ if (!cart) {
28
+ throw new CartContextError({
29
+ message: "Your cart could not be loaded. Please try again."
30
+ });
31
+ }
32
+ return cart;
33
+ }).finally(() => {
34
+ cartCreationPromise = null;
35
+ });
36
+ return cartCreationPromise;
37
+ }
25
38
  function addLineToCart({
26
39
  cart,
27
40
  line,
@@ -72,8 +85,18 @@ function CartProvider({
72
85
  cart
73
86
  }) {
74
87
  const [cartData, setCartData] = React.useState(cart);
88
+ const optimisticCart = React.useRef(cart);
89
+ const updateCartData = React.useCallback(
90
+ (update) => {
91
+ const nextCart = typeof update === "function" ? update(optimisticCart.current) : update;
92
+ optimisticCart.current = nextCart;
93
+ setCartData(nextCart);
94
+ return nextCart;
95
+ },
96
+ []
97
+ );
75
98
  const [isCartOpen, setIsCartOpen] = React.useState(false);
76
- const hasInitialized = React.useRef(false);
99
+ const isMounted = React.useRef(true);
77
100
  const analytics = useAnalyticsOptional();
78
101
  const serverCart = React.useRef(cart);
79
102
  const needsRefresh = React.useRef(false);
@@ -83,7 +106,7 @@ function CartProvider({
83
106
  const enqueueMutation = async (save) => {
84
107
  pendingMutations.current += 1;
85
108
  const request = mutationQueue.current.then(async () => {
86
- await cartCreationPromise;
109
+ await cartCreationPromise?.catch(() => null);
87
110
  if (needsRefresh.current) {
88
111
  const restoredCart = await getCartAction();
89
112
  if (!restoredCart)
@@ -93,7 +116,11 @@ function CartProvider({
93
116
  serverCart.current = restoredCart;
94
117
  needsRefresh.current = false;
95
118
  }
96
- if (!serverCart.current) return;
119
+ if (!serverCart.current) {
120
+ throw new CartContextError({
121
+ message: "Your cart could not be loaded. Please try again."
122
+ });
123
+ }
97
124
  try {
98
125
  const savedCart = await save(serverCart.current);
99
126
  if (!savedCart)
@@ -114,7 +141,7 @@ function CartProvider({
114
141
  if (pendingMutations.current === 0) {
115
142
  reportedLineQuantities.current.clear();
116
143
  optimisticLines.current.clear();
117
- setCartData(serverCart.current);
144
+ updateCartData(serverCart.current);
118
145
  }
119
146
  });
120
147
  await request;
@@ -133,39 +160,26 @@ function CartProvider({
133
160
  return line.merchandise?.id === merchandiseId && (line.sellingPlanAllocation?.sellingPlan.id ?? null) === sellingPlanId;
134
161
  });
135
162
  };
136
- React.useEffect(() => {
137
- const initializeCart = (loadedCart) => {
138
- serverCart.current = loadedCart;
139
- if (pendingMutations.current === 0) setCartData(loadedCart);
140
- };
141
- if (hasInitialized.current) {
142
- return;
143
- }
144
- if (cartCreationPromise) {
145
- void cartCreationPromise.then((cart2) => {
146
- if (cart2) {
147
- initializeCart(cart2);
148
- }
149
- });
150
- return;
163
+ const initializeCart = React.useCallback(async () => {
164
+ const loadedCart = await getOrCreateSharedCart();
165
+ if (!isMounted.current) {
166
+ throw new DOMException("Cart provider was unmounted", "AbortError");
151
167
  }
152
- hasInitialized.current = true;
153
- cartCreationPromise = getOrCreateCartAction().then((cart2) => {
154
- if (cart2) {
155
- initializeCart(cart2);
156
- } else {
157
- console.warn(
158
- "[Replo] Failed to get or create cart on the server. Reach out to support@replo.app if this persists."
159
- );
168
+ serverCart.current = loadedCart;
169
+ if (pendingMutations.current === 0) updateCartData(loadedCart);
170
+ return loadedCart;
171
+ }, [updateCartData]);
172
+ React.useEffect(() => {
173
+ isMounted.current = true;
174
+ void initializeCart().catch((error) => {
175
+ if (isMounted.current) {
176
+ console.error("[Replo] Error getting or creating cart:", error);
160
177
  }
161
- return cart2;
162
- }).catch((error) => {
163
- console.error("[Replo] Error getting or creating cart:", error);
164
- return null;
165
- }).finally(() => {
166
- cartCreationPromise = null;
167
178
  });
168
- }, []);
179
+ return () => {
180
+ isMounted.current = false;
181
+ };
182
+ }, [initializeCart]);
169
183
  const lineItems = cartData?.lines ?? [];
170
184
  const subtotal = cartData?.lines.reduce((sum, lineItem) => {
171
185
  if (lineItem.quantity > 0 && lineItem.merchandise) {
@@ -196,12 +210,7 @@ function CartProvider({
196
210
  }, []);
197
211
  const reportedLineQuantities = React.useRef(/* @__PURE__ */ new Map());
198
212
  const addToCart = async (lines, openCartAfterAdd = true) => {
199
- if (!cartData) {
200
- console.warn(
201
- "[Replo] Cannot add to cart: no cart exists. Reach out to support@replo.app if this persists."
202
- );
203
- return;
204
- }
213
+ const readyCart = cartData ?? serverCart.current ?? await initializeCart();
205
214
  reportedLineQuantities.current.clear();
206
215
  const additions = lines.map((line) => {
207
216
  const lineId = `temp-${uuidv4()}`;
@@ -209,14 +218,14 @@ function CartProvider({
209
218
  return { line, lineId };
210
219
  });
211
220
  const applyLines = (cart2) => {
212
- let updatedCart = { ...cart2 };
221
+ let updatedCart2 = { ...cart2 };
213
222
  for (const { line, lineId } of additions) {
214
- updatedCart = addLineToCart({ cart: updatedCart, line, lineId });
223
+ updatedCart2 = addLineToCart({ cart: updatedCart2, line, lineId });
215
224
  }
216
- return updatedCart;
225
+ return updatedCart2;
217
226
  };
218
- setCartData((currentCart) => {
219
- return currentCart ? applyLines(currentCart) : null;
227
+ const updatedCart = updateCartData((currentCart) => {
228
+ return applyLines(currentCart ?? readyCart);
220
229
  });
221
230
  if (analytics) {
222
231
  for (const line of lines) {
@@ -227,14 +236,14 @@ function CartProvider({
227
236
  data: buildCartLineAnalyticsData({
228
237
  merchandise: line.merchandise,
229
238
  quantity: line.quantity,
230
- currencyCode: cartData.cost.currencyCode
239
+ currencyCode: readyCart.cost.currencyCode
231
240
  })
232
241
  });
233
242
  }
234
243
  }
235
244
  if (openCartAfterAdd) {
236
245
  setIsCartOpen(true);
237
- emitCartView(applyLines(cartData));
246
+ emitCartView(updatedCart);
238
247
  }
239
248
  await enqueueMutation((currentCart) => {
240
249
  return addToCartAction(lines, currentCart.id);
@@ -259,7 +268,7 @@ function CartProvider({
259
268
  });
260
269
  void (quantityDelta > 0 ? analytics.addToCart({ data }) : analytics.removeFromCart({ data }));
261
270
  }
262
- setCartData((currentCart) => {
271
+ updateCartData((currentCart) => {
263
272
  if (!currentCart) {
264
273
  return null;
265
274
  }
@@ -295,7 +304,7 @@ function CartProvider({
295
304
  })
296
305
  });
297
306
  }
298
- setCartData((currentCart) => {
307
+ updateCartData((currentCart) => {
299
308
  if (!currentCart) {
300
309
  return null;
301
310
  }
@@ -311,18 +320,10 @@ function CartProvider({
311
320
  });
312
321
  };
313
322
  const updateDiscountCodes = async (discountCodes) => {
314
- if (!cartData) {
315
- console.warn(
316
- "[Replo] Cannot update discount codes: no cart exists. Reach out to support@replo.app if this persists."
317
- );
318
- return;
319
- }
320
- setCartData((currentCart) => {
321
- if (!currentCart) {
322
- return null;
323
- }
323
+ const readyCart = cartData ?? serverCart.current ?? await initializeCart();
324
+ updateCartData((currentCart) => {
324
325
  return {
325
- ...currentCart,
326
+ ...currentCart ?? readyCart,
326
327
  discountCodes: discountCodes.map((code) => ({
327
328
  code,
328
329
  applicable: true
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../cart/cart-provider.tsx"],
4
- "sourcesContent": ["/**\n * Use useCart() hook to access cart UI state (itemsCount, isCartOpen, openCart, closeCart). For adding products to cart, use useAddToCart. For buy now functionality, use useBuyNow.\n * @module\n */\n\"use client\";\n\nimport type { Cart, CartLine, CartLinePayload } from \"./cart-types\";\n\nimport React from \"react\";\n\nimport { v4 as uuidv4 } from \"uuid\";\n\nimport { useAnalyticsOptional } from \"../analytics/analytics-provider\";\nimport { CanopyError } from \"../lib/canopy-error\";\nimport {\n addToCartAction,\n createCartAction,\n getCartAction,\n getOrCreateCartAction,\n removeCartLineItemsAction,\n updateCartDiscountCodesAction,\n updateCartLineItemAction,\n} from \"./cart-actions\";\nimport {\n buildCartLineAnalyticsData,\n buildCartViewAnalyticsData,\n} from \"./utils/cart-analytics\";\nimport { recalculateCartCost } from \"./utils/cart-utils\";\nimport { createOptimisticSellingPlanAllocation } from \"./utils/variant-to-cart-line\";\n\nclass CartContextError extends CanopyError {}\n\n// Global promise to prevent multiple cart creation attempts\nlet cartCreationPromise: Promise<Cart | null> | null = null;\n\n/**\n * Client-side cart operation to add a line item. Used in editor mode.\n * Merges with existing lines if they match by merchandise ID and selling plan.\n *\n * @param cart - The cart to add the line to\n * @param line - The cart line payload to add\n * @returns The updated cart\n */\nfunction addLineToCart({\n cart,\n line,\n lineId,\n}: {\n cart: Cart;\n line: CartLinePayload;\n lineId: string;\n}): Cart {\n const existingLineIndex = cart.lines.findIndex((existingLine) => {\n return (\n existingLine.merchandise?.id === line.id &&\n // Distinguish by selling plan to avoid merging subscription with one-time\n (line.sellingPlanId ?? null) ===\n (existingLine.sellingPlanAllocation?.sellingPlan.id ?? null)\n );\n });\n\n if (existingLineIndex >= 0) {\n // Update existing line\n const updatedLines = [...cart.lines];\n updatedLines[existingLineIndex] = {\n ...updatedLines[existingLineIndex]!,\n quantity: updatedLines[existingLineIndex]!.quantity + line.quantity,\n };\n return recalculateCartCost({ ...cart, lines: updatedLines });\n } else {\n const optimisticSellingPlanAllocation =\n line.sellingPlanId && line.merchandise\n ? createOptimisticSellingPlanAllocation({\n merchandise: line.merchandise,\n sellingPlanId: line.sellingPlanId,\n currencyCode: cart.cost?.currencyCode ?? \"USD\",\n })\n : null;\n\n const newLine: CartLine = {\n id: lineId,\n quantity: line.quantity,\n merchandise: line.merchandise ?? null,\n attributes: line.properties ?? [],\n sellingPlanAllocation: optimisticSellingPlanAllocation,\n };\n return recalculateCartCost({ ...cart, lines: [newLine, ...cart.lines] });\n }\n}\n\n/**\n * Client-side cart operation to update a line item. Used in editor mode.\n *\n * @param cart - The cart containing the line to update\n * @param line - The cart line payload with updated values\n * @returns The updated cart\n */\nfunction updateLineInCart(cart: Cart, line: CartLinePayload): Cart {\n const updatedLines = cart.lines.map((existingLine) => {\n return existingLine.id === line.id\n ? { ...existingLine, quantity: line.quantity }\n : existingLine;\n });\n return recalculateCartCost({ ...cart, lines: updatedLines });\n}\n\n/**\n * Client-side cart operation to remove a line item. Used in editor mode.\n *\n * @param cart - The cart containing the line to remove\n * @param lineId - The ID of the line to remove\n * @returns The updated cart\n */\nfunction removeLineFromCart(cart: Cart, lineId: string): Cart {\n const updatedLines = cart.lines.filter((line) => line.id !== lineId);\n return recalculateCartCost({ ...cart, lines: updatedLines });\n}\n\n/**\n * Internal cart context type with full functionality.\n * This is for internal use only - external code should use the limited CartContextType.\n */\nexport interface CartContextTypeInternal {\n /** The current cart (can be null) */\n cartData: Cart | null;\n /** Array of cart line items */\n lineItems: CartLine[];\n /** Total price of all items */\n subtotal: number;\n /** Total number of items in cart */\n itemsCount: number;\n /** Currency code for the cart */\n currencyCode: string;\n /** Function to add items to cart */\n addToCart: (\n lines: CartLinePayload[],\n openCartAfterAdd?: boolean,\n ) => Promise<void>;\n /** Function to update cart item quantity */\n updateCartItem: (line: CartLinePayload) => Promise<void>;\n /** Function to remove item from cart */\n removeCartItem: (lineId: string) => Promise<void>;\n /** Function to update discount codes on cart */\n updateDiscountCodes: (discountCodes: string[]) => Promise<void>;\n /** Function to create cart and checkout immediately */\n buyNow: (\n lines: CartLinePayload[],\n discountCodes?: string[],\n ) => Promise<Cart | null>;\n /** URL to redirect to checkout */\n checkoutUrl: string;\n /** Whether the cart UI is open */\n isCartOpen: boolean;\n /** Function to open the cart UI */\n openCart: () => void;\n /** Function to close the cart UI */\n closeCart: () => void;\n}\n\n// NOTE (Gabe, 2026-01-08): We intentionally duplicate properties from CartContextTypeInternal\n// rather than using Pick<> so that TypeDoc generates expanded documentation for each property.\n/**\n * Public cart context type for LLM use.\n * For adding products to cart, use useAddToCart.\n * For buy now functionality, use useBuyNow.\n */\nexport interface CartContextType {\n /** Total number of items in cart */\n itemsCount: number;\n /** Whether the cart UI is open */\n isCartOpen: boolean;\n /** Function to open the cart UI */\n openCart: () => void;\n /** Function to close the cart UI */\n closeCart: () => void;\n /** Function to update discount codes on cart */\n updateDiscountCodes: (discountCodes: string[]) => Promise<void>;\n}\n\nconst CartContext = React.createContext<CartContextTypeInternal | undefined>(\n undefined,\n);\n\n/**\n * Provider component that manages global cart state and operations. Handles both\n * server-side cart synchronization and client-side optimistic updates.\n *\n * @returns A context provider wrapping the children with cart functionality\n */\nexport function CartProvider({\n children,\n cart,\n}: React.PropsWithChildren<{\n /** Initial cart data from the server (can be null) */\n cart: Cart | null;\n}>) {\n const [cartData, setCartData] = React.useState<Cart | null>(cart);\n const [isCartOpen, setIsCartOpen] = React.useState(false);\n const hasInitialized = React.useRef(false);\n const analytics = useAnalyticsOptional();\n const serverCart = React.useRef(cart);\n const needsRefresh = React.useRef(false);\n const mutationQueue = React.useRef(Promise.resolve());\n const pendingMutations = React.useRef(0);\n const optimisticLines = React.useRef(new Map<string, CartLinePayload>());\n\n const enqueueMutation = async (\n save: (currentCart: Cart) => Promise<Cart | null>,\n ) => {\n pendingMutations.current += 1;\n const request = mutationQueue.current.then(async () => {\n await cartCreationPromise;\n if (needsRefresh.current) {\n const restoredCart = await getCartAction();\n if (!restoredCart)\n throw new CartContextError({\n message:\n \"Your cart could not be refreshed. Please reload before changing it.\",\n });\n serverCart.current = restoredCart;\n needsRefresh.current = false;\n }\n if (!serverCart.current) return;\n try {\n const savedCart = await save(serverCart.current);\n if (!savedCart)\n throw new CartContextError({\n message: \"Your cart could not be saved. Please try again.\",\n });\n serverCart.current = savedCart;\n } catch (error) {\n // A lost response may still have persisted the add that the next removal targets.\n const restoredCart = await getCartAction().catch(() => null);\n needsRefresh.current = !restoredCart;\n if (restoredCart) serverCart.current = restoredCart;\n throw error;\n }\n });\n // Cookie writes must finish in shopper order, including after a failed request.\n mutationQueue.current = request\n .catch(() => {})\n .then(() => {\n pendingMutations.current -= 1;\n if (pendingMutations.current === 0) {\n reportedLineQuantities.current.clear();\n optimisticLines.current.clear();\n setCartData(serverCart.current);\n }\n });\n await request;\n };\n\n const findLine = ({\n currentCart,\n lineId,\n originalLine,\n }: {\n currentCart: Cart;\n lineId: string;\n originalLine?: CartLine;\n }) => {\n const existingLine = currentCart.lines.find((line) => line.id === lineId);\n if (existingLine) return existingLine;\n const optimisticLine = optimisticLines.current.get(lineId);\n const merchandiseId = optimisticLine?.id ?? originalLine?.merchandise?.id;\n const sellingPlanId =\n optimisticLine?.sellingPlanId ??\n originalLine?.sellingPlanAllocation?.sellingPlan.id ??\n null;\n return currentCart.lines.find((line) => {\n return (\n line.merchandise?.id === merchandiseId &&\n (line.sellingPlanAllocation?.sellingPlan.id ?? null) === sellingPlanId\n );\n });\n };\n\n // Initialize cart on mount\n // eslint-disable-next-line replo/no-use-effect -- Legacy effect - may or may not be necessary\n React.useEffect(() => {\n const initializeCart = (loadedCart: Cart) => {\n serverCart.current = loadedCart;\n if (pendingMutations.current === 0) setCartData(loadedCart);\n };\n\n // Early exit if already initialized\n if (hasInitialized.current) {\n return;\n }\n\n // If there's already a creation in progress, attach to it\n if (cartCreationPromise) {\n void cartCreationPromise.then((cart) => {\n if (cart) {\n initializeCart(cart);\n }\n });\n return;\n }\n\n // Mark as initialized to prevent duplicate calls\n hasInitialized.current = true;\n\n // Get existing cart or create new one\n cartCreationPromise = getOrCreateCartAction()\n .then((cart) => {\n if (cart) {\n initializeCart(cart);\n } else {\n console.warn(\n \"[Replo] Failed to get or create cart on the server. Reach out to support@replo.app if this persists.\",\n );\n }\n return cart;\n })\n .catch((error) => {\n console.error(\"[Replo] Error getting or creating cart:\", error);\n return null;\n })\n .finally(() => {\n // Reset the promise after completion\n cartCreationPromise = null;\n });\n }, []);\n\n // Derived values - handle null cart gracefully\n const lineItems = cartData?.lines ?? [];\n\n const subtotal =\n cartData?.lines.reduce((sum, lineItem) => {\n if (lineItem.quantity > 0 && lineItem.merchandise) {\n sum += lineItem.merchandise.price * lineItem.quantity;\n }\n return sum;\n }, 0) ?? 0;\n\n const itemsCount =\n cartData?.lines.reduce((sum, lineItem) => {\n if (lineItem.quantity > 0) {\n sum += lineItem.quantity;\n }\n return sum;\n }, 0) ?? 0;\n\n // Cart UI state functions\n const emitCartView = React.useCallback(\n (cart: Cart | null) => {\n if (analytics) {\n void analytics.viewCart({ data: buildCartViewAnalyticsData(cart) });\n }\n },\n [analytics],\n );\n\n const openCart = React.useCallback(() => {\n setIsCartOpen(true);\n emitCartView(cartData);\n }, [cartData, emitCartView]);\n\n const closeCart = React.useCallback(() => {\n setIsCartOpen(false);\n }, []);\n\n // Last quantity reported to analytics per line with an update in flight, so\n // overlapping stepper clicks diff against it instead of the same render-time\n // quantity. Dropped once the server confirms or another mutation replaces\n // the line set.\n const reportedLineQuantities = React.useRef(new Map<string, number>());\n\n const addToCart = async (\n lines: CartLinePayload[],\n openCartAfterAdd: boolean = true,\n ) => {\n // If no cart exists, we can't add to it\n if (!cartData) {\n console.warn(\n \"[Replo] Cannot add to cart: no cart exists. Reach out to support@replo.app if this persists.\",\n );\n return;\n }\n\n reportedLineQuantities.current.clear();\n const additions = lines.map((line) => {\n const lineId = `temp-${uuidv4()}`;\n optimisticLines.current.set(lineId, line);\n return { line, lineId };\n });\n const applyLines = (cart: Cart) => {\n let updatedCart = { ...cart };\n for (const { line, lineId } of additions) {\n updatedCart = addLineToCart({ cart: updatedCart, line, lineId });\n }\n return updatedCart;\n };\n\n // Optimistic update - use functional form to avoid stale state\n setCartData((currentCart) => {\n return currentCart ? applyLines(currentCart) : null;\n });\n\n if (analytics) {\n for (const line of lines) {\n if (!line.merchandise) {\n continue;\n }\n void analytics.addToCart({\n data: buildCartLineAnalyticsData({\n merchandise: line.merchandise,\n quantity: line.quantity,\n currencyCode: cartData.cost.currencyCode,\n }),\n });\n }\n }\n\n if (openCartAfterAdd) {\n setIsCartOpen(true);\n // The cart view has to describe the cart with the new lines in it, and\n // React state has not re-rendered yet, so build it from the same\n // projection the optimistic update used.\n emitCartView(applyLines(cartData));\n }\n\n await enqueueMutation((currentCart) => {\n return addToCartAction(lines, currentCart.id);\n });\n };\n\n const updateCartItem = async (line: CartLinePayload) => {\n // If no cart exists, we can't update it\n if (!cartData) {\n console.warn(\n \"[Replo] Cannot update cart item: no cart exists. Reach out to support@replo.app if this persists.\",\n );\n return;\n }\n\n // Ad platforms have no \"quantity changed\" event: an increase is an add of\n // the difference and a decrease is a remove of the difference, matching\n // how Shopify themes report their cart steppers.\n const currentLine = cartData.lines.find((item) => item.id === line.id);\n const merchandise = currentLine?.merchandise ?? line.merchandise;\n const quantityDelta =\n line.quantity -\n (reportedLineQuantities.current.get(line.id) ??\n currentLine?.quantity ??\n 0);\n reportedLineQuantities.current.set(line.id, line.quantity);\n if (analytics && merchandise && quantityDelta !== 0) {\n const data = buildCartLineAnalyticsData({\n merchandise,\n quantity: Math.abs(quantityDelta),\n currencyCode: cartData.cost.currencyCode,\n });\n void (quantityDelta > 0\n ? analytics.addToCart({ data })\n : analytics.removeFromCart({ data }));\n }\n\n // Optimistic update - use functional form to avoid stale state\n setCartData((currentCart) => {\n if (!currentCart) {\n return null;\n }\n return updateLineInCart(currentCart, line);\n });\n\n await enqueueMutation(async (currentCart) => {\n const savedLine = findLine({\n currentCart,\n lineId: line.id,\n originalLine: currentLine,\n });\n return savedLine\n ? await updateCartLineItemAction(\n { ...line, id: savedLine.id },\n currentCart.id,\n )\n : currentCart;\n });\n };\n\n const removeCartItem = async (lineId: string) => {\n if (!cartData) {\n console.warn(\n \"[Replo] Cannot remove cart item: no cart exists. Reach out to support@replo.app if this persists.\",\n );\n return;\n }\n\n const itemToRemove = cartData.lines.find((item) => item.id === lineId);\n reportedLineQuantities.current.delete(lineId);\n if (analytics && itemToRemove && itemToRemove.merchandise) {\n void analytics.removeFromCart({\n data: buildCartLineAnalyticsData({\n merchandise: itemToRemove.merchandise,\n quantity: itemToRemove.quantity,\n currencyCode: cartData.cost.currencyCode,\n }),\n });\n }\n\n // Optimistic update - use functional form to avoid stale state\n setCartData((currentCart) => {\n if (!currentCart) {\n return null;\n }\n return removeLineFromCart(currentCart, lineId);\n });\n\n await enqueueMutation(async (currentCart) => {\n const savedLine = findLine({\n currentCart,\n lineId,\n originalLine: itemToRemove,\n });\n return savedLine\n ? await removeCartLineItemsAction([savedLine.id], currentCart.id)\n : currentCart;\n });\n };\n\n const updateDiscountCodes = async (discountCodes: string[]) => {\n // If no cart exists, we can't update discount codes\n if (!cartData) {\n console.warn(\n \"[Replo] Cannot update discount codes: no cart exists. Reach out to support@replo.app if this persists.\",\n );\n return;\n }\n\n // Optimistic update - use functional form to avoid stale state\n setCartData((currentCart) => {\n if (!currentCart) {\n return null;\n }\n return {\n ...currentCart,\n discountCodes: discountCodes.map((code) => ({\n code,\n applicable: true,\n })),\n };\n });\n\n await enqueueMutation((currentCart) => {\n return updateCartDiscountCodesAction(discountCodes, currentCart.id);\n });\n };\n\n const buyNow = async (lines: CartLinePayload[], discountCodes?: string[]) => {\n // Create a new cart with the specified lines and discount codes\n const cart = await createCartAction({\n lines,\n skipStoringCart: true,\n discountCodes,\n });\n if (cart) {\n return cart;\n } else {\n console.warn(\n \"[Replo] Failed to create cart for buy now. Reach out to support@replo.app if this persists.\",\n );\n return null;\n }\n };\n\n const checkoutUrl = cartData?.checkoutUrl ?? \"/\";\n\n return (\n <CartContext.Provider\n value={{\n cartData,\n lineItems,\n subtotal,\n itemsCount,\n currencyCode: cartData?.cost.currencyCode ?? \"USD\",\n addToCart,\n updateCartItem,\n removeCartItem,\n updateDiscountCodes,\n buyNow,\n checkoutUrl,\n isCartOpen,\n openCart,\n closeCart,\n }}\n >\n {children}\n </CartContext.Provider>\n );\n}\n\n/**\n * @deprecated For internal use only. Use useAddToCart or useBuyNow\n * for cart operations. Use useCart for cart UI state (itemsCount, openCart, closeCart).\n */\nexport function useCartInternal(): CartContextTypeInternal {\n const context = React.useContext(CartContext);\n if (context === undefined) {\n throw new CartContextError({\n message: \"useCartInternal must be used within a CartProvider\",\n });\n }\n return context;\n}\n\n/**\n * Hook to access cart UI state and controls. For adding products to cart,\n * use useAddToCart. For buy now functionality, use useBuyNow.\n *\n * @example\n * ```tsx\n * import { useCart } from \"@replohq/sdk/cart/cart-provider\";\n *\n * function MyComponent() {\n * const { itemsCount, openCart } = useCart();\n * ...\n * }\n * ```\n * @throws Error if used outside of a CartProvider\n */\nexport function useCart(): CartContextType {\n const context = React.useContext(CartContext);\n if (context === undefined) {\n throw new CartContextError({\n message: \"useCart must be used within a CartProvider\",\n });\n }\n return {\n itemsCount: context.itemsCount,\n isCartOpen: context.isCartOpen,\n openCart: context.openCart,\n closeCart: context.closeCart,\n updateDiscountCodes: context.updateDiscountCodes,\n };\n}\n"],
5
- "mappings": "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",
6
- "names": ["cart"]
4
+ "sourcesContent": ["/**\n * Use useCart() hook to access cart UI state (itemsCount, isCartOpen, openCart, closeCart). For adding products to cart, use useAddToCart. For buy now functionality, use useBuyNow.\n * @module\n */\n\"use client\";\n\nimport type { Cart, CartLine, CartLinePayload } from \"./cart-types\";\n\nimport React from \"react\";\n\nimport { v4 as uuidv4 } from \"uuid\";\n\nimport { useAnalyticsOptional } from \"../analytics/analytics-provider\";\nimport { CanopyError } from \"../lib/canopy-error\";\nimport {\n addToCartAction,\n createCartAction,\n getCartAction,\n getOrCreateCartAction,\n removeCartLineItemsAction,\n updateCartDiscountCodesAction,\n updateCartLineItemAction,\n} from \"./cart-actions\";\nimport {\n buildCartLineAnalyticsData,\n buildCartViewAnalyticsData,\n} from \"./utils/cart-analytics\";\nimport { recalculateCartCost } from \"./utils/cart-utils\";\nimport { createOptimisticSellingPlanAllocation } from \"./utils/variant-to-cart-line\";\n\nclass CartContextError extends CanopyError {}\n\n// Global promise to prevent multiple cart creation attempts\nlet cartCreationPromise: Promise<Cart> | null = null;\n\nfunction getOrCreateSharedCart() {\n cartCreationPromise ??= getOrCreateCartAction()\n .then((cart) => {\n if (!cart) {\n throw new CartContextError({\n message: \"Your cart could not be loaded. Please try again.\",\n });\n }\n return cart;\n })\n .finally(() => {\n cartCreationPromise = null;\n });\n return cartCreationPromise;\n}\n\n/**\n * Client-side cart operation to add a line item. Used in editor mode.\n * Merges with existing lines if they match by merchandise ID and selling plan.\n *\n * @param cart - The cart to add the line to\n * @param line - The cart line payload to add\n * @returns The updated cart\n */\nfunction addLineToCart({\n cart,\n line,\n lineId,\n}: {\n cart: Cart;\n line: CartLinePayload;\n lineId: string;\n}): Cart {\n const existingLineIndex = cart.lines.findIndex((existingLine) => {\n return (\n existingLine.merchandise?.id === line.id &&\n // Distinguish by selling plan to avoid merging subscription with one-time\n (line.sellingPlanId ?? null) ===\n (existingLine.sellingPlanAllocation?.sellingPlan.id ?? null)\n );\n });\n\n if (existingLineIndex >= 0) {\n // Update existing line\n const updatedLines = [...cart.lines];\n updatedLines[existingLineIndex] = {\n ...updatedLines[existingLineIndex]!,\n quantity: updatedLines[existingLineIndex]!.quantity + line.quantity,\n };\n return recalculateCartCost({ ...cart, lines: updatedLines });\n } else {\n const optimisticSellingPlanAllocation =\n line.sellingPlanId && line.merchandise\n ? createOptimisticSellingPlanAllocation({\n merchandise: line.merchandise,\n sellingPlanId: line.sellingPlanId,\n currencyCode: cart.cost?.currencyCode ?? \"USD\",\n })\n : null;\n\n const newLine: CartLine = {\n id: lineId,\n quantity: line.quantity,\n merchandise: line.merchandise ?? null,\n attributes: line.properties ?? [],\n sellingPlanAllocation: optimisticSellingPlanAllocation,\n };\n return recalculateCartCost({ ...cart, lines: [newLine, ...cart.lines] });\n }\n}\n\n/**\n * Client-side cart operation to update a line item. Used in editor mode.\n *\n * @param cart - The cart containing the line to update\n * @param line - The cart line payload with updated values\n * @returns The updated cart\n */\nfunction updateLineInCart(cart: Cart, line: CartLinePayload): Cart {\n const updatedLines = cart.lines.map((existingLine) => {\n return existingLine.id === line.id\n ? { ...existingLine, quantity: line.quantity }\n : existingLine;\n });\n return recalculateCartCost({ ...cart, lines: updatedLines });\n}\n\n/**\n * Client-side cart operation to remove a line item. Used in editor mode.\n *\n * @param cart - The cart containing the line to remove\n * @param lineId - The ID of the line to remove\n * @returns The updated cart\n */\nfunction removeLineFromCart(cart: Cart, lineId: string): Cart {\n const updatedLines = cart.lines.filter((line) => line.id !== lineId);\n return recalculateCartCost({ ...cart, lines: updatedLines });\n}\n\n/**\n * Internal cart context type with full functionality.\n * This is for internal use only - external code should use the limited CartContextType.\n */\nexport interface CartContextTypeInternal {\n /** The current cart (can be null) */\n cartData: Cart | null;\n /** Array of cart line items */\n lineItems: CartLine[];\n /** Total price of all items */\n subtotal: number;\n /** Total number of items in cart */\n itemsCount: number;\n /** Currency code for the cart */\n currencyCode: string;\n /** Function to add items to cart */\n addToCart: (\n lines: CartLinePayload[],\n openCartAfterAdd?: boolean,\n ) => Promise<void>;\n /** Function to update cart item quantity */\n updateCartItem: (line: CartLinePayload) => Promise<void>;\n /** Function to remove item from cart */\n removeCartItem: (lineId: string) => Promise<void>;\n /** Function to update discount codes on cart */\n updateDiscountCodes: (discountCodes: string[]) => Promise<void>;\n /** Function to create cart and checkout immediately */\n buyNow: (\n lines: CartLinePayload[],\n discountCodes?: string[],\n ) => Promise<Cart | null>;\n /** URL to redirect to checkout */\n checkoutUrl: string;\n /** Whether the cart UI is open */\n isCartOpen: boolean;\n /** Function to open the cart UI */\n openCart: () => void;\n /** Function to close the cart UI */\n closeCart: () => void;\n}\n\n// NOTE (Gabe, 2026-01-08): We intentionally duplicate properties from CartContextTypeInternal\n// rather than using Pick<> so that TypeDoc generates expanded documentation for each property.\n/**\n * Public cart context type for LLM use.\n * For adding products to cart, use useAddToCart.\n * For buy now functionality, use useBuyNow.\n */\nexport interface CartContextType {\n /** Total number of items in cart */\n itemsCount: number;\n /** Whether the cart UI is open */\n isCartOpen: boolean;\n /** Function to open the cart UI */\n openCart: () => void;\n /** Function to close the cart UI */\n closeCart: () => void;\n /** Function to update discount codes on cart */\n updateDiscountCodes: (discountCodes: string[]) => Promise<void>;\n}\n\nconst CartContext = React.createContext<CartContextTypeInternal | undefined>(\n undefined,\n);\n\n/**\n * Provider component that manages global cart state and operations. Handles both\n * server-side cart synchronization and client-side optimistic updates.\n *\n * @returns A context provider wrapping the children with cart functionality\n */\nexport function CartProvider({\n children,\n cart,\n}: React.PropsWithChildren<{\n /** Initial cart data from the server (can be null) */\n cart: Cart | null;\n}>) {\n const [cartData, setCartData] = React.useState<Cart | null>(cart);\n const optimisticCart = React.useRef(cart);\n const updateCartData = React.useCallback(\n (update: React.SetStateAction<Cart | null>) => {\n const nextCart =\n typeof update === \"function\" ? update(optimisticCart.current) : update;\n // Analytics and overlapping mutations need the snapshot before React renders it.\n optimisticCart.current = nextCart;\n setCartData(nextCart);\n return nextCart;\n },\n [],\n );\n const [isCartOpen, setIsCartOpen] = React.useState(false);\n const isMounted = React.useRef(true);\n const analytics = useAnalyticsOptional();\n const serverCart = React.useRef(cart);\n const needsRefresh = React.useRef(false);\n const mutationQueue = React.useRef(Promise.resolve());\n const pendingMutations = React.useRef(0);\n const optimisticLines = React.useRef(new Map<string, CartLinePayload>());\n\n const enqueueMutation = async (\n save: (currentCart: Cart) => Promise<Cart | null>,\n ) => {\n pendingMutations.current += 1;\n const request = mutationQueue.current.then(async () => {\n // An existing server cart remains usable if background initialization fails.\n await cartCreationPromise?.catch(() => null);\n if (needsRefresh.current) {\n const restoredCart = await getCartAction();\n if (!restoredCart)\n throw new CartContextError({\n message:\n \"Your cart could not be refreshed. Please reload before changing it.\",\n });\n serverCart.current = restoredCart;\n needsRefresh.current = false;\n }\n if (!serverCart.current) {\n throw new CartContextError({\n message: \"Your cart could not be loaded. Please try again.\",\n });\n }\n try {\n const savedCart = await save(serverCart.current);\n if (!savedCart)\n throw new CartContextError({\n message: \"Your cart could not be saved. Please try again.\",\n });\n serverCart.current = savedCart;\n } catch (error) {\n // A lost response may still have persisted the add that the next removal targets.\n const restoredCart = await getCartAction().catch(() => null);\n needsRefresh.current = !restoredCart;\n if (restoredCart) serverCart.current = restoredCart;\n throw error;\n }\n });\n // Cookie writes must finish in shopper order, including after a failed request.\n mutationQueue.current = request\n .catch(() => {})\n .then(() => {\n pendingMutations.current -= 1;\n if (pendingMutations.current === 0) {\n reportedLineQuantities.current.clear();\n optimisticLines.current.clear();\n updateCartData(serverCart.current);\n }\n });\n await request;\n };\n\n const findLine = ({\n currentCart,\n lineId,\n originalLine,\n }: {\n currentCart: Cart;\n lineId: string;\n originalLine?: CartLine;\n }) => {\n const existingLine = currentCart.lines.find((line) => line.id === lineId);\n if (existingLine) return existingLine;\n const optimisticLine = optimisticLines.current.get(lineId);\n const merchandiseId = optimisticLine?.id ?? originalLine?.merchandise?.id;\n const sellingPlanId =\n optimisticLine?.sellingPlanId ??\n originalLine?.sellingPlanAllocation?.sellingPlan.id ??\n null;\n return currentCart.lines.find((line) => {\n return (\n line.merchandise?.id === merchandiseId &&\n (line.sellingPlanAllocation?.sellingPlan.id ?? null) === sellingPlanId\n );\n });\n };\n\n const initializeCart = React.useCallback(async () => {\n const loadedCart = await getOrCreateSharedCart();\n if (!isMounted.current) {\n throw new DOMException(\"Cart provider was unmounted\", \"AbortError\");\n }\n serverCart.current = loadedCart;\n if (pendingMutations.current === 0) updateCartData(loadedCart);\n return loadedCart;\n }, [updateCartData]);\n\n // eslint-disable-next-line replo/no-use-effect -- Initializes the browser cart on mount.\n React.useEffect(() => {\n isMounted.current = true;\n void initializeCart().catch((error) => {\n if (isMounted.current) {\n console.error(\"[Replo] Error getting or creating cart:\", error);\n }\n });\n return () => {\n isMounted.current = false;\n };\n }, [initializeCart]);\n\n // Derived values - handle null cart gracefully\n const lineItems = cartData?.lines ?? [];\n\n const subtotal =\n cartData?.lines.reduce((sum, lineItem) => {\n if (lineItem.quantity > 0 && lineItem.merchandise) {\n sum += lineItem.merchandise.price * lineItem.quantity;\n }\n return sum;\n }, 0) ?? 0;\n\n const itemsCount =\n cartData?.lines.reduce((sum, lineItem) => {\n if (lineItem.quantity > 0) {\n sum += lineItem.quantity;\n }\n return sum;\n }, 0) ?? 0;\n\n // Cart UI state functions\n const emitCartView = React.useCallback(\n (cart: Cart | null) => {\n if (analytics) {\n void analytics.viewCart({ data: buildCartViewAnalyticsData(cart) });\n }\n },\n [analytics],\n );\n\n const openCart = React.useCallback(() => {\n setIsCartOpen(true);\n emitCartView(cartData);\n }, [cartData, emitCartView]);\n\n const closeCart = React.useCallback(() => {\n setIsCartOpen(false);\n }, []);\n\n // Last quantity reported to analytics per line with an update in flight, so\n // overlapping stepper clicks diff against it instead of the same render-time\n // quantity. Dropped once the server confirms or another mutation replaces\n // the line set.\n const reportedLineQuantities = React.useRef(new Map<string, number>());\n\n const addToCart = async (\n lines: CartLinePayload[],\n openCartAfterAdd: boolean = true,\n ) => {\n // React callbacks retain their render's cart, even after initialization resolves.\n const readyCart =\n cartData ?? serverCart.current ?? (await initializeCart());\n\n reportedLineQuantities.current.clear();\n const additions = lines.map((line) => {\n const lineId = `temp-${uuidv4()}`;\n optimisticLines.current.set(lineId, line);\n return { line, lineId };\n });\n const applyLines = (cart: Cart) => {\n let updatedCart = { ...cart };\n for (const { line, lineId } of additions) {\n updatedCart = addLineToCart({ cart: updatedCart, line, lineId });\n }\n return updatedCart;\n };\n\n const updatedCart = updateCartData((currentCart) => {\n return applyLines(currentCart ?? readyCart);\n });\n\n if (analytics) {\n for (const line of lines) {\n if (!line.merchandise) {\n continue;\n }\n void analytics.addToCart({\n data: buildCartLineAnalyticsData({\n merchandise: line.merchandise,\n quantity: line.quantity,\n currencyCode: readyCart.cost.currencyCode,\n }),\n });\n }\n }\n\n if (openCartAfterAdd) {\n setIsCartOpen(true);\n emitCartView(updatedCart);\n }\n\n await enqueueMutation((currentCart) => {\n return addToCartAction(lines, currentCart.id);\n });\n };\n\n const updateCartItem = async (line: CartLinePayload) => {\n // If no cart exists, we can't update it\n if (!cartData) {\n console.warn(\n \"[Replo] Cannot update cart item: no cart exists. Reach out to support@replo.app if this persists.\",\n );\n return;\n }\n\n // Ad platforms have no \"quantity changed\" event: an increase is an add of\n // the difference and a decrease is a remove of the difference, matching\n // how Shopify themes report their cart steppers.\n const currentLine = cartData.lines.find((item) => item.id === line.id);\n const merchandise = currentLine?.merchandise ?? line.merchandise;\n const quantityDelta =\n line.quantity -\n (reportedLineQuantities.current.get(line.id) ??\n currentLine?.quantity ??\n 0);\n reportedLineQuantities.current.set(line.id, line.quantity);\n if (analytics && merchandise && quantityDelta !== 0) {\n const data = buildCartLineAnalyticsData({\n merchandise,\n quantity: Math.abs(quantityDelta),\n currencyCode: cartData.cost.currencyCode,\n });\n void (quantityDelta > 0\n ? analytics.addToCart({ data })\n : analytics.removeFromCart({ data }));\n }\n\n // Optimistic update - use functional form to avoid stale state\n updateCartData((currentCart) => {\n if (!currentCart) {\n return null;\n }\n return updateLineInCart(currentCart, line);\n });\n\n await enqueueMutation(async (currentCart) => {\n const savedLine = findLine({\n currentCart,\n lineId: line.id,\n originalLine: currentLine,\n });\n return savedLine\n ? await updateCartLineItemAction(\n { ...line, id: savedLine.id },\n currentCart.id,\n )\n : currentCart;\n });\n };\n\n const removeCartItem = async (lineId: string) => {\n if (!cartData) {\n console.warn(\n \"[Replo] Cannot remove cart item: no cart exists. Reach out to support@replo.app if this persists.\",\n );\n return;\n }\n\n const itemToRemove = cartData.lines.find((item) => item.id === lineId);\n reportedLineQuantities.current.delete(lineId);\n if (analytics && itemToRemove && itemToRemove.merchandise) {\n void analytics.removeFromCart({\n data: buildCartLineAnalyticsData({\n merchandise: itemToRemove.merchandise,\n quantity: itemToRemove.quantity,\n currencyCode: cartData.cost.currencyCode,\n }),\n });\n }\n\n // Optimistic update - use functional form to avoid stale state\n updateCartData((currentCart) => {\n if (!currentCart) {\n return null;\n }\n return removeLineFromCart(currentCart, lineId);\n });\n\n await enqueueMutation(async (currentCart) => {\n const savedLine = findLine({\n currentCart,\n lineId,\n originalLine: itemToRemove,\n });\n return savedLine\n ? await removeCartLineItemsAction([savedLine.id], currentCart.id)\n : currentCart;\n });\n };\n\n const updateDiscountCodes = async (discountCodes: string[]) => {\n const readyCart =\n cartData ?? serverCart.current ?? (await initializeCart());\n\n updateCartData((currentCart) => {\n return {\n ...(currentCart ?? readyCart),\n discountCodes: discountCodes.map((code) => ({\n code,\n applicable: true,\n })),\n };\n });\n\n await enqueueMutation((currentCart) => {\n return updateCartDiscountCodesAction(discountCodes, currentCart.id);\n });\n };\n\n const buyNow = async (lines: CartLinePayload[], discountCodes?: string[]) => {\n // Create a new cart with the specified lines and discount codes\n const cart = await createCartAction({\n lines,\n skipStoringCart: true,\n discountCodes,\n });\n if (cart) {\n return cart;\n } else {\n console.warn(\n \"[Replo] Failed to create cart for buy now. Reach out to support@replo.app if this persists.\",\n );\n return null;\n }\n };\n\n const checkoutUrl = cartData?.checkoutUrl ?? \"/\";\n\n return (\n <CartContext.Provider\n value={{\n cartData,\n lineItems,\n subtotal,\n itemsCount,\n currencyCode: cartData?.cost.currencyCode ?? \"USD\",\n addToCart,\n updateCartItem,\n removeCartItem,\n updateDiscountCodes,\n buyNow,\n checkoutUrl,\n isCartOpen,\n openCart,\n closeCart,\n }}\n >\n {children}\n </CartContext.Provider>\n );\n}\n\n/**\n * @deprecated For internal use only. Use useAddToCart or useBuyNow\n * for cart operations. Use useCart for cart UI state (itemsCount, openCart, closeCart).\n */\nexport function useCartInternal(): CartContextTypeInternal {\n const context = React.useContext(CartContext);\n if (context === undefined) {\n throw new CartContextError({\n message: \"useCartInternal must be used within a CartProvider\",\n });\n }\n return context;\n}\n\n/**\n * Hook to access cart UI state and controls. For adding products to cart,\n * use useAddToCart. For buy now functionality, use useBuyNow.\n *\n * @example\n * ```tsx\n * import { useCart } from \"@replohq/sdk/cart/cart-provider\";\n *\n * function MyComponent() {\n * const { itemsCount, openCart } = useCart();\n * ...\n * }\n * ```\n * @throws Error if used outside of a CartProvider\n */\nexport function useCart(): CartContextType {\n const context = React.useContext(CartContext);\n if (context === undefined) {\n throw new CartContextError({\n message: \"useCart must be used within a CartProvider\",\n });\n }\n return {\n itemsCount: context.itemsCount,\n isCartOpen: context.isCartOpen,\n openCart: context.openCart,\n closeCart: context.closeCart,\n updateDiscountCodes: context.updateDiscountCodes,\n };\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["cart", "updatedCart"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  export const BUILD_METADATA = {
2
2
  "packageName": "@replohq/sdk",
3
- "version": "1.3.2",
3
+ "version": "1.4.1",
4
4
  "branch": "HEAD",
5
- "commit": "a6ddf179a9377ee3c08389733ee7fc67a11ee3ec",
6
- "builtAt": "2026-09-08T07:18:18.884Z"
5
+ "commit": "1c91f9376d0e3d2c43e75b876a9c6a184969c874",
6
+ "builtAt": "2026-09-08T22:17:09.451Z"
7
7
  };
@@ -2,6 +2,7 @@ export type CollectionLoaderArgs = {
2
2
  handle?: string;
3
3
  collectionGid?: string;
4
4
  language?: string;
5
+ country?: string;
5
6
  };
6
7
  /**
7
8
  * Builds the single object used as BOTH the React Query key and the loader
@@ -12,4 +13,4 @@ export type CollectionLoaderArgs = {
12
13
  * Keys left `undefined` drop out of React Query's key hash, so omitting a field
13
14
  * here hashes the same as a prefetch that never passed it.
14
15
  */
15
- export declare function buildCollectionLoaderArgs({ handle, collectionGid, language, }: CollectionLoaderArgs): CollectionLoaderArgs;
16
+ export declare function buildCollectionLoaderArgs({ handle, collectionGid, language, country, }: CollectionLoaderArgs): CollectionLoaderArgs;
@@ -1,12 +1,14 @@
1
1
  function buildCollectionLoaderArgs({
2
2
  handle,
3
3
  collectionGid,
4
- language
4
+ language,
5
+ country
5
6
  }) {
6
7
  return {
7
8
  handle,
8
9
  collectionGid,
9
- language
10
+ language,
11
+ country
10
12
  };
11
13
  }
12
14
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../loaders/collection-loader-args.ts"],
4
- "sourcesContent": ["export type CollectionLoaderArgs = {\n handle?: string;\n collectionGid?: string;\n language?: string;\n};\n\n/**\n * Builds the single object used as BOTH the React Query key and the loader\n * payload. They must stay identical: `PrefetchedLoaders` seeds the cache under\n * `[loaderKey, args]`, so an arg sent to the loader but missing from the key\n * (or vice versa) silently misses the prefetch.\n *\n * Keys left `undefined` drop out of React Query's key hash, so omitting a field\n * here hashes the same as a prefetch that never passed it.\n */\nexport function buildCollectionLoaderArgs({\n handle,\n collectionGid,\n language,\n}: CollectionLoaderArgs): CollectionLoaderArgs {\n return {\n handle,\n collectionGid,\n language,\n };\n}\n"],
5
- "mappings": "AAeO,SAAS,0BAA0B;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AACF,GAA+C;AAC7C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["export type CollectionLoaderArgs = {\n handle?: string;\n collectionGid?: string;\n language?: string;\n country?: string;\n};\n\n/**\n * Builds the single object used as BOTH the React Query key and the loader\n * payload. They must stay identical: `PrefetchedLoaders` seeds the cache under\n * `[loaderKey, args]`, so an arg sent to the loader but missing from the key\n * (or vice versa) silently misses the prefetch.\n *\n * Keys left `undefined` drop out of React Query's key hash, so omitting a field\n * here hashes the same as a prefetch that never passed it.\n */\nexport function buildCollectionLoaderArgs({\n handle,\n collectionGid,\n language,\n country,\n}: CollectionLoaderArgs): CollectionLoaderArgs {\n return {\n handle,\n collectionGid,\n language,\n country,\n };\n}\n"],
5
+ "mappings": "AAgBO,SAAS,0BAA0B;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA+C;AAC7C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -6,5 +6,5 @@ type CollectionLoaderProps = CollectionLoaderArgs & {
6
6
  children: (data: FullCollection) => ReactNode;
7
7
  fallback?: ReactNode;
8
8
  };
9
- export declare function CollectionLoader({ loaderKey, handle, collectionGid, language, children, fallback, }: CollectionLoaderProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare function CollectionLoader({ loaderKey, handle, collectionGid, language, country, children, fallback, }: CollectionLoaderProps): import("react/jsx-runtime").JSX.Element;
10
10
  export {};
@@ -30,13 +30,15 @@ function CollectionLoader({
30
30
  handle,
31
31
  collectionGid,
32
32
  language,
33
+ country,
33
34
  children,
34
35
  fallback
35
36
  }) {
36
37
  const args = buildCollectionLoaderArgs({
37
38
  handle,
38
39
  collectionGid,
39
- language
40
+ language,
41
+ country
40
42
  });
41
43
  return /* @__PURE__ */ jsx(
42
44
  LoaderErrorBoundary,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../loaders/collection-loader.tsx"],
4
- "sourcesContent": ["\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport type { CollectionLoaderArgs } from \"./collection-loader-args\";\nimport type { FullCollection } from \"./loader-schemas\";\n\nimport { Suspense } from \"react\";\n\nimport { useSuspenseQuery } from \"@tanstack/react-query\";\n\nimport { buildCollectionLoaderArgs } from \"./collection-loader-args\";\nimport { invokeLoader } from \"./invoke-loader\";\nimport { LoaderErrorBoundary } from \"./loader-error-boundary\";\nimport { fullCollectionSchema } from \"./loader-schemas\";\nimport { useReportPreviewPlaceholderRender } from \"./preview-placeholder\";\n\ntype CollectionLoaderProps = CollectionLoaderArgs & {\n loaderKey: string;\n children: (data: FullCollection) => ReactNode;\n fallback?: ReactNode;\n};\n\nfunction CollectionLoaderInner({\n loaderKey,\n args,\n children,\n}: {\n loaderKey: string;\n args: CollectionLoaderArgs;\n children: (data: FullCollection) => ReactNode;\n}) {\n const queryResult = useSuspenseQuery({\n queryKey: [loaderKey, args],\n queryFn: async () => {\n const loadedData = await invokeLoader({\n loaderKey,\n args,\n });\n return fullCollectionSchema.parse(loadedData);\n },\n });\n useReportPreviewPlaceholderRender(queryResult.data);\n\n return <>{children(queryResult.data)}</>;\n}\n\nexport function CollectionLoader({\n loaderKey,\n handle,\n collectionGid,\n language,\n children,\n fallback,\n}: CollectionLoaderProps) {\n const args = buildCollectionLoaderArgs({\n handle,\n collectionGid,\n language,\n });\n\n return (\n <LoaderErrorBoundary\n fallback={fallback ?? null}\n resetKey={`${loaderKey}:${JSON.stringify(args)}`}\n >\n <Suspense fallback={fallback ?? null}>\n <CollectionLoaderInner loaderKey={loaderKey} args={args}>\n {children}\n </CollectionLoaderInner>\n </Suspense>\n </LoaderErrorBoundary>\n );\n}\n"],
5
- "mappings": ";AA2CS;AArCT,SAAS,gBAAgB;AAEzB,SAAS,wBAAwB;AAEjC,SAAS,iCAAiC;AAC1C,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AACpC,SAAS,4BAA4B;AACrC,SAAS,yCAAyC;AAQlD,SAAS,sBAAsB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,cAAc,iBAAiB;AAAA,IACnC,UAAU,CAAC,WAAW,IAAI;AAAA,IAC1B,SAAS,YAAY;AACnB,YAAM,aAAa,MAAM,aAAa;AAAA,QACpC;AAAA,QACA;AAAA,MACF,CAAC;AACD,aAAO,qBAAqB,MAAM,UAAU;AAAA,IAC9C;AAAA,EACF,CAAC;AACD,oCAAkC,YAAY,IAAI;AAElD,SAAO,gCAAG,mBAAS,YAAY,IAAI,GAAE;AACvC;AAEO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0B;AACxB,QAAM,OAAO,0BAA0B;AAAA,IACrC;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU,YAAY;AAAA,MACtB,UAAU,GAAG,SAAS,IAAI,KAAK,UAAU,IAAI,CAAC;AAAA,MAE9C,8BAAC,YAAS,UAAU,YAAY,MAC9B,8BAAC,yBAAsB,WAAsB,MAC1C,UACH,GACF;AAAA;AAAA,EACF;AAEJ;",
4
+ "sourcesContent": ["\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport type { CollectionLoaderArgs } from \"./collection-loader-args\";\nimport type { FullCollection } from \"./loader-schemas\";\n\nimport { Suspense } from \"react\";\n\nimport { useSuspenseQuery } from \"@tanstack/react-query\";\n\nimport { buildCollectionLoaderArgs } from \"./collection-loader-args\";\nimport { invokeLoader } from \"./invoke-loader\";\nimport { LoaderErrorBoundary } from \"./loader-error-boundary\";\nimport { fullCollectionSchema } from \"./loader-schemas\";\nimport { useReportPreviewPlaceholderRender } from \"./preview-placeholder\";\n\ntype CollectionLoaderProps = CollectionLoaderArgs & {\n loaderKey: string;\n children: (data: FullCollection) => ReactNode;\n fallback?: ReactNode;\n};\n\nfunction CollectionLoaderInner({\n loaderKey,\n args,\n children,\n}: {\n loaderKey: string;\n args: CollectionLoaderArgs;\n children: (data: FullCollection) => ReactNode;\n}) {\n const queryResult = useSuspenseQuery({\n queryKey: [loaderKey, args],\n queryFn: async () => {\n const loadedData = await invokeLoader({\n loaderKey,\n args,\n });\n return fullCollectionSchema.parse(loadedData);\n },\n });\n useReportPreviewPlaceholderRender(queryResult.data);\n\n return <>{children(queryResult.data)}</>;\n}\n\nexport function CollectionLoader({\n loaderKey,\n handle,\n collectionGid,\n language,\n country,\n children,\n fallback,\n}: CollectionLoaderProps) {\n const args = buildCollectionLoaderArgs({\n handle,\n collectionGid,\n language,\n country,\n });\n\n return (\n <LoaderErrorBoundary\n fallback={fallback ?? null}\n resetKey={`${loaderKey}:${JSON.stringify(args)}`}\n >\n <Suspense fallback={fallback ?? null}>\n <CollectionLoaderInner loaderKey={loaderKey} args={args}>\n {children}\n </CollectionLoaderInner>\n </Suspense>\n </LoaderErrorBoundary>\n );\n}\n"],
5
+ "mappings": ";AA2CS;AArCT,SAAS,gBAAgB;AAEzB,SAAS,wBAAwB;AAEjC,SAAS,iCAAiC;AAC1C,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AACpC,SAAS,4BAA4B;AACrC,SAAS,yCAAyC;AAQlD,SAAS,sBAAsB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,cAAc,iBAAiB;AAAA,IACnC,UAAU,CAAC,WAAW,IAAI;AAAA,IAC1B,SAAS,YAAY;AACnB,YAAM,aAAa,MAAM,aAAa;AAAA,QACpC;AAAA,QACA;AAAA,MACF,CAAC;AACD,aAAO,qBAAqB,MAAM,UAAU;AAAA,IAC9C;AAAA,EACF,CAAC;AACD,oCAAkC,YAAY,IAAI;AAElD,SAAO,gCAAG,mBAAS,YAAY,IAAI,GAAE;AACvC;AAEO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0B;AACxB,QAAM,OAAO,0BAA0B;AAAA,IACrC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU,YAAY;AAAA,MACtB,UAAU,GAAG,SAAS,IAAI,KAAK,UAAU,IAAI,CAAC;AAAA,MAE9C,8BAAC,YAAS,UAAU,YAAY,MAC9B,8BAAC,yBAAsB,WAAsB,MAC1C,UACH,GACF;AAAA;AAAA,EACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -3,6 +3,7 @@ export type CollectionProductsLoaderArgs = {
3
3
  first?: number;
4
4
  after?: string;
5
5
  language?: string;
6
+ country?: string;
6
7
  };
7
8
  /**
8
9
  * Builds the single object used as BOTH the React Query key and the loader
@@ -13,4 +14,4 @@ export type CollectionProductsLoaderArgs = {
13
14
  * Keys left `undefined` drop out of React Query's key hash, so omitting a field
14
15
  * here hashes the same as a prefetch that never passed it.
15
16
  */
16
- export declare function buildCollectionProductsLoaderArgs({ collectionGid, first, after, language, }: CollectionProductsLoaderArgs): CollectionProductsLoaderArgs;
17
+ export declare function buildCollectionProductsLoaderArgs({ collectionGid, first, after, language, country, }: CollectionProductsLoaderArgs): CollectionProductsLoaderArgs;
@@ -2,13 +2,15 @@ function buildCollectionProductsLoaderArgs({
2
2
  collectionGid,
3
3
  first,
4
4
  after,
5
- language
5
+ language,
6
+ country
6
7
  }) {
7
8
  return {
8
9
  collectionGid,
9
10
  first,
10
11
  after,
11
- language
12
+ language,
13
+ country
12
14
  };
13
15
  }
14
16
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../loaders/collection-products-loader-args.ts"],
4
- "sourcesContent": ["export type CollectionProductsLoaderArgs = {\n collectionGid: string;\n first?: number;\n after?: string;\n language?: string;\n};\n\n/**\n * Builds the single object used as BOTH the React Query key and the loader\n * payload. They must stay identical: `PrefetchedLoaders` seeds the cache under\n * `[loaderKey, args]`, so an arg sent to the loader but missing from the key\n * (or vice versa) silently misses the prefetch.\n *\n * Keys left `undefined` drop out of React Query's key hash, so omitting a field\n * here hashes the same as a prefetch that never passed it.\n */\nexport function buildCollectionProductsLoaderArgs({\n collectionGid,\n first,\n after,\n language,\n}: CollectionProductsLoaderArgs): CollectionProductsLoaderArgs {\n return {\n collectionGid,\n first,\n after,\n language,\n };\n}\n"],
5
- "mappings": "AAgBO,SAAS,kCAAkC;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA+D;AAC7D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["export type CollectionProductsLoaderArgs = {\n collectionGid: string;\n first?: number;\n after?: string;\n language?: string;\n country?: string;\n};\n\n/**\n * Builds the single object used as BOTH the React Query key and the loader\n * payload. They must stay identical: `PrefetchedLoaders` seeds the cache under\n * `[loaderKey, args]`, so an arg sent to the loader but missing from the key\n * (or vice versa) silently misses the prefetch.\n *\n * Keys left `undefined` drop out of React Query's key hash, so omitting a field\n * here hashes the same as a prefetch that never passed it.\n */\nexport function buildCollectionProductsLoaderArgs({\n collectionGid,\n first,\n after,\n language,\n country,\n}: CollectionProductsLoaderArgs): CollectionProductsLoaderArgs {\n return {\n collectionGid,\n first,\n after,\n language,\n country,\n };\n}\n"],
5
+ "mappings": "AAiBO,SAAS,kCAAkC;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA+D;AAC7D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -6,5 +6,5 @@ type CollectionProductsLoaderProps = CollectionProductsLoaderArgs & {
6
6
  children: (data: PaginatedProducts) => ReactNode;
7
7
  fallback?: ReactNode;
8
8
  };
9
- export declare function CollectionProductsLoader({ loaderKey, collectionGid, first, after, language, children, fallback, }: CollectionProductsLoaderProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare function CollectionProductsLoader({ loaderKey, collectionGid, first, after, language, country, children, fallback, }: CollectionProductsLoaderProps): import("react/jsx-runtime").JSX.Element;
10
10
  export {};
@@ -31,6 +31,7 @@ function CollectionProductsLoader({
31
31
  first,
32
32
  after,
33
33
  language,
34
+ country,
34
35
  children,
35
36
  fallback
36
37
  }) {
@@ -38,7 +39,8 @@ function CollectionProductsLoader({
38
39
  collectionGid,
39
40
  first,
40
41
  after,
41
- language
42
+ language,
43
+ country
42
44
  });
43
45
  return /* @__PURE__ */ jsx(
44
46
  LoaderErrorBoundary,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../loaders/collection-products-loader.tsx"],
4
- "sourcesContent": ["\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport type { CollectionProductsLoaderArgs } from \"./collection-products-loader-args\";\nimport type { PaginatedProducts } from \"./loader-schemas\";\n\nimport { Suspense } from \"react\";\n\nimport { useSuspenseQuery } from \"@tanstack/react-query\";\n\nimport { buildCollectionProductsLoaderArgs } from \"./collection-products-loader-args\";\nimport { invokeLoader } from \"./invoke-loader\";\nimport { LoaderErrorBoundary } from \"./loader-error-boundary\";\nimport { paginatedProductsSchema } from \"./loader-schemas\";\nimport { useReportPreviewPlaceholderRender } from \"./preview-placeholder\";\n\ntype CollectionProductsLoaderProps = CollectionProductsLoaderArgs & {\n loaderKey: string;\n children: (data: PaginatedProducts) => ReactNode;\n fallback?: ReactNode;\n};\n\nfunction CollectionProductsLoaderInner({\n loaderKey,\n args,\n children,\n}: {\n loaderKey: string;\n args: CollectionProductsLoaderArgs;\n children: (data: PaginatedProducts) => ReactNode;\n}) {\n const queryResult = useSuspenseQuery({\n queryKey: [loaderKey, args],\n queryFn: async () => {\n const loadedData = await invokeLoader({\n loaderKey,\n args,\n });\n return paginatedProductsSchema.parse(loadedData);\n },\n });\n useReportPreviewPlaceholderRender(queryResult.data);\n\n return <>{children(queryResult.data)}</>;\n}\n\nexport function CollectionProductsLoader({\n loaderKey,\n collectionGid,\n first,\n after,\n language,\n children,\n fallback,\n}: CollectionProductsLoaderProps) {\n const args = buildCollectionProductsLoaderArgs({\n collectionGid,\n first,\n after,\n language,\n });\n\n return (\n <LoaderErrorBoundary\n fallback={fallback ?? null}\n resetKey={`${loaderKey}:${JSON.stringify(args)}`}\n >\n <Suspense fallback={fallback ?? null}>\n <CollectionProductsLoaderInner loaderKey={loaderKey} args={args}>\n {children}\n </CollectionProductsLoaderInner>\n </Suspense>\n </LoaderErrorBoundary>\n );\n}\n"],
5
- "mappings": ";AA2CS;AArCT,SAAS,gBAAgB;AAEzB,SAAS,wBAAwB;AAEjC,SAAS,yCAAyC;AAClD,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AACpC,SAAS,+BAA+B;AACxC,SAAS,yCAAyC;AAQlD,SAAS,8BAA8B;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,cAAc,iBAAiB;AAAA,IACnC,UAAU,CAAC,WAAW,IAAI;AAAA,IAC1B,SAAS,YAAY;AACnB,YAAM,aAAa,MAAM,aAAa;AAAA,QACpC;AAAA,QACA;AAAA,MACF,CAAC;AACD,aAAO,wBAAwB,MAAM,UAAU;AAAA,IACjD;AAAA,EACF,CAAC;AACD,oCAAkC,YAAY,IAAI;AAElD,SAAO,gCAAG,mBAAS,YAAY,IAAI,GAAE;AACvC;AAEO,SAAS,yBAAyB;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAkC;AAChC,QAAM,OAAO,kCAAkC;AAAA,IAC7C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU,YAAY;AAAA,MACtB,UAAU,GAAG,SAAS,IAAI,KAAK,UAAU,IAAI,CAAC;AAAA,MAE9C,8BAAC,YAAS,UAAU,YAAY,MAC9B,8BAAC,iCAA8B,WAAsB,MAClD,UACH,GACF;AAAA;AAAA,EACF;AAEJ;",
4
+ "sourcesContent": ["\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport type { CollectionProductsLoaderArgs } from \"./collection-products-loader-args\";\nimport type { PaginatedProducts } from \"./loader-schemas\";\n\nimport { Suspense } from \"react\";\n\nimport { useSuspenseQuery } from \"@tanstack/react-query\";\n\nimport { buildCollectionProductsLoaderArgs } from \"./collection-products-loader-args\";\nimport { invokeLoader } from \"./invoke-loader\";\nimport { LoaderErrorBoundary } from \"./loader-error-boundary\";\nimport { paginatedProductsSchema } from \"./loader-schemas\";\nimport { useReportPreviewPlaceholderRender } from \"./preview-placeholder\";\n\ntype CollectionProductsLoaderProps = CollectionProductsLoaderArgs & {\n loaderKey: string;\n children: (data: PaginatedProducts) => ReactNode;\n fallback?: ReactNode;\n};\n\nfunction CollectionProductsLoaderInner({\n loaderKey,\n args,\n children,\n}: {\n loaderKey: string;\n args: CollectionProductsLoaderArgs;\n children: (data: PaginatedProducts) => ReactNode;\n}) {\n const queryResult = useSuspenseQuery({\n queryKey: [loaderKey, args],\n queryFn: async () => {\n const loadedData = await invokeLoader({\n loaderKey,\n args,\n });\n return paginatedProductsSchema.parse(loadedData);\n },\n });\n useReportPreviewPlaceholderRender(queryResult.data);\n\n return <>{children(queryResult.data)}</>;\n}\n\nexport function CollectionProductsLoader({\n loaderKey,\n collectionGid,\n first,\n after,\n language,\n country,\n children,\n fallback,\n}: CollectionProductsLoaderProps) {\n const args = buildCollectionProductsLoaderArgs({\n collectionGid,\n first,\n after,\n language,\n country,\n });\n\n return (\n <LoaderErrorBoundary\n fallback={fallback ?? null}\n resetKey={`${loaderKey}:${JSON.stringify(args)}`}\n >\n <Suspense fallback={fallback ?? null}>\n <CollectionProductsLoaderInner loaderKey={loaderKey} args={args}>\n {children}\n </CollectionProductsLoaderInner>\n </Suspense>\n </LoaderErrorBoundary>\n );\n}\n"],
5
+ "mappings": ";AA2CS;AArCT,SAAS,gBAAgB;AAEzB,SAAS,wBAAwB;AAEjC,SAAS,yCAAyC;AAClD,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AACpC,SAAS,+BAA+B;AACxC,SAAS,yCAAyC;AAQlD,SAAS,8BAA8B;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,cAAc,iBAAiB;AAAA,IACnC,UAAU,CAAC,WAAW,IAAI;AAAA,IAC1B,SAAS,YAAY;AACnB,YAAM,aAAa,MAAM,aAAa;AAAA,QACpC;AAAA,QACA;AAAA,MACF,CAAC;AACD,aAAO,wBAAwB,MAAM,UAAU;AAAA,IACjD;AAAA,EACF,CAAC;AACD,oCAAkC,YAAY,IAAI;AAElD,SAAO,gCAAG,mBAAS,YAAY,IAAI,GAAE;AACvC;AAEO,SAAS,yBAAyB;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAkC;AAChC,QAAM,OAAO,kCAAkC;AAAA,IAC7C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU,YAAY;AAAA,MACtB,UAAU,GAAG,SAAS,IAAI,KAAK,UAAU,IAAI,CAAC;AAAA,MAE9C,8BAAC,YAAS,UAAU,YAAY,MAC9B,8BAAC,iCAA8B,WAAsB,MAClD,UACH,GACF;AAAA;AAAA,EACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -8,6 +8,7 @@ export type ProductLoaderArgs = {
8
8
  productMetafieldIdentifiers?: MetafieldIdentifier[];
9
9
  variantMetafieldIdentifiers?: MetafieldIdentifier[];
10
10
  language?: string;
11
+ country?: string;
11
12
  };
12
13
  /**
13
14
  * Builds the single object used as BOTH the React Query key and the loader
@@ -19,4 +20,4 @@ export type ProductLoaderArgs = {
19
20
  * Keys left `undefined` drop out of React Query's key hash, so omitting a field
20
21
  * here hashes the same as a prefetch that never passed it.
21
22
  */
22
- export declare function buildProductLoaderArgs({ handle, productId, productMetafieldIdentifiers, variantMetafieldIdentifiers, language, }: ProductLoaderArgs): ProductLoaderArgs;
23
+ export declare function buildProductLoaderArgs({ handle, productId, productMetafieldIdentifiers, variantMetafieldIdentifiers, language, country, }: ProductLoaderArgs): ProductLoaderArgs;
@@ -3,14 +3,16 @@ function buildProductLoaderArgs({
3
3
  productId,
4
4
  productMetafieldIdentifiers,
5
5
  variantMetafieldIdentifiers,
6
- language
6
+ language,
7
+ country
7
8
  }) {
8
9
  return {
9
10
  handle,
10
11
  productId,
11
12
  productMetafieldIdentifiers,
12
13
  variantMetafieldIdentifiers,
13
- language
14
+ language,
15
+ country
14
16
  };
15
17
  }
16
18
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../loaders/product-loader-args.ts"],
4
- "sourcesContent": ["export type MetafieldIdentifier = {\n namespace: string;\n key: string;\n};\n\nexport type ProductLoaderArgs = {\n handle?: string;\n productId?: string;\n productMetafieldIdentifiers?: MetafieldIdentifier[];\n variantMetafieldIdentifiers?: MetafieldIdentifier[];\n language?: string;\n};\n\n/**\n * Builds the single object used as BOTH the React Query key and the loader\n * payload. They must stay identical: `PrefetchedLoaders` seeds the cache under\n * `[loaderKey, args]`, so an arg sent to the loader but missing from the key\n * (or vice versa) silently misses the prefetch \u2014 the client refetches without\n * it and the page renders incomplete data instead of erroring.\n *\n * Keys left `undefined` drop out of React Query's key hash, so omitting a field\n * here hashes the same as a prefetch that never passed it.\n */\nexport function buildProductLoaderArgs({\n handle,\n productId,\n productMetafieldIdentifiers,\n variantMetafieldIdentifiers,\n language,\n}: ProductLoaderArgs): ProductLoaderArgs {\n return {\n handle,\n productId,\n productMetafieldIdentifiers,\n variantMetafieldIdentifiers,\n language,\n };\n}\n"],
5
- "mappings": "AAuBO,SAAS,uBAAuB;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAyC;AACvC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["export type MetafieldIdentifier = {\n namespace: string;\n key: string;\n};\n\nexport type ProductLoaderArgs = {\n handle?: string;\n productId?: string;\n productMetafieldIdentifiers?: MetafieldIdentifier[];\n variantMetafieldIdentifiers?: MetafieldIdentifier[];\n language?: string;\n country?: string;\n};\n\n/**\n * Builds the single object used as BOTH the React Query key and the loader\n * payload. They must stay identical: `PrefetchedLoaders` seeds the cache under\n * `[loaderKey, args]`, so an arg sent to the loader but missing from the key\n * (or vice versa) silently misses the prefetch \u2014 the client refetches without\n * it and the page renders incomplete data instead of erroring.\n *\n * Keys left `undefined` drop out of React Query's key hash, so omitting a field\n * here hashes the same as a prefetch that never passed it.\n */\nexport function buildProductLoaderArgs({\n handle,\n productId,\n productMetafieldIdentifiers,\n variantMetafieldIdentifiers,\n language,\n country,\n}: ProductLoaderArgs): ProductLoaderArgs {\n return {\n handle,\n productId,\n productMetafieldIdentifiers,\n variantMetafieldIdentifiers,\n language,\n country,\n };\n}\n"],
5
+ "mappings": "AAwBO,SAAS,uBAAuB;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAyC;AACvC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -7,5 +7,5 @@ type ProductLoaderProps = ProductLoaderArgs & {
7
7
  fallback?: ReactNode;
8
8
  loadingFallback?: ReactNode;
9
9
  };
10
- export declare function ProductLoader({ loaderKey, handle, productId, productMetafieldIdentifiers, variantMetafieldIdentifiers, language, children, fallback, loadingFallback, }: ProductLoaderProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare function ProductLoader({ loaderKey, handle, productId, productMetafieldIdentifiers, variantMetafieldIdentifiers, language, country, children, fallback, loadingFallback, }: ProductLoaderProps): import("react/jsx-runtime").JSX.Element;
11
11
  export {};
@@ -29,6 +29,7 @@ function ProductLoader({
29
29
  productMetafieldIdentifiers,
30
30
  variantMetafieldIdentifiers,
31
31
  language,
32
+ country,
32
33
  children,
33
34
  fallback,
34
35
  loadingFallback = fallback
@@ -38,7 +39,8 @@ function ProductLoader({
38
39
  productId,
39
40
  productMetafieldIdentifiers,
40
41
  variantMetafieldIdentifiers,
41
- language
42
+ language,
43
+ country
42
44
  });
43
45
  return /* @__PURE__ */ jsx(
44
46
  LoaderErrorBoundary,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../loaders/product-loader.tsx"],
4
- "sourcesContent": ["\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport type { FullProduct } from \"./loader-schemas\";\nimport type { ProductLoaderArgs } from \"./product-loader-args\";\n\nimport { Suspense } from \"react\";\n\nimport { useSuspenseQuery } from \"@tanstack/react-query\";\n\nimport { invokeLoader } from \"./invoke-loader\";\nimport { LoaderErrorBoundary } from \"./loader-error-boundary\";\nimport { fullProductSchema } from \"./loader-schemas\";\nimport { useReportPreviewPlaceholderRender } from \"./preview-placeholder\";\nimport { buildProductLoaderArgs } from \"./product-loader-args\";\n\ntype ProductLoaderProps = ProductLoaderArgs & {\n loaderKey: string;\n children: (data: FullProduct) => ReactNode;\n fallback?: ReactNode;\n loadingFallback?: ReactNode;\n};\n\nfunction ProductLoaderInner({\n loaderKey,\n args,\n children,\n}: {\n loaderKey: string;\n args: ProductLoaderArgs;\n children: (data: FullProduct) => ReactNode;\n}) {\n const queryResult = useSuspenseQuery({\n queryKey: [loaderKey, args],\n queryFn: async () => {\n const loadedData = await invokeLoader({ loaderKey, args });\n return fullProductSchema.parse(loadedData);\n },\n });\n useReportPreviewPlaceholderRender(queryResult.data);\n\n return <>{children(queryResult.data)}</>;\n}\n\nexport function ProductLoader({\n loaderKey,\n handle,\n productId,\n productMetafieldIdentifiers,\n variantMetafieldIdentifiers,\n language,\n children,\n fallback,\n loadingFallback = fallback,\n}: ProductLoaderProps) {\n const args = buildProductLoaderArgs({\n handle,\n productId,\n productMetafieldIdentifiers,\n variantMetafieldIdentifiers,\n language,\n });\n\n return (\n <LoaderErrorBoundary\n fallback={fallback ?? null}\n resetKey={`${loaderKey}:${JSON.stringify(args)}`}\n >\n <Suspense fallback={loadingFallback ?? null}>\n <ProductLoaderInner loaderKey={loaderKey} args={args}>\n {children}\n </ProductLoaderInner>\n </Suspense>\n </LoaderErrorBoundary>\n );\n}\n"],
5
- "mappings": ";AAyCS;AAnCT,SAAS,gBAAgB;AAEzB,SAAS,wBAAwB;AAEjC,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AACpC,SAAS,yBAAyB;AAClC,SAAS,yCAAyC;AAClD,SAAS,8BAA8B;AASvC,SAAS,mBAAmB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,cAAc,iBAAiB;AAAA,IACnC,UAAU,CAAC,WAAW,IAAI;AAAA,IAC1B,SAAS,YAAY;AACnB,YAAM,aAAa,MAAM,aAAa,EAAE,WAAW,KAAK,CAAC;AACzD,aAAO,kBAAkB,MAAM,UAAU;AAAA,IAC3C;AAAA,EACF,CAAC;AACD,oCAAkC,YAAY,IAAI;AAElD,SAAO,gCAAG,mBAAS,YAAY,IAAI,GAAE;AACvC;AAEO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAkB;AACpB,GAAuB;AACrB,QAAM,OAAO,uBAAuB;AAAA,IAClC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU,YAAY;AAAA,MACtB,UAAU,GAAG,SAAS,IAAI,KAAK,UAAU,IAAI,CAAC;AAAA,MAE9C,8BAAC,YAAS,UAAU,mBAAmB,MACrC,8BAAC,sBAAmB,WAAsB,MACvC,UACH,GACF;AAAA;AAAA,EACF;AAEJ;",
4
+ "sourcesContent": ["\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport type { FullProduct } from \"./loader-schemas\";\nimport type { ProductLoaderArgs } from \"./product-loader-args\";\n\nimport { Suspense } from \"react\";\n\nimport { useSuspenseQuery } from \"@tanstack/react-query\";\n\nimport { invokeLoader } from \"./invoke-loader\";\nimport { LoaderErrorBoundary } from \"./loader-error-boundary\";\nimport { fullProductSchema } from \"./loader-schemas\";\nimport { useReportPreviewPlaceholderRender } from \"./preview-placeholder\";\nimport { buildProductLoaderArgs } from \"./product-loader-args\";\n\ntype ProductLoaderProps = ProductLoaderArgs & {\n loaderKey: string;\n children: (data: FullProduct) => ReactNode;\n fallback?: ReactNode;\n loadingFallback?: ReactNode;\n};\n\nfunction ProductLoaderInner({\n loaderKey,\n args,\n children,\n}: {\n loaderKey: string;\n args: ProductLoaderArgs;\n children: (data: FullProduct) => ReactNode;\n}) {\n const queryResult = useSuspenseQuery({\n queryKey: [loaderKey, args],\n queryFn: async () => {\n const loadedData = await invokeLoader({ loaderKey, args });\n return fullProductSchema.parse(loadedData);\n },\n });\n useReportPreviewPlaceholderRender(queryResult.data);\n\n return <>{children(queryResult.data)}</>;\n}\n\nexport function ProductLoader({\n loaderKey,\n handle,\n productId,\n productMetafieldIdentifiers,\n variantMetafieldIdentifiers,\n language,\n country,\n children,\n fallback,\n loadingFallback = fallback,\n}: ProductLoaderProps) {\n const args = buildProductLoaderArgs({\n handle,\n productId,\n productMetafieldIdentifiers,\n variantMetafieldIdentifiers,\n language,\n country,\n });\n\n return (\n <LoaderErrorBoundary\n fallback={fallback ?? null}\n resetKey={`${loaderKey}:${JSON.stringify(args)}`}\n >\n <Suspense fallback={loadingFallback ?? null}>\n <ProductLoaderInner loaderKey={loaderKey} args={args}>\n {children}\n </ProductLoaderInner>\n </Suspense>\n </LoaderErrorBoundary>\n );\n}\n"],
5
+ "mappings": ";AAyCS;AAnCT,SAAS,gBAAgB;AAEzB,SAAS,wBAAwB;AAEjC,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AACpC,SAAS,yBAAyB;AAClC,SAAS,yCAAyC;AAClD,SAAS,8BAA8B;AASvC,SAAS,mBAAmB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,cAAc,iBAAiB;AAAA,IACnC,UAAU,CAAC,WAAW,IAAI;AAAA,IAC1B,SAAS,YAAY;AACnB,YAAM,aAAa,MAAM,aAAa,EAAE,WAAW,KAAK,CAAC;AACzD,aAAO,kBAAkB,MAAM,UAAU;AAAA,IAC3C;AAAA,EACF,CAAC;AACD,oCAAkC,YAAY,IAAI;AAElD,SAAO,gCAAG,mBAAS,YAAY,IAAI,GAAE;AACvC;AAEO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAkB;AACpB,GAAuB;AACrB,QAAM,OAAO,uBAAuB;AAAA,IAClC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU,YAAY;AAAA,MACtB,UAAU,GAAG,SAAS,IAAI,KAAK,UAAU,IAAI,CAAC;AAAA,MAE9C,8BAAC,YAAS,UAAU,mBAAmB,MACrC,8BAAC,sBAAmB,WAAsB,MACvC,UACH,GACF;AAAA;AAAA,EACF;AAEJ;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@replohq/sdk",
3
- "version": "1.3.2",
3
+ "version": "1.4.1",
4
4
  "reploBuild": {
5
5
  "packageName": "@replohq/sdk",
6
- "version": "1.3.2",
6
+ "version": "1.4.1",
7
7
  "branch": "HEAD",
8
- "commit": "a6ddf179a9377ee3c08389733ee7fc67a11ee3ec",
9
- "builtAt": "2026-09-08T07:18:18.884Z"
8
+ "commit": "1c91f9376d0e3d2c43e75b876a9c6a184969c874",
9
+ "builtAt": "2026-09-08T22:17:09.451Z"
10
10
  },
11
11
  "description": "Replo SDK — cart, analytics, and data loaders for agent-built Next.js sites.",
12
12
  "license": "SEE LICENSE IN LICENSE",