@kasuvia/sdk 0.0.2 → 0.0.5

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.
Files changed (77) hide show
  1. package/dist/hooks/index.d.mts +430 -0
  2. package/dist/hooks/index.d.ts +430 -0
  3. package/dist/hooks/index.js +3073 -0
  4. package/dist/hooks/index.js.map +1 -0
  5. package/dist/hooks/index.mjs +2962 -0
  6. package/dist/hooks/index.mjs.map +1 -0
  7. package/dist/index-CxNLI4nw.d.ts +786 -0
  8. package/dist/index-CzVMyUs4.d.mts +492 -0
  9. package/dist/index-CzVMyUs4.d.ts +492 -0
  10. package/dist/index-Dowl5224.d.mts +786 -0
  11. package/dist/index.d.mts +48 -1739
  12. package/dist/index.d.ts +48 -1739
  13. package/dist/index.js +1544 -2359
  14. package/dist/index.js.map +1 -1
  15. package/dist/index.mjs +1527 -2258
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/sdk-context-BuarJbeb.d.ts +75 -0
  18. package/dist/sdk-context-Db8kf1Tv.d.mts +75 -0
  19. package/dist/services/index.d.mts +2 -0
  20. package/dist/services/index.d.ts +2 -0
  21. package/dist/services/index.js +2369 -0
  22. package/dist/services/index.js.map +1 -0
  23. package/dist/services/index.mjs +2252 -0
  24. package/dist/services/index.mjs.map +1 -0
  25. package/package.json +11 -2
  26. package/src/config/index.ts +10 -91
  27. package/src/constants.ts +13 -0
  28. package/src/context/sdk-context.tsx +70 -0
  29. package/src/graphql/collections.graphql.ts +2 -10
  30. package/src/graphql/products.graphql.ts +215 -65
  31. package/src/graphql/wishlist.graphql.ts +7 -6
  32. package/src/hooks/index.ts +2 -0
  33. package/src/hooks/use-auth.ts +82 -158
  34. package/src/hooks/use-bespoke-availability.ts +25 -8
  35. package/src/hooks/use-cart.ts +222 -119
  36. package/src/hooks/use-cms.ts +179 -86
  37. package/src/hooks/use-collections.ts +52 -15
  38. package/src/hooks/use-consultation-stream.ts +4 -3
  39. package/src/hooks/use-consultations.ts +120 -51
  40. package/src/hooks/use-countries.ts +35 -13
  41. package/src/hooks/use-currencies.ts +26 -13
  42. package/src/hooks/use-google-translate.ts +22 -8
  43. package/src/hooks/use-languages.ts +40 -20
  44. package/src/hooks/use-mobile.ts +23 -0
  45. package/src/hooks/use-order-stream.ts +9 -5
  46. package/src/hooks/use-orders.ts +99 -44
  47. package/src/hooks/use-payment.ts +108 -40
  48. package/src/hooks/use-products.ts +251 -53
  49. package/src/hooks/use-service-booking.ts +152 -90
  50. package/src/hooks/use-states.ts +35 -15
  51. package/src/hooks/use-wishlist.ts +92 -91
  52. package/src/index.ts +26 -30
  53. package/src/services/auth.service.ts +209 -167
  54. package/src/services/bespoke.service.ts +12 -4
  55. package/src/services/cart.service.ts +172 -70
  56. package/src/services/cms.service.ts +70 -35
  57. package/src/services/collection.service.ts +22 -5
  58. package/src/services/config.service.ts +34 -14
  59. package/src/services/consultation.service.ts +72 -18
  60. package/src/services/logistics.service.ts +35 -11
  61. package/src/services/notifications.service.ts +27 -12
  62. package/src/services/order.service.ts +74 -15
  63. package/src/services/payment.service.ts +86 -31
  64. package/src/services/product.service.ts +279 -39
  65. package/src/services/service-booking.service.ts +98 -26
  66. package/src/services/wishlist.service.ts +69 -25
  67. package/src/types/auth/index.ts +6 -4
  68. package/src/types/business/index.ts +7 -2
  69. package/src/types/payments/index.ts +3 -3
  70. package/src/types/services/index.ts +2 -5
  71. package/src/types/store/index.ts +38 -3
  72. package/src/utils/error-handler.ts +10 -5
  73. package/src/utils/storage.ts +48 -26
  74. package/src/utils/validators.ts +85 -0
  75. package/src/client/authClient.ts +0 -135
  76. package/src/client/graphqlClient.ts +0 -53
  77. package/src/client/httpClient.ts +0 -298
@@ -0,0 +1,2962 @@
1
+ // src/hooks/use-cart.ts
2
+ import React2, { useContext as useContext2, useState } from "react";
3
+ import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
4
+
5
+ // src/services/cart.service.ts
6
+ function parseItems(items) {
7
+ return items.map((item) => ({
8
+ ...item,
9
+ variant_attributes: item.variant_attributes && typeof item.variant_attributes === "string" ? JSON.parse(item.variant_attributes) : item.variant_attributes
10
+ }));
11
+ }
12
+ async function getGuestCart(config, guestSessionId) {
13
+ if (!guestSessionId) return [];
14
+ try {
15
+ const response = await fetch(`${config.backendUrls.store}/cart/`, {
16
+ headers: {
17
+ "X-Storefront-Key": config.storefrontApiKey,
18
+ "X-Business-ID": config.businessId,
19
+ "X-Guest-Session": guestSessionId
20
+ }
21
+ });
22
+ if (!response.ok) return [];
23
+ const data = await response.json();
24
+ return parseItems(data.items || []);
25
+ } catch {
26
+ return [];
27
+ }
28
+ }
29
+ async function getCart(config, accessToken) {
30
+ if (!accessToken) {
31
+ return { id: "", items: [], subtotal: 0, total: 0, product_type: "physical" };
32
+ }
33
+ const response = await fetch(`${config.backendUrls.store}/cart/`, {
34
+ headers: {
35
+ "Authorization": `Bearer ${accessToken}`,
36
+ "X-Storefront-Key": config.storefrontApiKey,
37
+ "X-Business-ID": config.businessId
38
+ }
39
+ });
40
+ if (!response.ok) throw new Error("Failed to fetch cart");
41
+ const data = await response.json();
42
+ const parsedItems = parseItems(data.items || []);
43
+ return { ...data, items: parsedItems };
44
+ }
45
+ async function addToCart(config, accessToken, item) {
46
+ const response = await fetch(`${config.backendUrls.store}/cart/`, {
47
+ method: "POST",
48
+ headers: {
49
+ "Content-Type": "application/json",
50
+ "Authorization": `Bearer ${accessToken}`,
51
+ "X-Storefront-Key": config.storefrontApiKey,
52
+ "X-Business-ID": config.businessId
53
+ },
54
+ body: JSON.stringify(item)
55
+ });
56
+ if (!response.ok) throw new Error("Failed to add to cart");
57
+ const data = await response.json();
58
+ const parsedItems = parseItems(data.items || []);
59
+ return { ...data, items: parsedItems };
60
+ }
61
+ async function updateCartItem(config, accessToken, itemId, quantity) {
62
+ const response = await fetch(`${config.backendUrls.store}/cart/${itemId}`, {
63
+ method: "PATCH",
64
+ headers: {
65
+ "Content-Type": "application/json",
66
+ "Authorization": `Bearer ${accessToken}`,
67
+ "X-Storefront-Key": config.storefrontApiKey,
68
+ "X-Business-ID": config.businessId
69
+ },
70
+ body: JSON.stringify({ quantity })
71
+ });
72
+ if (!response.ok) throw new Error("Failed to update cart item");
73
+ const data = await response.json();
74
+ const parsedItems = parseItems(data.items || []);
75
+ return { ...data, items: parsedItems };
76
+ }
77
+ async function removeFromCart(config, accessToken, itemId) {
78
+ await fetch(`${config.backendUrls.store}/cart/${itemId}`, {
79
+ method: "DELETE",
80
+ headers: {
81
+ "Authorization": `Bearer ${accessToken}`,
82
+ "X-Storefront-Key": config.storefrontApiKey,
83
+ "X-Business-ID": config.businessId
84
+ }
85
+ });
86
+ return getCart(config, accessToken);
87
+ }
88
+ async function clearCart(config, accessToken) {
89
+ await fetch(`${config.backendUrls.store}/cart/clear`, {
90
+ method: "DELETE",
91
+ headers: {
92
+ "Authorization": `Bearer ${accessToken}`,
93
+ "X-Storefront-Key": config.storefrontApiKey,
94
+ "X-Business-ID": config.businessId
95
+ }
96
+ });
97
+ }
98
+ async function mergeGuestCart(config, accessToken, guestSessionId) {
99
+ const guestItems = guestSessionId ? await getGuestCart(config, guestSessionId) : [];
100
+ if (guestItems.length === 0) {
101
+ return getCart(config, accessToken);
102
+ }
103
+ const payloadItems = guestItems.map((item) => ({
104
+ product_id: item.product_id,
105
+ product_slug: item.product_slug,
106
+ product_name: item.product_name,
107
+ image: item.image,
108
+ variant_id: item.variant_id,
109
+ variant_attributes: typeof item.variant_attributes === "string" ? item.variant_attributes : JSON.stringify(item.variant_attributes ?? {}),
110
+ unit_price: item.unit_price,
111
+ quantity: item.quantity,
112
+ custom_measurements: typeof item.custom_measurements === "string" ? item.custom_measurements : JSON.stringify(item.custom_measurements ?? {}),
113
+ is_bespoke: item.is_bespoke
114
+ }));
115
+ const headers = {
116
+ "Content-Type": "application/json",
117
+ "Authorization": `Bearer ${accessToken}`,
118
+ "X-Storefront-Key": config.storefrontApiKey,
119
+ "X-Business-ID": config.businessId
120
+ };
121
+ if (guestSessionId) {
122
+ headers["X-Guest-Session"] = guestSessionId;
123
+ }
124
+ const response = await fetch(`${config.backendUrls.store}/cart/merge`, {
125
+ method: "POST",
126
+ headers,
127
+ body: JSON.stringify({ items: payloadItems })
128
+ });
129
+ if (!response.ok) throw new Error("Failed to merge guest cart");
130
+ const data = await response.json();
131
+ return { ...data, items: parseItems(data.items || []) };
132
+ }
133
+ async function mergeGuestCartIfPresent(config, accessToken, guestSessionId) {
134
+ try {
135
+ const guestItems = await getGuestCart(config, guestSessionId);
136
+ if (guestItems.length === 0) return;
137
+ await mergeGuestCart(config, accessToken, guestSessionId);
138
+ } catch (error) {
139
+ console.warn("[Cart] Failed to merge guest cart:", error);
140
+ }
141
+ }
142
+
143
+ // src/context/sdk-context.tsx
144
+ import { createContext, useContext } from "react";
145
+ import { jsx } from "react/jsx-runtime";
146
+ var SdkContext = createContext(null);
147
+ function SdkProvider({ config, accessToken, children }) {
148
+ return /* @__PURE__ */ jsx(SdkContext.Provider, { value: { config, accessToken }, children });
149
+ }
150
+ function useSdkContext() {
151
+ return useContext(SdkContext);
152
+ }
153
+ function resolveHookArgs(explicitConfig, explicitToken, ctx) {
154
+ const config = explicitConfig ?? ctx?.config;
155
+ if (!config) {
156
+ throw new Error(
157
+ "[kasuvia-sdk] No SdkConfig found. Either pass config explicitly or wrap your app with <SdkProvider config={...}>."
158
+ );
159
+ }
160
+ const accessToken = explicitToken !== void 0 ? explicitToken : ctx?.accessToken ?? null;
161
+ return { config, accessToken };
162
+ }
163
+
164
+ // src/hooks/use-cart.ts
165
+ var CartCtx = React2.createContext ? React2.createContext(null) : null;
166
+ function CartProvider({ children }) {
167
+ const [isOpen, setIsOpen] = useState(false);
168
+ if (!CartCtx) return children;
169
+ return React2.createElement(CartCtx.Provider, { value: { isOpen, setOpen: setIsOpen } }, children);
170
+ }
171
+ function useCart(config, accessToken) {
172
+ const ctx = useSdkContext();
173
+ try {
174
+ const resolved = resolveHookArgs(config, accessToken, ctx);
175
+ const resolvedConfig = resolved.config;
176
+ const resolvedToken = resolved.accessToken;
177
+ const queryClient = useQueryClient();
178
+ const context = CartCtx ? useContext2(CartCtx) : null;
179
+ const isOpen = context ? context.isOpen : false;
180
+ const setOpen = context ? context.setOpen : () => {
181
+ };
182
+ const [productTypeMismatch, setProductTypeMismatch] = useState(null);
183
+ const cartQuery = useQuery({
184
+ queryKey: ["cart"],
185
+ queryFn: async () => {
186
+ if (resolvedToken) {
187
+ return getCart(resolvedConfig, resolvedToken);
188
+ }
189
+ if (typeof window !== "undefined") {
190
+ const res = await fetch("/api/cart", { credentials: "include" });
191
+ if (!res.ok) throw new Error("Failed to fetch cart");
192
+ return res.json();
193
+ }
194
+ return void 0;
195
+ },
196
+ enabled: true
197
+ });
198
+ const addToCartMutation = useMutation({
199
+ mutationFn: async (item) => {
200
+ if (resolvedToken) {
201
+ return addToCart(resolvedConfig, resolvedToken, item);
202
+ }
203
+ if (typeof window !== "undefined") {
204
+ const res = await fetch("/api/cart", {
205
+ method: "POST",
206
+ headers: { "Content-Type": "application/json" },
207
+ credentials: "include",
208
+ body: JSON.stringify(item)
209
+ });
210
+ if (!res.ok) {
211
+ const data = await res.json().catch(() => ({}));
212
+ throw { status: res.status, data };
213
+ }
214
+ return res.json();
215
+ }
216
+ throw new Error("No access token and not in browser context");
217
+ },
218
+ onSuccess: () => {
219
+ setProductTypeMismatch(null);
220
+ queryClient.invalidateQueries({ queryKey: ["cart"] });
221
+ },
222
+ onError: (error) => {
223
+ const err = error;
224
+ if (err.status === 409 && err.data?.detail?.code === "CART_PRODUCT_TYPE_MISMATCH") {
225
+ const errorDetail = err.data.detail;
226
+ setProductTypeMismatch({
227
+ message: errorDetail.message ?? "Your cart contains incompatible items.",
228
+ existing_type: errorDetail.existing_type ?? "physical",
229
+ new_type: errorDetail.new_type ?? "physical"
230
+ });
231
+ }
232
+ }
233
+ });
234
+ const updateCartItemMutation = useMutation({
235
+ mutationFn: async ({ itemId, quantity }) => {
236
+ if (resolvedToken) {
237
+ return updateCartItem(resolvedConfig, resolvedToken, itemId, quantity);
238
+ }
239
+ if (typeof window !== "undefined") {
240
+ const res = await fetch(`/api/cart/${itemId}`, {
241
+ method: "PATCH",
242
+ headers: { "Content-Type": "application/json" },
243
+ credentials: "include",
244
+ body: JSON.stringify({ quantity })
245
+ });
246
+ if (!res.ok) throw new Error("Failed to update cart item");
247
+ return res.json();
248
+ }
249
+ throw new Error("No access token");
250
+ },
251
+ onSuccess: () => {
252
+ queryClient.invalidateQueries({ queryKey: ["cart"] });
253
+ }
254
+ });
255
+ const removeFromCartMutation = useMutation({
256
+ mutationFn: async (itemId) => {
257
+ if (resolvedToken) {
258
+ return removeFromCart(resolvedConfig, resolvedToken, itemId);
259
+ }
260
+ if (typeof window !== "undefined") {
261
+ const res = await fetch(`/api/cart/${itemId}`, {
262
+ method: "DELETE",
263
+ credentials: "include"
264
+ });
265
+ if (!res.ok) throw new Error("Failed to remove cart item");
266
+ return res.json();
267
+ }
268
+ throw new Error("No access token");
269
+ },
270
+ onSuccess: () => {
271
+ queryClient.invalidateQueries({ queryKey: ["cart"] });
272
+ }
273
+ });
274
+ const clearCartMutation = useMutation({
275
+ mutationFn: async () => {
276
+ if (resolvedToken) {
277
+ return clearCart(resolvedConfig, resolvedToken);
278
+ }
279
+ if (typeof window !== "undefined") {
280
+ const res = await fetch("/api/cart/clear", {
281
+ method: "DELETE",
282
+ credentials: "include"
283
+ });
284
+ if (!res.ok) throw new Error("Failed to clear cart");
285
+ return res.json();
286
+ }
287
+ throw new Error("No access token");
288
+ },
289
+ onSuccess: () => {
290
+ queryClient.invalidateQueries({ queryKey: ["cart"] });
291
+ }
292
+ });
293
+ const mergeGuestCartMutation = useMutation({
294
+ mutationFn: (guestSessionId) => resolvedToken ? mergeGuestCartIfPresent(resolvedConfig, resolvedToken, guestSessionId) : Promise.resolve(),
295
+ onSuccess: () => {
296
+ queryClient.invalidateQueries({ queryKey: ["cart"] });
297
+ }
298
+ });
299
+ const addItem = (product, variantId, quantity = 1, customMeasurements) => {
300
+ const variant = variantId ? product.variants.find((v) => v.id === variantId) : void 0;
301
+ return addToCartMutation.mutate({
302
+ product_id: product.id,
303
+ product_slug: product.slug,
304
+ product_name: product.name,
305
+ image: product.images[0] || void 0,
306
+ variant_id: variantId,
307
+ variant_attributes: variant?.attributes ? JSON.stringify(variant.attributes) : void 0,
308
+ unit_price: variant?.price ?? product.base_price,
309
+ quantity,
310
+ custom_measurements: customMeasurements ? JSON.stringify(customMeasurements) : void 0,
311
+ is_bespoke: product.is_bespoke
312
+ });
313
+ };
314
+ const items = cartQuery.data?.items || [];
315
+ const subtotal = cartQuery.data?.subtotal || 0;
316
+ const count = items.reduce((total, item) => total + item.quantity, 0);
317
+ const updateQty = (itemId, quantity) => {
318
+ updateCartItemMutation.mutate({ itemId, quantity });
319
+ };
320
+ const removeItem = (itemId) => {
321
+ removeFromCartMutation.mutate(itemId);
322
+ };
323
+ const handleClearCartAndAdd = () => {
324
+ clearCartMutation.mutate();
325
+ setProductTypeMismatch(null);
326
+ };
327
+ const handleKeepCurrentCart = () => {
328
+ setProductTypeMismatch(null);
329
+ };
330
+ return {
331
+ cart: cartQuery.data,
332
+ items,
333
+ count,
334
+ isOpen,
335
+ setOpen,
336
+ isLoading: cartQuery.isLoading,
337
+ error: cartQuery.error,
338
+ addToCart: addToCartMutation.mutate,
339
+ updateCartItem: updateCartItemMutation.mutate,
340
+ removeFromCart: removeFromCartMutation.mutate,
341
+ clearCart: clearCartMutation.mutate,
342
+ clear: clearCartMutation.mutate,
343
+ // Alias for storefront compatibility
344
+ mergeGuestCart: mergeGuestCartMutation.mutate,
345
+ addItem,
346
+ updateQty,
347
+ removeItem,
348
+ subtotal,
349
+ productTypeMismatch,
350
+ handleClearCartAndAdd,
351
+ handleKeepCurrentCart
352
+ };
353
+ } catch (error) {
354
+ console.warn("[useCart] Called outside QueryClientProvider, returning empty cart");
355
+ const context = CartCtx ? useContext2(CartCtx) : null;
356
+ const isOpen = context ? context.isOpen : false;
357
+ const setOpen = context ? context.setOpen : () => {
358
+ };
359
+ return {
360
+ cart: void 0,
361
+ items: [],
362
+ count: 0,
363
+ isOpen,
364
+ setOpen,
365
+ isLoading: false,
366
+ error: null,
367
+ addToCart: () => {
368
+ },
369
+ updateCartItem: () => {
370
+ },
371
+ removeFromCart: () => {
372
+ },
373
+ clearCart: () => {
374
+ },
375
+ clear: () => {
376
+ },
377
+ mergeGuestCart: () => {
378
+ },
379
+ addItem: () => {
380
+ },
381
+ updateQty: () => {
382
+ },
383
+ removeItem: () => {
384
+ },
385
+ subtotal: 0,
386
+ productTypeMismatch: null,
387
+ handleClearCartAndAdd: () => {
388
+ },
389
+ handleKeepCurrentCart: () => {
390
+ }
391
+ };
392
+ }
393
+ }
394
+
395
+ // src/hooks/use-orders.ts
396
+ import { useQuery as useQuery2, useMutation as useMutation2, useQueryClient as useQueryClient2 } from "@tanstack/react-query";
397
+
398
+ // src/services/order.service.ts
399
+ function deriveCustomerName(raw) {
400
+ if (raw.customer_name) return raw.customer_name;
401
+ if (raw.guest_name) return raw.guest_name;
402
+ const addr = typeof raw.shipping_address === "object" && raw.shipping_address !== null ? raw.shipping_address : null;
403
+ if (addr) {
404
+ const full = `${addr.first_name ?? ""} ${addr.last_name ?? ""}`.trim();
405
+ if (full) return full;
406
+ }
407
+ const email = raw.guest_email ?? raw.customer_email ?? "";
408
+ if (email) return email.split("@")[0];
409
+ return "";
410
+ }
411
+ function normaliseStorefrontOrder(raw) {
412
+ const items = (raw.items ?? []).map((item) => ({
413
+ id: item.id,
414
+ productName: item.product_name ?? item.productName ?? "",
415
+ image: item.image ?? "",
416
+ quantity: item.quantity ?? 1,
417
+ price: item.unit_price ?? item.price ?? 0
418
+ }));
419
+ const addr = typeof raw.shipping_address === "object" && raw.shipping_address !== null ? raw.shipping_address : null;
420
+ return {
421
+ id: raw.id,
422
+ display_id: raw.display_id,
423
+ items,
424
+ total: raw.total_amount ?? raw.total ?? 0,
425
+ status: raw.status,
426
+ customerEmail: raw.guest_email ?? raw.customer_email ?? "",
427
+ customerName: deriveCustomerName(raw),
428
+ createdAt: raw.created_at ? new Date(raw.created_at).getTime() : Date.now(),
429
+ updatedAt: raw.updated_at ? new Date(raw.updated_at).getTime() : Date.now(),
430
+ deliveryMethod: raw.delivery_method,
431
+ trackingNumber: raw.tracking_number,
432
+ deliveryAddress: typeof raw.shipping_address === "string" ? raw.shipping_address : addr ? `${addr.street}, ${addr.city}, ${addr.state}, ${addr.country}` : void 0,
433
+ shippingAddress: addr ? {
434
+ first_name: addr.first_name ?? "",
435
+ last_name: addr.last_name ?? "",
436
+ phone: addr.phone ?? "",
437
+ street: addr.street ?? "",
438
+ city: addr.city ?? "",
439
+ state: addr.state ?? "",
440
+ lga: addr.lga ?? "",
441
+ country: addr.country ?? "",
442
+ postal: addr.postal ?? ""
443
+ } : void 0,
444
+ cancellationReason: raw.cancellation_reason,
445
+ hasBespoke: raw.product_type === "bespoke",
446
+ bespokeStage: raw.bespoke_stage,
447
+ bespokeBrief: raw.bespoke_brief,
448
+ deliveryStatus: raw.delivery_status,
449
+ carrierName: raw.carrier_name,
450
+ terminalShipmentId: raw.terminal_shipment_id,
451
+ guestToken: raw.guest_token,
452
+ guestEmail: raw.guest_email,
453
+ guestPhone: raw.guest_phone,
454
+ guestName: raw.guest_name
455
+ };
456
+ }
457
+ async function createOrder(config, accessToken, payload) {
458
+ const response = await fetch(`${config.backendUrls.store}/orders/storefront`, {
459
+ method: "POST",
460
+ headers: {
461
+ "Content-Type": "application/json",
462
+ "Authorization": `Bearer ${accessToken}`,
463
+ "X-Storefront-Key": config.storefrontApiKey,
464
+ "X-Business-ID": config.businessId
465
+ },
466
+ body: JSON.stringify(payload)
467
+ });
468
+ if (!response.ok) throw new Error("Failed to create order");
469
+ const data = await response.json();
470
+ return normaliseStorefrontOrder(data);
471
+ }
472
+ async function findOrder(config, params) {
473
+ const queryParams = new URLSearchParams();
474
+ if (params.email) queryParams.set("email", params.email);
475
+ if (params.order_id) queryParams.set("order_id", params.order_id);
476
+ if (params.guest_token) queryParams.set("guest_token", params.guest_token);
477
+ const response = await fetch(`${config.backendUrls.store}/orders/find/?${queryParams.toString()}`, {
478
+ headers: {
479
+ "X-Storefront-Key": config.storefrontApiKey,
480
+ "X-Business-ID": config.businessId
481
+ }
482
+ });
483
+ if (!response.ok) throw new Error("Failed to find order");
484
+ const data = await response.json();
485
+ return normaliseStorefrontOrder(data);
486
+ }
487
+ async function getOrders(config, accessToken, params) {
488
+ const queryParams = new URLSearchParams();
489
+ if (params?.email) queryParams.set("email", params.email);
490
+ if (params?.page) queryParams.set("page", params.page.toString());
491
+ if (params?.page_size) queryParams.set("page_size", params.page_size.toString());
492
+ const response = await fetch(`${config.backendUrls.store}/orders/?${queryParams.toString()}`, {
493
+ headers: {
494
+ "Authorization": `Bearer ${accessToken}`,
495
+ "X-Storefront-Key": config.storefrontApiKey,
496
+ "X-Business-ID": config.businessId
497
+ }
498
+ });
499
+ if (!response.ok) throw new Error("Failed to get orders");
500
+ const data = await response.json();
501
+ const items = Array.isArray(data) ? data : data.items ?? [];
502
+ return items.map(normaliseStorefrontOrder);
503
+ }
504
+ async function cancelOrder(config, accessToken, orderId, reason) {
505
+ const response = await fetch(`${config.backendUrls.store}/orders/${orderId}/cancel/`, {
506
+ method: "POST",
507
+ headers: {
508
+ "Content-Type": "application/json",
509
+ "Authorization": `Bearer ${accessToken}`,
510
+ "X-Storefront-Key": config.storefrontApiKey,
511
+ "X-Business-ID": config.businessId
512
+ },
513
+ body: JSON.stringify({ reason })
514
+ });
515
+ if (!response.ok) throw new Error("Failed to cancel order");
516
+ const data = await response.json();
517
+ return normaliseStorefrontOrder(data);
518
+ }
519
+ async function trackOrder(config, orderId, token) {
520
+ const queryParams = token ? `?token=${token}` : "";
521
+ const response = await fetch(`${config.backendUrls.store}/orders/track/${orderId}${queryParams}`, {
522
+ headers: {
523
+ "X-Storefront-Key": config.storefrontApiKey,
524
+ "X-Business-ID": config.businessId
525
+ }
526
+ });
527
+ if (!response.ok) throw new Error("Failed to track order");
528
+ const data = await response.json();
529
+ return normaliseStorefrontOrder(data);
530
+ }
531
+
532
+ // src/utils/cache.ts
533
+ var CACHE_TIERS = {
534
+ none: { staleTime: 0, gcTime: 0 },
535
+ infinity: { staleTime: Infinity, gcTime: 0 },
536
+ low: { staleTime: 1e3 * 30, gcTime: 1e3 * 60 },
537
+ // 30s / 1m
538
+ medium: { staleTime: 1e3 * 60 * 5, gcTime: 1e3 * 60 * 10 },
539
+ // 5m / 10m
540
+ high: { staleTime: 1e3 * 60 * 30, gcTime: 1e3 * 60 * 60 }
541
+ // 30m / 1h
542
+ };
543
+ var isDevelopment = true;
544
+ var getCacheTier = (tier) => {
545
+ if (isDevelopment) return CACHE_TIERS.none;
546
+ return CACHE_TIERS[tier];
547
+ };
548
+
549
+ // src/utils/logger.ts
550
+ var isDevelopment2 = true;
551
+ var logger = {
552
+ log: (...args) => {
553
+ if (isDevelopment2) {
554
+ console.log(...args);
555
+ }
556
+ },
557
+ warn: (...args) => {
558
+ if (isDevelopment2) {
559
+ console.warn(...args);
560
+ }
561
+ },
562
+ /**
563
+ * Logs a warning to the console in development only.
564
+ * Alias for warn() for Python logging compatibility.
565
+ * In production, this is a no-op.
566
+ */
567
+ warning: (...args) => {
568
+ if (isDevelopment2) {
569
+ console.warn(...args);
570
+ }
571
+ },
572
+ error: (...args) => {
573
+ if (isDevelopment2) {
574
+ console.error(...args);
575
+ }
576
+ },
577
+ info: (...args) => {
578
+ if (isDevelopment2) {
579
+ console.info(...args);
580
+ }
581
+ },
582
+ createScope: (scope) => ({
583
+ log: (...args) => {
584
+ if (isDevelopment2) {
585
+ console.log(`[${scope}]`, ...args);
586
+ }
587
+ },
588
+ warn: (...args) => {
589
+ if (isDevelopment2) {
590
+ console.warn(`[${scope}]`, ...args);
591
+ }
592
+ },
593
+ warning: (...args) => {
594
+ if (isDevelopment2) {
595
+ console.warn(`[${scope}]`, ...args);
596
+ }
597
+ },
598
+ error: (...args) => {
599
+ if (isDevelopment2) {
600
+ console.error(`[${scope}]`, ...args);
601
+ }
602
+ },
603
+ info: (...args) => {
604
+ if (isDevelopment2) {
605
+ console.info(`[${scope}]`, ...args);
606
+ }
607
+ }
608
+ })
609
+ };
610
+
611
+ // src/hooks/use-orders.ts
612
+ function useOrders(arg1, arg2, arg3) {
613
+ const ctx = useSdkContext();
614
+ const isArg1Config = typeof arg1 === "object" && arg1 !== null && "businessId" in arg1;
615
+ const explicitConfig = isArg1Config ? arg1 : void 0;
616
+ const explicitToken = isArg1Config ? arg2 : void 0;
617
+ const params = isArg1Config ? arg3 : arg1;
618
+ try {
619
+ const { config: cfg, accessToken: token } = resolveHookArgs(explicitConfig, explicitToken, ctx);
620
+ return useQuery2({
621
+ queryKey: ["orders", params],
622
+ queryFn: () => token ? getOrders(cfg, token, params || {}) : Promise.resolve(void 0),
623
+ enabled: !!token
624
+ });
625
+ } catch (error) {
626
+ logger.warn("[useOrders] Called outside QueryClientProvider, returning empty list");
627
+ return { data: void 0, isLoading: false, error: null, isFetching: false, refetch: () => Promise.resolve({ data: void 0 }) };
628
+ }
629
+ }
630
+ function useOrdersList(arg1, arg2, arg3) {
631
+ return useOrders(arg1, arg2, arg3);
632
+ }
633
+ function useFindOrder(arg1, arg2) {
634
+ const ctx = useSdkContext();
635
+ const isArg1Config = typeof arg1 === "object" && arg1 !== null && "businessId" in arg1;
636
+ const explicitConfig = isArg1Config ? arg1 : void 0;
637
+ const params = isArg1Config ? arg2 : typeof arg1 === "string" ? { order_id: arg1, email: "" } : arg1;
638
+ try {
639
+ const { config: cfg } = resolveHookArgs(explicitConfig, void 0, ctx);
640
+ return useQuery2({
641
+ queryKey: ["order", params],
642
+ queryFn: () => params ? findOrder(cfg, params) : Promise.resolve(void 0),
643
+ enabled: !!params?.order_id
644
+ });
645
+ } catch (error) {
646
+ logger.warn("[useFindOrder] Called outside QueryClientProvider, returning undefined");
647
+ return { data: void 0, isLoading: false, error: null, isFetching: false, refetch: () => Promise.resolve({ data: void 0 }) };
648
+ }
649
+ }
650
+ function useOrder(arg1, arg2) {
651
+ return useFindOrder(arg1, arg2);
652
+ }
653
+ function useOrderTracking(arg1, arg2, arg3) {
654
+ const ctx = useSdkContext();
655
+ const isArg1Config = typeof arg1 === "object" && arg1 !== null && "businessId" in arg1;
656
+ const explicitConfig = isArg1Config ? arg1 : void 0;
657
+ const orderId = isArg1Config ? arg2 : typeof arg1 === "string" ? arg1 : void 0;
658
+ const guestToken = isArg1Config ? arg3 : typeof arg2 === "string" ? arg2 : void 0;
659
+ try {
660
+ const { config: cfg } = resolveHookArgs(explicitConfig, void 0, ctx);
661
+ return useQuery2({
662
+ queryKey: ["order-tracking", orderId, guestToken],
663
+ queryFn: () => trackOrder(cfg, orderId, guestToken),
664
+ enabled: !!orderId,
665
+ refetchInterval: 3e4
666
+ });
667
+ } catch (error) {
668
+ logger.warn("[useOrderTracking] Called outside QueryClientProvider, returning undefined");
669
+ return { data: void 0, isLoading: false, error: null, isFetching: false, refetch: () => Promise.resolve({ data: void 0 }) };
670
+ }
671
+ }
672
+ function useCreateOrder(config, accessToken) {
673
+ const ctx = useSdkContext();
674
+ try {
675
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx);
676
+ const queryClient = useQueryClient2();
677
+ return useMutation2({
678
+ mutationFn: (payload) => createOrder(cfg, token || "", payload),
679
+ onSuccess: () => {
680
+ queryClient.invalidateQueries({ queryKey: ["orders"] });
681
+ }
682
+ });
683
+ } catch (error) {
684
+ logger.warn("[useCreateOrder] Called outside QueryClientProvider, returning no-op mutation");
685
+ return { mutate: () => {
686
+ }, mutateAsync: () => Promise.resolve(void 0) };
687
+ }
688
+ }
689
+ function useCancelOrder(config, accessToken) {
690
+ const ctx = useSdkContext();
691
+ try {
692
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx);
693
+ const queryClient = useQueryClient2();
694
+ return useMutation2({
695
+ mutationFn: ({ orderId, reason = "" }) => token ? cancelOrder(cfg, token, orderId, reason) : Promise.reject("No access token"),
696
+ onSuccess: () => {
697
+ queryClient.invalidateQueries({ queryKey: ["orders"] });
698
+ }
699
+ });
700
+ } catch (error) {
701
+ logger.warn("[useCancelOrder] Called outside QueryClientProvider, returning no-op mutation");
702
+ return { mutate: () => {
703
+ }, mutateAsync: () => Promise.resolve(void 0) };
704
+ }
705
+ }
706
+
707
+ // src/hooks/use-auth.ts
708
+ import { useQuery as useQuery3, useMutation as useMutation3, useQueryClient as useQueryClient3 } from "@tanstack/react-query";
709
+
710
+ // src/services/auth.service.ts
711
+ async function loginCustomer(config, payload) {
712
+ const response = await fetch(`${config.backendUrls.auth}/auth/login/customer/`, {
713
+ method: "POST",
714
+ headers: {
715
+ "Content-Type": "application/json",
716
+ "X-Storefront-Key": config.storefrontApiKey,
717
+ "X-Business-ID": config.businessId
718
+ },
719
+ body: JSON.stringify({
720
+ ...payload,
721
+ tenant_id: config.businessId
722
+ })
723
+ });
724
+ if (!response.ok) {
725
+ throw new Error("Login failed");
726
+ }
727
+ const data = await response.json();
728
+ return data;
729
+ }
730
+ async function registerCustomer(config, payload) {
731
+ const response = await fetch(`${config.backendUrls.auth}/auth/register/customer/`, {
732
+ method: "POST",
733
+ headers: {
734
+ "Content-Type": "application/json",
735
+ "X-Storefront-Key": config.storefrontApiKey,
736
+ "X-Business-ID": config.businessId
737
+ },
738
+ body: JSON.stringify({
739
+ ...payload,
740
+ tenant_id: config.businessId
741
+ })
742
+ });
743
+ if (!response.ok) {
744
+ throw new Error("Registration failed");
745
+ }
746
+ const data = await response.json();
747
+ return data;
748
+ }
749
+ async function logout(config, refresh) {
750
+ const payload = refresh ? { refresh } : {};
751
+ try {
752
+ await fetch(`${config.backendUrls.auth}/auth/logout/`, {
753
+ method: "POST",
754
+ headers: {
755
+ "Content-Type": "application/json"
756
+ },
757
+ body: JSON.stringify(payload)
758
+ });
759
+ } catch {
760
+ }
761
+ }
762
+ function resolveProvider(data) {
763
+ if (data.is_google_auth_enabled) return "google";
764
+ if (data.is_facebook_auth_enabled) return "facebook";
765
+ return "email";
766
+ }
767
+ function resolveAvatar(profilePicture) {
768
+ if (!profilePicture) return null;
769
+ if (typeof profilePicture === "string") return profilePicture;
770
+ if (typeof profilePicture === "object" && profilePicture !== null && "url" in profilePicture) {
771
+ const url = profilePicture.url;
772
+ return typeof url === "string" ? url : null;
773
+ }
774
+ return null;
775
+ }
776
+ function mapAuthUserToCustomer(data, provider) {
777
+ const firstname = data.profile?.firstname?.trim() || void 0;
778
+ const lastname = data.profile?.lastname?.trim() || void 0;
779
+ const phone = data.profile?.phone?.trim() || void 0;
780
+ return {
781
+ id: String(data.id),
782
+ email: data.email,
783
+ firstname,
784
+ lastname,
785
+ phone,
786
+ full_name: buildFullName2(firstname, lastname),
787
+ avatar: resolveAvatar(data.profile?.profile_picture),
788
+ provider: provider ?? resolveProvider(data)
789
+ };
790
+ }
791
+ async function getAuthUser(config, accessToken) {
792
+ if (!config || !accessToken) {
793
+ const response2 = await fetch("/api/auth/me", { credentials: "include" });
794
+ if (!response2.ok) throw new Error("Failed to fetch auth user");
795
+ const data2 = await response2.json();
796
+ return data2.user;
797
+ }
798
+ const response = await fetch(`${config.backendUrls.auth}/auth/profile/`, {
799
+ headers: {
800
+ "Authorization": `Bearer ${accessToken}`
801
+ }
802
+ });
803
+ if (!response.ok) {
804
+ throw new Error("Failed to fetch auth user");
805
+ }
806
+ const data = await response.json();
807
+ return data;
808
+ }
809
+ async function updateProfile(configOrPayload, accessTokenOrPayload, payloadParam) {
810
+ const isArg1Config = typeof configOrPayload === "object" && configOrPayload !== null && "businessId" in configOrPayload;
811
+ if (!isArg1Config) {
812
+ const payload2 = configOrPayload;
813
+ const response2 = await fetch("/api/auth/profile", {
814
+ method: "PUT",
815
+ headers: { "Content-Type": "application/json" },
816
+ credentials: "include",
817
+ body: JSON.stringify(payload2)
818
+ });
819
+ if (!response2.ok) throw new Error("Failed to update profile");
820
+ return response2.json();
821
+ }
822
+ const config = configOrPayload;
823
+ const accessToken = accessTokenOrPayload;
824
+ const payload = payloadParam;
825
+ const response = await fetch(`${config.backendUrls.auth}/auth/profile/`, {
826
+ method: "PUT",
827
+ headers: {
828
+ "Content-Type": "application/json",
829
+ "Authorization": `Bearer ${accessToken}`
830
+ },
831
+ body: JSON.stringify(payload)
832
+ });
833
+ if (!response.ok) {
834
+ throw new Error("Failed to update profile");
835
+ }
836
+ const data = await response.json();
837
+ return mapAuthUserToCustomer(data);
838
+ }
839
+ function buildFullName2(firstname, lastname) {
840
+ if (firstname && lastname) return `${firstname} ${lastname}`;
841
+ return firstname || lastname || "";
842
+ }
843
+
844
+ // src/hooks/use-auth.ts
845
+ function useAuthUser(config, accessToken) {
846
+ const ctx = useSdkContext();
847
+ try {
848
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken ?? null, ctx);
849
+ return useQuery3({
850
+ queryKey: ["auth-user"],
851
+ queryFn: () => getAuthUser(cfg, token ?? ""),
852
+ enabled: !!token
853
+ });
854
+ } catch (error) {
855
+ logger.warn("[useAuthUser] Called outside QueryClientProvider, returning empty user");
856
+ return { data: void 0, isLoading: false, error: null, isFetching: false, refetch: () => Promise.resolve({ data: void 0 }) };
857
+ }
858
+ }
859
+ function useLogin(config) {
860
+ const ctx = useSdkContext();
861
+ try {
862
+ const { config: cfg } = resolveHookArgs(config, void 0, ctx);
863
+ const queryClient = useQueryClient3();
864
+ return useMutation3({
865
+ mutationFn: (payload) => loginCustomer(cfg, payload),
866
+ onSuccess: () => {
867
+ queryClient.invalidateQueries({ queryKey: ["auth-user"] });
868
+ queryClient.invalidateQueries({ queryKey: ["cart"] });
869
+ }
870
+ });
871
+ } catch (error) {
872
+ logger.warn("[useLogin] Called outside QueryClientProvider, returning no-op mutation");
873
+ return { mutate: () => {
874
+ }, mutateAsync: () => Promise.resolve(void 0) };
875
+ }
876
+ }
877
+ function useRegister(config) {
878
+ const ctx = useSdkContext();
879
+ try {
880
+ const { config: cfg } = resolveHookArgs(config, void 0, ctx);
881
+ const queryClient = useQueryClient3();
882
+ return useMutation3({
883
+ mutationFn: (payload) => registerCustomer(cfg, payload),
884
+ onSuccess: () => {
885
+ queryClient.invalidateQueries({ queryKey: ["auth-user"] });
886
+ queryClient.invalidateQueries({ queryKey: ["cart"] });
887
+ }
888
+ });
889
+ } catch (error) {
890
+ logger.warn("[useRegister] Called outside QueryClientProvider, returning no-op mutation");
891
+ return { mutate: () => {
892
+ }, mutateAsync: () => Promise.resolve(void 0) };
893
+ }
894
+ }
895
+ function useUpdateProfile(config, accessToken) {
896
+ const ctx = useSdkContext();
897
+ try {
898
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx);
899
+ const queryClient = useQueryClient3();
900
+ return useMutation3({
901
+ mutationFn: (payload) => token ? updateProfile(cfg, token, payload) : Promise.reject("No access token"),
902
+ onSuccess: () => {
903
+ queryClient.invalidateQueries({ queryKey: ["auth-user"] });
904
+ }
905
+ });
906
+ } catch (error) {
907
+ logger.warn("[useUpdateProfile] Called outside QueryClientProvider, returning no-op mutation");
908
+ return { mutate: () => {
909
+ }, mutateAsync: () => Promise.resolve(void 0) };
910
+ }
911
+ }
912
+ function useLogout(config, refreshToken) {
913
+ const ctx = useSdkContext();
914
+ try {
915
+ const { config: cfg } = resolveHookArgs(config, void 0, ctx);
916
+ const queryClient = useQueryClient3();
917
+ return useMutation3({
918
+ mutationFn: () => logout(cfg, refreshToken),
919
+ onSuccess: () => {
920
+ queryClient.clear();
921
+ }
922
+ });
923
+ } catch (error) {
924
+ logger.warn("[useLogout] Called outside QueryClientProvider, returning no-op mutation");
925
+ return { mutate: () => {
926
+ }, mutateAsync: () => Promise.resolve(void 0) };
927
+ }
928
+ }
929
+
930
+ // src/hooks/use-countries.ts
931
+ import { useQuery as useQuery4 } from "@tanstack/react-query";
932
+ async function getCountries(config) {
933
+ const response = await fetch(`${config.backendUrls.auth}/auth/countries/`, {
934
+ headers: {
935
+ "X-Storefront-Key": config.storefrontApiKey,
936
+ "X-Business-ID": config.businessId
937
+ }
938
+ });
939
+ if (!response.ok) throw new Error("Failed to fetch countries");
940
+ return response.json();
941
+ }
942
+ function useCountries(config) {
943
+ const ctx = useSdkContext();
944
+ try {
945
+ const { config: cfg } = resolveHookArgs(config, void 0, ctx);
946
+ return useQuery4({
947
+ queryKey: ["countries"],
948
+ queryFn: () => getCountries(cfg),
949
+ retry: 1,
950
+ refetchOnWindowFocus: false,
951
+ refetchOnReconnect: false,
952
+ staleTime: 24 * 60 * 60 * 1e3
953
+ });
954
+ } catch (error) {
955
+ logger.warn("[useCountries] Called outside QueryClientProvider, returning empty list");
956
+ return {
957
+ data: [],
958
+ isLoading: false,
959
+ error: null,
960
+ isFetching: false,
961
+ refetch: () => Promise.resolve({ data: [] })
962
+ };
963
+ }
964
+ }
965
+
966
+ // src/hooks/use-states.ts
967
+ import { useQuery as useQuery5 } from "@tanstack/react-query";
968
+ async function getStates(config, countryIso) {
969
+ if (!countryIso) return [];
970
+ const response = await fetch(`${config.backendUrls.auth}/auth/countries/?iso=${countryIso}`, {
971
+ headers: {
972
+ "X-Storefront-Key": config.storefrontApiKey,
973
+ "X-Business-ID": config.businessId
974
+ }
975
+ });
976
+ if (!response.ok) throw new Error("Failed to fetch states");
977
+ return response.json();
978
+ }
979
+ function useStates(countryIso, config) {
980
+ const ctx = useSdkContext();
981
+ try {
982
+ const { config: cfg } = resolveHookArgs(config, void 0, ctx);
983
+ return useQuery5({
984
+ queryKey: ["states", countryIso],
985
+ queryFn: () => getStates(cfg, countryIso),
986
+ enabled: !!countryIso,
987
+ retry: 1,
988
+ refetchOnWindowFocus: false,
989
+ refetchOnReconnect: false,
990
+ staleTime: 24 * 60 * 60 * 1e3
991
+ });
992
+ } catch (error) {
993
+ logger.warn("[useStates] Called outside QueryClientProvider, returning empty list");
994
+ return {
995
+ data: [],
996
+ isLoading: false,
997
+ error: null,
998
+ isFetching: false,
999
+ refetch: () => Promise.resolve({ data: [] })
1000
+ };
1001
+ }
1002
+ }
1003
+
1004
+ // src/hooks/use-languages.ts
1005
+ import { useQuery as useQuery6 } from "@tanstack/react-query";
1006
+
1007
+ // src/services/config.service.ts
1008
+ async function getSupportedLanguages(config) {
1009
+ const response = await fetch(`${config.backendUrls.payment}/config/supported-languages`, {
1010
+ headers: {
1011
+ "X-Storefront-Key": config.storefrontApiKey,
1012
+ "X-Business-ID": config.businessId
1013
+ }
1014
+ });
1015
+ if (!response.ok) throw new Error("Failed to get supported languages");
1016
+ return response.json();
1017
+ }
1018
+ async function getSupportedCurrencies(config) {
1019
+ const response = await fetch(`${config.backendUrls.payment}/config/supported-currencies`, {
1020
+ headers: {
1021
+ "X-Storefront-Key": config.storefrontApiKey,
1022
+ "X-Business-ID": config.businessId
1023
+ }
1024
+ });
1025
+ if (!response.ok) throw new Error("Failed to get supported currencies");
1026
+ return response.json();
1027
+ }
1028
+
1029
+ // src/hooks/use-languages.ts
1030
+ async function getSupportedLanguagesList(config) {
1031
+ const data = await getSupportedLanguages(config);
1032
+ return (data.languages || []).map((language) => ({
1033
+ code: language.code,
1034
+ appCode: language.code,
1035
+ label: language.label,
1036
+ native: language.label,
1037
+ flag: language.flag
1038
+ }));
1039
+ }
1040
+ function useSupportedLanguages(config) {
1041
+ const ctx = useSdkContext();
1042
+ try {
1043
+ const { config: cfg } = resolveHookArgs(config, void 0, ctx);
1044
+ return useQuery6({
1045
+ queryKey: ["supported-languages"],
1046
+ queryFn: () => getSupportedLanguagesList(cfg),
1047
+ retry: 1,
1048
+ ...getCacheTier("high")
1049
+ });
1050
+ } catch {
1051
+ return {
1052
+ data: [],
1053
+ isLoading: false,
1054
+ error: null,
1055
+ isFetching: false,
1056
+ isPending: false,
1057
+ isError: false,
1058
+ isSuccess: true,
1059
+ status: "success",
1060
+ fetchStatus: "idle",
1061
+ refetch: async () => ({
1062
+ data: [],
1063
+ isLoading: false,
1064
+ error: null,
1065
+ isFetching: false,
1066
+ isPending: false,
1067
+ isError: false,
1068
+ isSuccess: true,
1069
+ status: "success",
1070
+ fetchStatus: "idle"
1071
+ })
1072
+ };
1073
+ }
1074
+ }
1075
+
1076
+ // src/hooks/use-currencies.ts
1077
+ import { useQuery as useQuery7 } from "@tanstack/react-query";
1078
+ async function getSupportedCurrenciesList(config) {
1079
+ const data = await getSupportedCurrencies(config);
1080
+ return data.currencies || [];
1081
+ }
1082
+ function useCurrencies(config) {
1083
+ const ctx = useSdkContext();
1084
+ try {
1085
+ const { config: cfg } = resolveHookArgs(config, void 0, ctx);
1086
+ return useQuery7({
1087
+ queryKey: ["supported-currencies"],
1088
+ queryFn: () => getSupportedCurrenciesList(cfg),
1089
+ retry: 1,
1090
+ ...getCacheTier("high")
1091
+ });
1092
+ } catch (error) {
1093
+ logger.warn("[useCurrencies] Called outside QueryClientProvider, returning empty list");
1094
+ return {
1095
+ data: [],
1096
+ isLoading: false,
1097
+ error: null,
1098
+ isFetching: false,
1099
+ refetch: () => Promise.resolve({ data: [] })
1100
+ };
1101
+ }
1102
+ }
1103
+
1104
+ // src/hooks/use-bespoke-availability.ts
1105
+ import { useQuery as useQuery8 } from "@tanstack/react-query";
1106
+
1107
+ // src/services/bespoke.service.ts
1108
+ async function checkAvailability(config, product_id) {
1109
+ const response = await fetch(`${config.backendUrls.store}/bespoke/availability/${product_id}`, {
1110
+ headers: {
1111
+ "X-Storefront-Key": config.storefrontApiKey,
1112
+ "X-Business-ID": config.businessId
1113
+ }
1114
+ });
1115
+ if (!response.ok) throw new Error("Failed to check bespoke availability");
1116
+ return response.json();
1117
+ }
1118
+
1119
+ // src/hooks/use-bespoke-availability.ts
1120
+ function useBespokeAvailability(product_id, config) {
1121
+ const ctx = useSdkContext();
1122
+ try {
1123
+ const { config: cfg } = resolveHookArgs(config, void 0, ctx);
1124
+ return useQuery8({
1125
+ queryKey: ["bespoke-availability", product_id],
1126
+ queryFn: () => checkAvailability(cfg, product_id),
1127
+ enabled: !!product_id,
1128
+ retry: false
1129
+ });
1130
+ } catch (error) {
1131
+ logger.warn("[useBespokeAvailability] Called outside QueryClientProvider, returning undefined");
1132
+ return {
1133
+ data: void 0,
1134
+ isLoading: false,
1135
+ error: null,
1136
+ isFetching: false,
1137
+ refetch: () => Promise.resolve({ data: void 0 })
1138
+ };
1139
+ }
1140
+ }
1141
+
1142
+ // src/hooks/use-collections.ts
1143
+ import { useQuery as useQuery9 } from "@tanstack/react-query";
1144
+ var collectionKeys = {
1145
+ all: ["core", "collections"],
1146
+ list: (params) => ["core", "collections", "list", params ?? {}],
1147
+ slug: (slug) => ["core", "collections", "slug", slug]
1148
+ };
1149
+ function useStorefrontCollections(params) {
1150
+ try {
1151
+ const queryParams = new URLSearchParams();
1152
+ if (params?.page) queryParams.set("page", params.page.toString());
1153
+ if (params?.pageSize) queryParams.set("pageSize", params.pageSize.toString());
1154
+ return useQuery9({
1155
+ queryKey: collectionKeys.list(params),
1156
+ queryFn: async () => {
1157
+ const response = await fetch(`/api/collections?${queryParams.toString()}`);
1158
+ if (!response.ok) throw new Error("Failed to fetch collections");
1159
+ return response.json();
1160
+ },
1161
+ // medium — collections change infrequently
1162
+ ...getCacheTier("medium")
1163
+ });
1164
+ } catch (error) {
1165
+ logger.warn("[useStorefrontCollections] Called outside QueryClientProvider, returning empty list");
1166
+ return {
1167
+ data: void 0,
1168
+ isLoading: false,
1169
+ error: null,
1170
+ isFetching: false,
1171
+ refetch: () => Promise.resolve({ data: void 0 })
1172
+ };
1173
+ }
1174
+ }
1175
+ function useStorefrontCollection(slug) {
1176
+ try {
1177
+ return useQuery9({
1178
+ queryKey: collectionKeys.slug(slug),
1179
+ queryFn: async () => {
1180
+ const response = await fetch(`/api/collections/${slug}`);
1181
+ if (!response.ok) throw new Error("Failed to fetch collection");
1182
+ return response.json();
1183
+ },
1184
+ // medium — collection details change infrequently
1185
+ ...getCacheTier("medium"),
1186
+ enabled: !!slug
1187
+ });
1188
+ } catch (error) {
1189
+ logger.warn("[useStorefrontCollection] Called outside QueryClientProvider, returning undefined");
1190
+ return {
1191
+ data: void 0,
1192
+ isLoading: false,
1193
+ error: null,
1194
+ isFetching: false,
1195
+ refetch: () => Promise.resolve({ data: void 0 })
1196
+ };
1197
+ }
1198
+ }
1199
+
1200
+ // src/hooks/use-products.ts
1201
+ import { useQuery as useQuery10 } from "@tanstack/react-query";
1202
+ var productKeys = {
1203
+ all: ["products"],
1204
+ list: (params) => [...productKeys.all, "list", params],
1205
+ detail: (slug) => [...productKeys.all, "detail", slug],
1206
+ recommended: (params) => [...productKeys.all, "recommended", params],
1207
+ latest: (params) => [...productKeys.all, "latest", params],
1208
+ popular: (params) => [...productKeys.all, "popular", params],
1209
+ featured: (params) => [...productKeys.all, "featured", params],
1210
+ new: (params) => [...productKeys.all, "new", params],
1211
+ onSale: (params) => [...productKeys.all, "onSale", params],
1212
+ lowStock: (params) => [...productKeys.all, "lowStock", params]
1213
+ };
1214
+ function useLatestProducts(params) {
1215
+ try {
1216
+ const queryParams = new URLSearchParams();
1217
+ if (params?.page) queryParams.set("page", params.page.toString());
1218
+ if (params?.pageSize) queryParams.set("pageSize", params.pageSize.toString());
1219
+ return useQuery10({
1220
+ queryKey: productKeys.latest(params),
1221
+ queryFn: async () => {
1222
+ const response = await fetch(`/api/products/latest?${queryParams.toString()}`);
1223
+ if (!response.ok) throw new Error("Failed to fetch latest products");
1224
+ return response.json();
1225
+ },
1226
+ // medium — latest products change infrequently
1227
+ ...getCacheTier("medium")
1228
+ });
1229
+ } catch (error) {
1230
+ logger.warn("[useLatestProducts] Called outside QueryClientProvider, returning empty list");
1231
+ return {
1232
+ data: void 0,
1233
+ isLoading: false,
1234
+ error: null,
1235
+ isFetching: false,
1236
+ refetch: () => Promise.resolve({ data: void 0 })
1237
+ };
1238
+ }
1239
+ }
1240
+ function usePopularProducts(params) {
1241
+ try {
1242
+ const queryParams = new URLSearchParams();
1243
+ if (params?.page) queryParams.set("page", params.page.toString());
1244
+ if (params?.pageSize) queryParams.set("pageSize", params.pageSize.toString());
1245
+ return useQuery10({
1246
+ queryKey: productKeys.popular(params),
1247
+ queryFn: async () => {
1248
+ const response = await fetch(`/api/products/popular?${queryParams.toString()}`);
1249
+ if (!response.ok) throw new Error("Failed to fetch popular products");
1250
+ return response.json();
1251
+ },
1252
+ // medium — popular products change infrequently
1253
+ ...getCacheTier("medium")
1254
+ });
1255
+ } catch (error) {
1256
+ logger.warn("[usePopularProducts] Called outside QueryClientProvider, returning empty list");
1257
+ return {
1258
+ data: void 0,
1259
+ isLoading: false,
1260
+ error: null,
1261
+ isFetching: false,
1262
+ refetch: () => Promise.resolve({ data: void 0 })
1263
+ };
1264
+ }
1265
+ }
1266
+ function useFeaturedProducts(params) {
1267
+ try {
1268
+ const queryParams = new URLSearchParams();
1269
+ if (params?.page) queryParams.set("page", params.page.toString());
1270
+ if (params?.pageSize) queryParams.set("pageSize", params.pageSize.toString());
1271
+ return useQuery10({
1272
+ queryKey: productKeys.featured(params),
1273
+ queryFn: async () => {
1274
+ const response = await fetch(`/api/products/featured?${queryParams.toString()}`);
1275
+ if (!response.ok) throw new Error("Failed to fetch featured products");
1276
+ return response.json();
1277
+ },
1278
+ // medium — featured products change infrequently
1279
+ ...getCacheTier("medium")
1280
+ });
1281
+ } catch (error) {
1282
+ logger.warn("[useFeaturedProducts] Called outside QueryClientProvider, returning empty list");
1283
+ return {
1284
+ data: void 0,
1285
+ isLoading: false,
1286
+ error: null,
1287
+ isFetching: false,
1288
+ refetch: () => Promise.resolve({ data: void 0 })
1289
+ };
1290
+ }
1291
+ }
1292
+ function useNewProducts(params) {
1293
+ try {
1294
+ const queryParams = new URLSearchParams();
1295
+ if (params?.page) queryParams.set("page", params.page.toString());
1296
+ if (params?.pageSize) queryParams.set("pageSize", params.pageSize.toString());
1297
+ return useQuery10({
1298
+ queryKey: productKeys.new(params),
1299
+ queryFn: async () => {
1300
+ const response = await fetch(`/api/products/new?${queryParams.toString()}`);
1301
+ if (!response.ok) throw new Error("Failed to fetch new products");
1302
+ return response.json();
1303
+ },
1304
+ // medium — new products change infrequently
1305
+ ...getCacheTier("medium")
1306
+ });
1307
+ } catch (error) {
1308
+ logger.warn("[useNewProducts] Called outside QueryClientProvider, returning empty list");
1309
+ return {
1310
+ data: void 0,
1311
+ isLoading: false,
1312
+ error: null,
1313
+ isFetching: false,
1314
+ refetch: () => Promise.resolve({ data: void 0 })
1315
+ };
1316
+ }
1317
+ }
1318
+ function useOnSaleProducts(params) {
1319
+ try {
1320
+ const queryParams = new URLSearchParams();
1321
+ if (params?.page) queryParams.set("page", params.page.toString());
1322
+ if (params?.pageSize) queryParams.set("pageSize", params.pageSize.toString());
1323
+ return useQuery10({
1324
+ queryKey: productKeys.onSale(params),
1325
+ queryFn: async () => {
1326
+ const response = await fetch(`/api/products/on-sale?${queryParams.toString()}`);
1327
+ if (!response.ok) throw new Error("Failed to fetch on-sale products");
1328
+ return response.json();
1329
+ },
1330
+ // medium — sale products change infrequently
1331
+ ...getCacheTier("medium")
1332
+ });
1333
+ } catch (error) {
1334
+ logger.warn("[useOnSaleProducts] Called outside QueryClientProvider, returning empty list");
1335
+ return {
1336
+ data: void 0,
1337
+ isLoading: false,
1338
+ error: null,
1339
+ isFetching: false,
1340
+ refetch: () => Promise.resolve({ data: void 0 })
1341
+ };
1342
+ }
1343
+ }
1344
+ function useLowStockProducts(params) {
1345
+ try {
1346
+ const queryParams = new URLSearchParams();
1347
+ if (params?.page) queryParams.set("page", params.page.toString());
1348
+ if (params?.pageSize) queryParams.set("pageSize", params.pageSize.toString());
1349
+ return useQuery10({
1350
+ queryKey: productKeys.lowStock(params),
1351
+ queryFn: async () => {
1352
+ const response = await fetch(`/api/products/low-stock?${queryParams.toString()}`);
1353
+ if (!response.ok) throw new Error("Failed to fetch low-stock products");
1354
+ return response.json();
1355
+ },
1356
+ // low — low stock status changes frequently
1357
+ ...getCacheTier("low")
1358
+ });
1359
+ } catch (error) {
1360
+ logger.warn("[useLowStockProducts] Called outside QueryClientProvider, returning empty list");
1361
+ return {
1362
+ data: void 0,
1363
+ isLoading: false,
1364
+ error: null,
1365
+ isFetching: false,
1366
+ refetch: () => Promise.resolve({ data: void 0 })
1367
+ };
1368
+ }
1369
+ }
1370
+ function useStorefrontProducts(params) {
1371
+ try {
1372
+ const queryParams = new URLSearchParams();
1373
+ if (params?.page) queryParams.set("page", params.page.toString());
1374
+ if (params?.pageSize) queryParams.set("pageSize", params.pageSize.toString());
1375
+ if (params?.collectionSlug) queryParams.set("collectionSlug", params.collectionSlug);
1376
+ if (params?.search) queryParams.set("search", params.search);
1377
+ return useQuery10({
1378
+ queryKey: productKeys.list(params),
1379
+ queryFn: async () => {
1380
+ const response = await fetch(`/api/products?${queryParams.toString()}`);
1381
+ if (!response.ok) throw new Error("Failed to fetch products");
1382
+ return response.json();
1383
+ },
1384
+ // medium — product catalog changes infrequently
1385
+ ...getCacheTier("medium")
1386
+ });
1387
+ } catch (error) {
1388
+ logger.warn("[useStorefrontProducts] Called outside QueryClientProvider, returning empty list");
1389
+ return {
1390
+ data: void 0,
1391
+ isLoading: false,
1392
+ error: null,
1393
+ isFetching: false,
1394
+ refetch: () => Promise.resolve({ data: void 0 })
1395
+ };
1396
+ }
1397
+ }
1398
+ function useProduct(slug) {
1399
+ try {
1400
+ return useQuery10({
1401
+ queryKey: productKeys.detail(slug),
1402
+ queryFn: async () => {
1403
+ const response = await fetch(`/api/products/${slug}`);
1404
+ if (!response.ok) throw new Error("Failed to fetch product");
1405
+ return response.json();
1406
+ },
1407
+ // medium — product details change infrequently
1408
+ ...getCacheTier("medium"),
1409
+ enabled: !!slug
1410
+ });
1411
+ } catch (error) {
1412
+ logger.warn("[useProduct] Called outside QueryClientProvider, returning undefined");
1413
+ return {
1414
+ data: void 0,
1415
+ isLoading: false,
1416
+ error: null,
1417
+ isFetching: false,
1418
+ refetch: () => Promise.resolve({ data: void 0 })
1419
+ };
1420
+ }
1421
+ }
1422
+ function useRecommendedProducts(params) {
1423
+ try {
1424
+ const queryParams = new URLSearchParams();
1425
+ if (params?.page) queryParams.set("page", params.page.toString());
1426
+ if (params?.pageSize) queryParams.set("pageSize", params.pageSize.toString());
1427
+ if (params?.excludeProductId) queryParams.set("excludeProductId", params.excludeProductId);
1428
+ return useQuery10({
1429
+ queryKey: productKeys.recommended(params),
1430
+ queryFn: async () => {
1431
+ const response = await fetch(`/api/products/recommended?${queryParams.toString()}`);
1432
+ if (!response.ok) throw new Error("Failed to fetch recommended products");
1433
+ return response.json();
1434
+ },
1435
+ // medium — recommendations change infrequently
1436
+ ...getCacheTier("medium")
1437
+ });
1438
+ } catch (error) {
1439
+ logger.warn("[useRecommendedProducts] Called outside QueryClientProvider, returning empty list");
1440
+ return {
1441
+ data: void 0,
1442
+ isLoading: false,
1443
+ error: null,
1444
+ isFetching: false,
1445
+ refetch: () => Promise.resolve({ data: void 0 })
1446
+ };
1447
+ }
1448
+ }
1449
+
1450
+ // src/hooks/use-wishlist.ts
1451
+ import { useQuery as useQuery11, useMutation as useMutation4, useQueryClient as useQueryClient4 } from "@tanstack/react-query";
1452
+
1453
+ // src/services/wishlist.service.ts
1454
+ import { GraphQLClient } from "graphql-request";
1455
+ var GET_STOREFRONT_WISHLIST = `
1456
+ query GetStorefrontWishlist($page: Int!, $pageSize: Int!) {
1457
+ storefront_wishlist(page: $page, pageSize: $pageSize) {
1458
+ items {
1459
+ id
1460
+ product_id
1461
+ notes
1462
+ created_at
1463
+ product_name
1464
+ product_slug
1465
+ product_price
1466
+ currency
1467
+ product_image
1468
+ }
1469
+ total
1470
+ page
1471
+ page_size
1472
+ total_pages
1473
+ }
1474
+ }
1475
+ `;
1476
+ var CHECK_IN_STOREFRONT_WISHLIST = `
1477
+ query CheckInStorefrontWishlist($productId: String!) {
1478
+ check_in_storefront_wishlist(productId: $productId) {
1479
+ in_wishlist
1480
+ }
1481
+ }
1482
+ `;
1483
+ function createGraphQLClient(config, accessToken) {
1484
+ const headers = {
1485
+ "Content-Type": "application/json",
1486
+ "Accept": "application/json",
1487
+ "X-Storefront-Key": config.storefrontApiKey,
1488
+ "X-Business-ID": config.businessId
1489
+ };
1490
+ if (accessToken) {
1491
+ headers["Authorization"] = `Bearer ${accessToken}`;
1492
+ }
1493
+ return new GraphQLClient(`${config.backendUrls.store}/graphql`, { headers });
1494
+ }
1495
+ async function getWishlist(config, accessToken, params) {
1496
+ const client = createGraphQLClient(config, accessToken);
1497
+ const variables = {
1498
+ page: params?.page || 1,
1499
+ pageSize: params?.pageSize || 20
1500
+ };
1501
+ const data = await client.request(GET_STOREFRONT_WISHLIST, variables);
1502
+ return data.storefront_wishlist;
1503
+ }
1504
+ async function checkInWishlist(config, accessToken, productId) {
1505
+ const client = createGraphQLClient(config, accessToken);
1506
+ const data = await client.request(CHECK_IN_STOREFRONT_WISHLIST, { productId });
1507
+ return data.check_in_storefront_wishlist;
1508
+ }
1509
+ async function addToWishlist(config, accessToken, productId, notes) {
1510
+ const response = await fetch(`${config.backendUrls.store}/wishlist/`, {
1511
+ method: "POST",
1512
+ headers: {
1513
+ "Content-Type": "application/json",
1514
+ "Authorization": `Bearer ${accessToken}`,
1515
+ "X-Storefront-Key": config.storefrontApiKey,
1516
+ "X-Business-ID": config.businessId
1517
+ },
1518
+ body: JSON.stringify({
1519
+ product_id: productId,
1520
+ notes: notes || void 0
1521
+ })
1522
+ });
1523
+ if (!response.ok) throw new Error("Failed to add to wishlist");
1524
+ return response.json();
1525
+ }
1526
+ async function removeFromWishlist(config, accessToken, itemId) {
1527
+ const response = await fetch(`${config.backendUrls.store}/wishlist/${itemId}`, {
1528
+ method: "DELETE",
1529
+ headers: {
1530
+ "Authorization": `Bearer ${accessToken}`,
1531
+ "X-Storefront-Key": config.storefrontApiKey,
1532
+ "X-Business-ID": config.businessId
1533
+ }
1534
+ });
1535
+ if (!response.ok) throw new Error("Failed to remove from wishlist");
1536
+ }
1537
+ async function removeProductFromWishlist(config, accessToken, productId) {
1538
+ const response = await fetch(`${config.backendUrls.store}/wishlist/product/${productId}`, {
1539
+ method: "DELETE",
1540
+ headers: {
1541
+ "Authorization": `Bearer ${accessToken}`,
1542
+ "X-Storefront-Key": config.storefrontApiKey,
1543
+ "X-Business-ID": config.businessId
1544
+ }
1545
+ });
1546
+ if (!response.ok) throw new Error("Failed to remove product from wishlist");
1547
+ }
1548
+
1549
+ // src/hooks/use-wishlist.ts
1550
+ var wishlistKeys = {
1551
+ all: ["wishlist"],
1552
+ list: () => [...wishlistKeys.all, "list"],
1553
+ check: (productId) => [...wishlistKeys.all, "check", productId]
1554
+ };
1555
+ function useWishlist(arg1, arg2, arg3) {
1556
+ const ctx = useSdkContext();
1557
+ const isArg1Config = typeof arg1 === "object" && arg1 !== null && "businessId" in arg1;
1558
+ const explicitConfig = isArg1Config ? arg1 : void 0;
1559
+ const explicitToken = isArg1Config ? arg2 : void 0;
1560
+ const params = isArg1Config ? arg3 : arg1;
1561
+ try {
1562
+ const { config: cfg, accessToken: token } = resolveHookArgs(explicitConfig, explicitToken, ctx);
1563
+ return useQuery11({
1564
+ queryKey: [...wishlistKeys.list(), params],
1565
+ queryFn: () => token ? getWishlist(cfg, token, params) : Promise.resolve(void 0),
1566
+ enabled: !!token,
1567
+ ...getCacheTier("medium")
1568
+ });
1569
+ } catch (error) {
1570
+ console.warn("[useWishlist] Called outside QueryClientProvider, returning empty wishlist");
1571
+ return { data: void 0, isLoading: false, error: null, isFetching: false, refetch: () => Promise.resolve({ data: void 0 }) };
1572
+ }
1573
+ }
1574
+ function useCheckInWishlist(arg1, arg2, arg3) {
1575
+ const ctx = useSdkContext();
1576
+ const isArg1Config = typeof arg1 === "object" && arg1 !== null && "businessId" in arg1;
1577
+ const explicitConfig = isArg1Config ? arg1 : void 0;
1578
+ const explicitToken = isArg1Config ? arg2 : void 0;
1579
+ const productId = isArg1Config ? arg3 : typeof arg1 === "string" ? arg1 : void 0;
1580
+ try {
1581
+ const { config: cfg, accessToken: token } = resolveHookArgs(explicitConfig, explicitToken, ctx);
1582
+ return useQuery11({
1583
+ queryKey: wishlistKeys.check(productId ?? ""),
1584
+ queryFn: () => token && productId ? checkInWishlist(cfg, token, productId) : Promise.resolve({ in_wishlist: false }),
1585
+ ...getCacheTier("low"),
1586
+ enabled: !!productId && !!token
1587
+ });
1588
+ } catch (error) {
1589
+ console.warn("[useCheckInWishlist] Called outside QueryClientProvider, returning false");
1590
+ return { data: false, isLoading: false, error: null, isFetching: false, refetch: () => Promise.resolve({ data: false }) };
1591
+ }
1592
+ }
1593
+ function useAddToWishlist(config, accessToken) {
1594
+ const ctx = useSdkContext();
1595
+ try {
1596
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx);
1597
+ const queryClient = useQueryClient4();
1598
+ return useMutation4({
1599
+ mutationFn: ({ productId, notes }) => token ? addToWishlist(cfg, token, productId, notes) : Promise.reject("No access token"),
1600
+ onSuccess: () => {
1601
+ queryClient.invalidateQueries({ queryKey: wishlistKeys.all });
1602
+ queryClient.invalidateQueries({ queryKey: ["wishlist", "check"] });
1603
+ }
1604
+ });
1605
+ } catch (error) {
1606
+ console.warn("[useAddToWishlist] Called outside QueryClientProvider, returning no-op mutation");
1607
+ return { mutate: () => {
1608
+ }, mutateAsync: () => Promise.resolve(void 0) };
1609
+ }
1610
+ }
1611
+ function useRemoveFromWishlist(config, accessToken) {
1612
+ const ctx = useSdkContext();
1613
+ try {
1614
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx);
1615
+ const queryClient = useQueryClient4();
1616
+ return useMutation4({
1617
+ mutationFn: (itemId) => token ? removeFromWishlist(cfg, token, itemId) : Promise.reject("No access token"),
1618
+ onSuccess: () => {
1619
+ queryClient.invalidateQueries({ queryKey: wishlistKeys.all });
1620
+ queryClient.invalidateQueries({ queryKey: ["wishlist", "check"] });
1621
+ }
1622
+ });
1623
+ } catch (error) {
1624
+ console.warn("[useRemoveFromWishlist] Called outside QueryClientProvider, returning no-op mutation");
1625
+ return { mutate: () => {
1626
+ }, mutateAsync: () => Promise.resolve(void 0) };
1627
+ }
1628
+ }
1629
+ function useRemoveProductFromWishlist(config, accessToken) {
1630
+ const ctx = useSdkContext();
1631
+ try {
1632
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx);
1633
+ const queryClient = useQueryClient4();
1634
+ return useMutation4({
1635
+ mutationFn: (productId) => token ? removeProductFromWishlist(cfg, token, productId) : Promise.reject("No access token"),
1636
+ onSuccess: () => {
1637
+ queryClient.invalidateQueries({ queryKey: wishlistKeys.all });
1638
+ queryClient.invalidateQueries({ queryKey: ["wishlist", "check"] });
1639
+ }
1640
+ });
1641
+ } catch (error) {
1642
+ console.warn("[useRemoveProductFromWishlist] Called outside QueryClientProvider, returning no-op mutation");
1643
+ return { mutate: () => {
1644
+ }, mutateAsync: () => Promise.resolve(void 0) };
1645
+ }
1646
+ }
1647
+
1648
+ // src/hooks/use-service-booking.ts
1649
+ import { useQuery as useQuery12, useMutation as useMutation5, useQueryClient as useQueryClient5 } from "@tanstack/react-query";
1650
+
1651
+ // src/services/service-booking.service.ts
1652
+ async function getAvailableSlots(config, product_id, date_from, date_to) {
1653
+ const response = await fetch(
1654
+ `${config.backendUrls.store}/service/available-slots/${product_id}?date_from=${date_from}&date_to=${date_to}`,
1655
+ {
1656
+ headers: {
1657
+ "X-Storefront-Key": config.storefrontApiKey,
1658
+ "X-Business-ID": config.businessId
1659
+ }
1660
+ }
1661
+ );
1662
+ if (!response.ok) throw new Error("Failed to get available slots");
1663
+ return response.json();
1664
+ }
1665
+ async function bookAppointment(config, accessToken, payload) {
1666
+ const response = await fetch(`${config.backendUrls.store}/service/appointments/`, {
1667
+ method: "POST",
1668
+ headers: {
1669
+ "Content-Type": "application/json",
1670
+ "Authorization": `Bearer ${accessToken}`,
1671
+ "X-Storefront-Key": config.storefrontApiKey,
1672
+ "X-Business-ID": config.businessId
1673
+ },
1674
+ body: JSON.stringify(payload)
1675
+ });
1676
+ if (!response.ok) throw new Error("Failed to book appointment");
1677
+ return response.json();
1678
+ }
1679
+ async function getAppointments(config, accessToken) {
1680
+ const response = await fetch(`${config.backendUrls.store}/service/bookings/my`, {
1681
+ headers: {
1682
+ "Authorization": `Bearer ${accessToken}`,
1683
+ "X-Storefront-Key": config.storefrontApiKey,
1684
+ "X-Business-ID": config.businessId
1685
+ }
1686
+ });
1687
+ if (!response.ok) throw new Error("Failed to get appointments");
1688
+ return response.json();
1689
+ }
1690
+ async function getAppointment(config, accessToken, id) {
1691
+ const response = await fetch(`${config.backendUrls.store}/service/bookings/${id}`, {
1692
+ headers: {
1693
+ "Authorization": `Bearer ${accessToken}`,
1694
+ "X-Storefront-Key": config.storefrontApiKey,
1695
+ "X-Business-ID": config.businessId
1696
+ }
1697
+ });
1698
+ if (!response.ok) throw new Error("Failed to get appointment");
1699
+ return response.json();
1700
+ }
1701
+ async function cancelAppointment(config, accessToken, id) {
1702
+ await fetch(`${config.backendUrls.store}/service/bookings/${id}`, {
1703
+ method: "DELETE",
1704
+ headers: {
1705
+ "Authorization": `Bearer ${accessToken}`,
1706
+ "X-Storefront-Key": config.storefrontApiKey,
1707
+ "X-Business-ID": config.businessId
1708
+ }
1709
+ });
1710
+ }
1711
+ async function getDeliverables(config, accessToken, order_id) {
1712
+ const response = await fetch(`${config.backendUrls.store}/service/projects/${order_id}/deliverables/`, {
1713
+ headers: {
1714
+ "Authorization": `Bearer ${accessToken}`,
1715
+ "X-Storefront-Key": config.storefrontApiKey,
1716
+ "X-Business-ID": config.businessId
1717
+ }
1718
+ });
1719
+ if (!response.ok) throw new Error("Failed to get deliverables");
1720
+ return response.json();
1721
+ }
1722
+ async function approveDeliverable(config, accessToken, order_id, deliverable_id) {
1723
+ const response = await fetch(
1724
+ `${config.backendUrls.store}/service/projects/${order_id}/deliverables/${deliverable_id}/approve`,
1725
+ {
1726
+ method: "POST",
1727
+ headers: {
1728
+ "Content-Type": "application/json",
1729
+ "Authorization": `Bearer ${accessToken}`,
1730
+ "X-Storefront-Key": config.storefrontApiKey,
1731
+ "X-Business-ID": config.businessId
1732
+ },
1733
+ body: JSON.stringify({ approved: true })
1734
+ }
1735
+ );
1736
+ if (!response.ok) throw new Error("Failed to approve deliverable");
1737
+ return response.json();
1738
+ }
1739
+ async function requestRevision(config, accessToken, order_id, deliverable_id, feedback) {
1740
+ const response = await fetch(
1741
+ `${config.backendUrls.store}/service/projects/${order_id}/deliverables/${deliverable_id}/revision`,
1742
+ {
1743
+ method: "POST",
1744
+ headers: {
1745
+ "Content-Type": "application/json",
1746
+ "Authorization": `Bearer ${accessToken}`,
1747
+ "X-Storefront-Key": config.storefrontApiKey,
1748
+ "X-Business-ID": config.businessId
1749
+ },
1750
+ body: JSON.stringify({ approved: false, feedback })
1751
+ }
1752
+ );
1753
+ if (!response.ok) throw new Error("Failed to request revision");
1754
+ return response.json();
1755
+ }
1756
+
1757
+ // src/hooks/use-service-booking.ts
1758
+ function useAvailableSlots(arg1, arg2, arg3, arg4) {
1759
+ const ctx = useSdkContext();
1760
+ const isArg1Config = typeof arg1 === "object" && arg1 !== null && "businessId" in arg1;
1761
+ const explicitConfig = isArg1Config ? arg1 : void 0;
1762
+ const product_id = isArg1Config ? arg2 : typeof arg1 === "string" ? arg1 : void 0;
1763
+ const date_from = isArg1Config ? arg3 : typeof arg2 === "string" ? arg2 : void 0;
1764
+ const date_to = isArg1Config ? arg4 : typeof arg3 === "string" ? arg3 : void 0;
1765
+ try {
1766
+ const { config: cfg } = resolveHookArgs(explicitConfig, void 0, ctx);
1767
+ return useQuery12({
1768
+ queryKey: ["available-slots", product_id, date_from, date_to],
1769
+ queryFn: () => getAvailableSlots(cfg, product_id, date_from, date_to),
1770
+ enabled: !!product_id && !!date_from && !!date_to
1771
+ });
1772
+ } catch (error) {
1773
+ logger.warn("[useAvailableSlots] Called outside QueryClientProvider, returning undefined");
1774
+ return { data: void 0, isLoading: false, error: null, isFetching: false, refetch: () => Promise.resolve({ data: void 0 }) };
1775
+ }
1776
+ }
1777
+ function useBookAppointment(config, accessToken) {
1778
+ const ctx = useSdkContext();
1779
+ try {
1780
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx);
1781
+ const queryClient = useQueryClient5();
1782
+ return useMutation5({
1783
+ mutationFn: (payload) => token ? bookAppointment(cfg, token, payload) : Promise.reject("No access token"),
1784
+ onSuccess: () => {
1785
+ queryClient.invalidateQueries({ queryKey: ["appointments"] });
1786
+ }
1787
+ });
1788
+ } catch (error) {
1789
+ logger.warn("[useBookAppointment] Called outside QueryClientProvider, returning no-op mutation");
1790
+ return { mutate: () => {
1791
+ }, mutateAsync: () => Promise.resolve(void 0) };
1792
+ }
1793
+ }
1794
+ function useAppointments(config, accessToken) {
1795
+ const ctx = useSdkContext();
1796
+ try {
1797
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx);
1798
+ return useQuery12({
1799
+ queryKey: ["appointments"],
1800
+ queryFn: () => token ? getAppointments(cfg, token) : Promise.resolve([]),
1801
+ enabled: !!token
1802
+ });
1803
+ } catch (error) {
1804
+ logger.warn("[useAppointments] Called outside QueryClientProvider, returning empty list");
1805
+ return { data: void 0, isLoading: false, error: null, isFetching: false, refetch: () => Promise.resolve({ data: void 0 }) };
1806
+ }
1807
+ }
1808
+ function useAppointment(arg1, arg2, arg3) {
1809
+ const ctx = useSdkContext();
1810
+ const isArg1Config = typeof arg1 === "object" && arg1 !== null && "businessId" in arg1;
1811
+ const explicitConfig = isArg1Config ? arg1 : void 0;
1812
+ const explicitToken = isArg1Config ? arg2 : void 0;
1813
+ const id = isArg1Config ? arg3 : typeof arg1 === "string" ? arg1 : void 0;
1814
+ try {
1815
+ const { config: cfg, accessToken: token } = resolveHookArgs(explicitConfig, explicitToken, ctx);
1816
+ return useQuery12({
1817
+ queryKey: ["appointment", id],
1818
+ queryFn: () => token && id ? getAppointment(cfg, token, id) : Promise.resolve(void 0),
1819
+ enabled: !!id && !!token
1820
+ });
1821
+ } catch (error) {
1822
+ logger.warn("[useAppointment] Called outside QueryClientProvider, returning undefined");
1823
+ return { data: void 0, isLoading: false, error: null, isFetching: false, refetch: () => Promise.resolve({ data: void 0 }) };
1824
+ }
1825
+ }
1826
+ function useCancelAppointment(config, accessToken) {
1827
+ const ctx = useSdkContext();
1828
+ try {
1829
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx);
1830
+ const queryClient = useQueryClient5();
1831
+ return useMutation5({
1832
+ mutationFn: (id) => token ? cancelAppointment(cfg, token, id) : Promise.reject("No access token"),
1833
+ onSuccess: () => {
1834
+ queryClient.invalidateQueries({ queryKey: ["appointments"] });
1835
+ }
1836
+ });
1837
+ } catch (error) {
1838
+ logger.warn("[useCancelAppointment] Called outside QueryClientProvider, returning no-op mutation");
1839
+ return { mutate: () => {
1840
+ }, mutateAsync: () => Promise.resolve(void 0) };
1841
+ }
1842
+ }
1843
+ function useDeliverables(arg1, arg2, arg3) {
1844
+ const ctx = useSdkContext();
1845
+ const isArg1Config = typeof arg1 === "object" && arg1 !== null && "businessId" in arg1;
1846
+ const explicitConfig = isArg1Config ? arg1 : void 0;
1847
+ const explicitToken = isArg1Config ? arg2 : void 0;
1848
+ const order_id = isArg1Config ? arg3 : typeof arg1 === "string" ? arg1 : void 0;
1849
+ try {
1850
+ const { config: cfg, accessToken: token } = resolveHookArgs(explicitConfig, explicitToken, ctx);
1851
+ return useQuery12({
1852
+ queryKey: ["deliverables", order_id],
1853
+ queryFn: () => token && order_id ? getDeliverables(cfg, token, order_id) : Promise.resolve([]),
1854
+ enabled: !!order_id && !!token
1855
+ });
1856
+ } catch (error) {
1857
+ logger.warn("[useDeliverables] Called outside QueryClientProvider, returning empty list");
1858
+ return { data: void 0, isLoading: false, error: null, isFetching: false, refetch: () => Promise.resolve({ data: void 0 }) };
1859
+ }
1860
+ }
1861
+ function useApproveDeliverable(config, accessToken, order_id, deliverable_id) {
1862
+ const ctx = useSdkContext();
1863
+ try {
1864
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx);
1865
+ const queryClient = useQueryClient5();
1866
+ return useMutation5({
1867
+ mutationFn: () => token && order_id && deliverable_id ? approveDeliverable(cfg, token, order_id, deliverable_id) : Promise.reject("No access token"),
1868
+ onSuccess: () => {
1869
+ queryClient.invalidateQueries({ queryKey: ["deliverables", order_id] });
1870
+ }
1871
+ });
1872
+ } catch (error) {
1873
+ logger.warn("[useApproveDeliverable] Called outside QueryClientProvider, returning no-op mutation");
1874
+ return { mutate: () => {
1875
+ }, mutateAsync: () => Promise.resolve(void 0) };
1876
+ }
1877
+ }
1878
+ function useRequestRevision(config, accessToken, order_id, deliverable_id) {
1879
+ const ctx = useSdkContext();
1880
+ try {
1881
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx);
1882
+ const queryClient = useQueryClient5();
1883
+ return useMutation5({
1884
+ mutationFn: (feedback) => token && order_id && deliverable_id ? requestRevision(cfg, token, order_id, deliverable_id, feedback) : Promise.reject("No access token"),
1885
+ onSuccess: () => {
1886
+ queryClient.invalidateQueries({ queryKey: ["deliverables", order_id] });
1887
+ }
1888
+ });
1889
+ } catch (error) {
1890
+ logger.warn("[useRequestRevision] Called outside QueryClientProvider, returning no-op mutation");
1891
+ return { mutate: () => {
1892
+ }, mutateAsync: () => Promise.resolve(void 0) };
1893
+ }
1894
+ }
1895
+
1896
+ // src/hooks/use-consultations.ts
1897
+ import { useQuery as useQuery13, useMutation as useMutation6, useQueryClient as useQueryClient6 } from "@tanstack/react-query";
1898
+
1899
+ // src/services/consultation.service.ts
1900
+ async function createConsultation(config, accessToken, payload) {
1901
+ const response = await fetch(`${config.backendUrls.store}/social/consultations/`, {
1902
+ method: "POST",
1903
+ headers: {
1904
+ "Content-Type": "application/json",
1905
+ "Authorization": `Bearer ${accessToken}`,
1906
+ "X-Storefront-Key": config.storefrontApiKey,
1907
+ "X-Business-ID": config.businessId
1908
+ },
1909
+ body: JSON.stringify(payload)
1910
+ });
1911
+ if (!response.ok) throw new Error("Failed to create consultation");
1912
+ return response.json();
1913
+ }
1914
+ async function getConsultations(config, accessToken) {
1915
+ const response = await fetch(`${config.backendUrls.store}/social/consultations/`, {
1916
+ headers: {
1917
+ "Authorization": `Bearer ${accessToken}`,
1918
+ "X-Storefront-Key": config.storefrontApiKey,
1919
+ "X-Business-ID": config.businessId
1920
+ }
1921
+ });
1922
+ if (!response.ok) throw new Error("Failed to get consultations");
1923
+ return response.json();
1924
+ }
1925
+ async function getConsultation(config, accessToken, id) {
1926
+ const response = await fetch(`${config.backendUrls.store}/social/consultations/${id}`, {
1927
+ headers: {
1928
+ "Authorization": `Bearer ${accessToken}`,
1929
+ "X-Storefront-Key": config.storefrontApiKey,
1930
+ "X-Business-ID": config.businessId
1931
+ }
1932
+ });
1933
+ if (!response.ok) throw new Error("Failed to get consultation");
1934
+ return response.json();
1935
+ }
1936
+ async function sendMessage(config, accessToken, id, payload) {
1937
+ await fetch(`${config.backendUrls.store}/social/consultations/${id}/messages`, {
1938
+ method: "POST",
1939
+ headers: {
1940
+ "Content-Type": "application/json",
1941
+ "Authorization": `Bearer ${accessToken}`,
1942
+ "X-Storefront-Key": config.storefrontApiKey,
1943
+ "X-Business-ID": config.businessId
1944
+ },
1945
+ body: JSON.stringify(payload)
1946
+ });
1947
+ }
1948
+ async function acceptQuote(config, accessToken, id, payload) {
1949
+ const response = await fetch(`${config.backendUrls.store}/social/consultations/${id}/accept-quote`, {
1950
+ method: "POST",
1951
+ headers: {
1952
+ "Content-Type": "application/json",
1953
+ "Authorization": `Bearer ${accessToken}`,
1954
+ "X-Storefront-Key": config.storefrontApiKey,
1955
+ "X-Business-ID": config.businessId
1956
+ },
1957
+ body: JSON.stringify(payload)
1958
+ });
1959
+ if (!response.ok) throw new Error("Failed to accept quote");
1960
+ return response.json();
1961
+ }
1962
+ async function rejectQuote(config, accessToken, id, reason) {
1963
+ const response = await fetch(`${config.backendUrls.store}/social/consultations/${id}/reject-quote`, {
1964
+ method: "POST",
1965
+ headers: {
1966
+ "Content-Type": "application/json",
1967
+ "Authorization": `Bearer ${accessToken}`,
1968
+ "X-Storefront-Key": config.storefrontApiKey,
1969
+ "X-Business-ID": config.businessId
1970
+ },
1971
+ body: JSON.stringify({ reason })
1972
+ });
1973
+ if (!response.ok) throw new Error("Failed to reject quote");
1974
+ return response.json();
1975
+ }
1976
+
1977
+ // src/hooks/use-consultations.ts
1978
+ function useConsultations(config, accessToken) {
1979
+ const ctx = useSdkContext();
1980
+ try {
1981
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx);
1982
+ return useQuery13({
1983
+ queryKey: ["consultations"],
1984
+ queryFn: () => token ? getConsultations(cfg, token) : Promise.resolve([]),
1985
+ enabled: !!token
1986
+ });
1987
+ } catch (error) {
1988
+ logger.warn("[useConsultations] Called outside QueryClientProvider, returning empty list");
1989
+ return { data: void 0, isLoading: false, error: null, isFetching: false, refetch: () => Promise.resolve({ data: void 0 }) };
1990
+ }
1991
+ }
1992
+ function useConsultation(arg1, arg2, arg3) {
1993
+ const ctx = useSdkContext();
1994
+ const isArg1Config = typeof arg1 === "object" && arg1 !== null;
1995
+ const explicitConfig = isArg1Config ? arg1 : void 0;
1996
+ const explicitToken = isArg1Config ? arg2 : void 0;
1997
+ const id = isArg1Config ? arg3 : typeof arg1 === "string" ? arg1 : void 0;
1998
+ try {
1999
+ const { config: cfg, accessToken: token } = resolveHookArgs(explicitConfig, explicitToken, ctx);
2000
+ return useQuery13({
2001
+ queryKey: ["consultation", id],
2002
+ queryFn: () => token && id ? getConsultation(cfg, token, id) : Promise.resolve(void 0),
2003
+ enabled: !!id && !!token
2004
+ });
2005
+ } catch (error) {
2006
+ logger.warn("[useConsultation] Called outside QueryClientProvider, returning undefined");
2007
+ return { data: void 0, isLoading: false, error: null, isFetching: false, refetch: () => Promise.resolve({ data: void 0 }) };
2008
+ }
2009
+ }
2010
+ function useCreateConsultation(config, accessToken) {
2011
+ const ctx = useSdkContext();
2012
+ try {
2013
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx);
2014
+ const queryClient = useQueryClient6();
2015
+ return useMutation6({
2016
+ mutationFn: (payload) => token ? createConsultation(cfg, token, payload) : Promise.reject("No access token"),
2017
+ onSuccess: () => {
2018
+ queryClient.invalidateQueries({ queryKey: ["consultations"] });
2019
+ }
2020
+ });
2021
+ } catch (error) {
2022
+ logger.warn("[useCreateConsultation] Called outside QueryClientProvider, returning no-op mutation");
2023
+ return { mutate: () => {
2024
+ }, mutateAsync: () => Promise.resolve(void 0) };
2025
+ }
2026
+ }
2027
+ function useSendMessage(arg1, arg2, arg3) {
2028
+ const ctx = useSdkContext();
2029
+ const isArg1Config = typeof arg1 === "object" && arg1 !== null;
2030
+ const explicitConfig = isArg1Config ? arg1 : void 0;
2031
+ const explicitToken = isArg1Config ? arg2 : void 0;
2032
+ const consultationId = isArg1Config ? arg3 : typeof arg1 === "string" ? arg1 : void 0;
2033
+ try {
2034
+ const { config: cfg, accessToken: token } = resolveHookArgs(explicitConfig, explicitToken, ctx);
2035
+ const queryClient = useQueryClient6();
2036
+ return useMutation6({
2037
+ mutationFn: (payload) => token && consultationId ? sendMessage(cfg, token, consultationId, payload) : Promise.reject("No access token"),
2038
+ onSuccess: () => {
2039
+ queryClient.invalidateQueries({ queryKey: ["consultation", consultationId] });
2040
+ }
2041
+ });
2042
+ } catch (error) {
2043
+ logger.warn("[useSendMessage] Called outside QueryClientProvider, returning no-op mutation");
2044
+ return { mutate: () => {
2045
+ }, mutateAsync: () => Promise.resolve(void 0) };
2046
+ }
2047
+ }
2048
+ function useAcceptQuote(arg1, arg2, arg3) {
2049
+ const ctx = useSdkContext();
2050
+ const isArg1Config = typeof arg1 === "object" && arg1 !== null;
2051
+ const explicitConfig = isArg1Config ? arg1 : void 0;
2052
+ const explicitToken = isArg1Config ? arg2 : void 0;
2053
+ const consultationId = isArg1Config ? arg3 : typeof arg1 === "string" ? arg1 : void 0;
2054
+ try {
2055
+ const { config: cfg, accessToken: token } = resolveHookArgs(explicitConfig, explicitToken, ctx);
2056
+ const queryClient = useQueryClient6();
2057
+ return useMutation6({
2058
+ mutationFn: (payload) => token && consultationId ? acceptQuote(cfg, token, consultationId, payload) : Promise.reject("No access token"),
2059
+ onSuccess: () => {
2060
+ queryClient.invalidateQueries({ queryKey: ["consultation", consultationId] });
2061
+ }
2062
+ });
2063
+ } catch (error) {
2064
+ logger.warn("[useAcceptQuote] Called outside QueryClientProvider, returning no-op mutation");
2065
+ return { mutate: () => {
2066
+ }, mutateAsync: () => Promise.resolve(void 0) };
2067
+ }
2068
+ }
2069
+ function useRejectQuote(arg1, arg2, arg3) {
2070
+ const ctx = useSdkContext();
2071
+ const isArg1Config = typeof arg1 === "object" && arg1 !== null;
2072
+ const explicitConfig = isArg1Config ? arg1 : void 0;
2073
+ const explicitToken = isArg1Config ? arg2 : void 0;
2074
+ const consultationId = isArg1Config ? arg3 : typeof arg1 === "string" ? arg1 : void 0;
2075
+ try {
2076
+ const { config: cfg, accessToken: token } = resolveHookArgs(explicitConfig, explicitToken, ctx);
2077
+ const queryClient = useQueryClient6();
2078
+ return useMutation6({
2079
+ mutationFn: (reason) => token && consultationId ? rejectQuote(cfg, token, consultationId, reason) : Promise.reject("No access token"),
2080
+ onSuccess: () => {
2081
+ queryClient.invalidateQueries({ queryKey: ["consultation", consultationId] });
2082
+ }
2083
+ });
2084
+ } catch (error) {
2085
+ logger.warn("[useRejectQuote] Called outside QueryClientProvider, returning no-op mutation");
2086
+ return { mutate: () => {
2087
+ }, mutateAsync: () => Promise.resolve(void 0) };
2088
+ }
2089
+ }
2090
+
2091
+ // src/hooks/use-consultation-stream.ts
2092
+ import { useEffect, useRef, useState as useState2 } from "react";
2093
+ import { fetchEventSource } from "@microsoft/fetch-event-source";
2094
+ function useConsultationStream({
2095
+ config,
2096
+ consultationId,
2097
+ onMessage,
2098
+ onQuote,
2099
+ onStatusChange,
2100
+ onError
2101
+ }) {
2102
+ const abortControllerRef = useRef(null);
2103
+ const [isConnected, setIsConnected] = useState2(false);
2104
+ const [lastEvent, setLastEvent] = useState2(null);
2105
+ useEffect(() => {
2106
+ if (!consultationId) {
2107
+ return;
2108
+ }
2109
+ const abortController = new AbortController();
2110
+ abortControllerRef.current = abortController;
2111
+ const streamUrl = `${config.backendUrls.payment}/events/stream/consultation/${consultationId}`;
2112
+ fetchEventSource(streamUrl, {
2113
+ method: "GET",
2114
+ signal: abortController.signal,
2115
+ onmessage: (event) => {
2116
+ try {
2117
+ if (!event.data || event.data.trim() === "") {
2118
+ return;
2119
+ }
2120
+ const data = JSON.parse(event.data);
2121
+ logger.log("[ConsultationStream] Received event:", data);
2122
+ setLastEvent(data);
2123
+ if (data.event === "consultation.message") {
2124
+ logger.log("[ConsultationStream] Message detected, calling onMessage");
2125
+ if (onMessage) {
2126
+ onMessage(data);
2127
+ }
2128
+ }
2129
+ if (data.event === "consultation.quote") {
2130
+ logger.log("[ConsultationStream] Quote detected, calling onQuote");
2131
+ if (onQuote) {
2132
+ onQuote(data);
2133
+ }
2134
+ }
2135
+ if (data.event === "consultation.status") {
2136
+ logger.log("[ConsultationStream] Status change detected, calling onStatusChange");
2137
+ if (onStatusChange) {
2138
+ onStatusChange(data);
2139
+ }
2140
+ }
2141
+ } catch (error) {
2142
+ logger.error("[ConsultationStream] Error parsing event:", error);
2143
+ }
2144
+ },
2145
+ onerror: (error) => {
2146
+ if (abortController.signal.aborted) {
2147
+ logger.log("[ConsultationStream] Connection closed via AbortController");
2148
+ return;
2149
+ }
2150
+ logger.error("[ConsultationStream] Connection error:", error);
2151
+ setIsConnected(false);
2152
+ if (onError) {
2153
+ onError(error);
2154
+ }
2155
+ },
2156
+ onopen: async (response) => {
2157
+ if (response.ok && response.headers.get("content-type")?.includes("text/event-stream")) {
2158
+ logger.log("[ConsultationStream] Connection established for consultation:", consultationId);
2159
+ setIsConnected(true);
2160
+ return;
2161
+ }
2162
+ throw new Error(`Unexpected response: ${response.status}`);
2163
+ }
2164
+ }).catch((error) => {
2165
+ if (abortController.signal.aborted || error.name === "AbortError") {
2166
+ return;
2167
+ }
2168
+ logger.error("[ConsultationStream] fetchEventSource failed:", error);
2169
+ });
2170
+ return () => {
2171
+ abortController.abort();
2172
+ setIsConnected(false);
2173
+ };
2174
+ }, [consultationId, onMessage, onQuote, onStatusChange, onError]);
2175
+ return { isConnected, lastEvent };
2176
+ }
2177
+
2178
+ // src/hooks/use-order-stream.ts
2179
+ import { useEffect as useEffect2, useRef as useRef2 } from "react";
2180
+ import { fetchEventSource as fetchEventSource2 } from "@microsoft/fetch-event-source";
2181
+ function useOrderStream({
2182
+ config: explicitConfig,
2183
+ orderId,
2184
+ onPaymentComplete,
2185
+ onDigitalReady,
2186
+ onBespokeUpdate,
2187
+ onConsultationUpdate,
2188
+ onServiceBookingUpdate,
2189
+ onError
2190
+ }) {
2191
+ const ctx = useSdkContext();
2192
+ const config = explicitConfig ?? ctx?.config;
2193
+ const abortControllerRef = useRef2(null);
2194
+ useEffect2(() => {
2195
+ if (!orderId || !config) {
2196
+ return;
2197
+ }
2198
+ const abortController = new AbortController();
2199
+ abortControllerRef.current = abortController;
2200
+ const streamUrl = `${config.backendUrls.payment}/events/stream/order/${encodeURIComponent(orderId)}`;
2201
+ fetchEventSource2(streamUrl, {
2202
+ method: "GET",
2203
+ signal: abortController.signal,
2204
+ onmessage: (event) => {
2205
+ try {
2206
+ if (!event.data || event.data.trim() === "") {
2207
+ return;
2208
+ }
2209
+ const data = JSON.parse(event.data);
2210
+ logger.log("[OrderStream] Received event:", data);
2211
+ if (data.event === "payment.success") {
2212
+ logger.log("[OrderStream] Payment success detected, calling onPaymentComplete");
2213
+ if (onPaymentComplete) {
2214
+ onPaymentComplete(data);
2215
+ }
2216
+ abortController.abort();
2217
+ }
2218
+ if (data.event === "digital.ready") {
2219
+ logger.log("[OrderStream] Digital delivery ready detected, calling onDigitalReady");
2220
+ if (onDigitalReady) {
2221
+ onDigitalReady(data);
2222
+ }
2223
+ }
2224
+ if (data.event === "bespoke.update") {
2225
+ logger.log("[OrderStream] Bespoke update detected, calling onBespokeUpdate");
2226
+ if (onBespokeUpdate) {
2227
+ onBespokeUpdate(data);
2228
+ }
2229
+ }
2230
+ if (data.event === "consultation.update") {
2231
+ logger.log("[OrderStream] Consultation update detected, calling onConsultationUpdate");
2232
+ if (onConsultationUpdate) {
2233
+ onConsultationUpdate(data);
2234
+ }
2235
+ }
2236
+ if (data.event === "service_booking.update") {
2237
+ logger.log("[OrderStream] Service booking update detected, calling onServiceBookingUpdate");
2238
+ if (onServiceBookingUpdate) {
2239
+ onServiceBookingUpdate(data);
2240
+ }
2241
+ }
2242
+ } catch (error) {
2243
+ logger.error("[OrderStream] Error parsing event:", error);
2244
+ }
2245
+ },
2246
+ onerror: (error) => {
2247
+ if (abortController.signal.aborted) {
2248
+ logger.log("[OrderStream] Connection closed via AbortController");
2249
+ return;
2250
+ }
2251
+ if (error.message?.includes("404") || error.message?.includes("Not Found")) {
2252
+ logger.warn("[OrderStream] Stream endpoint unavailable for order:", orderId);
2253
+ return;
2254
+ }
2255
+ logger.error("[OrderStream] Connection error:", error);
2256
+ if (onError) {
2257
+ onError(error);
2258
+ }
2259
+ },
2260
+ onopen: async (response) => {
2261
+ if (response.ok && response.headers.get("content-type")?.includes("text/event-stream")) {
2262
+ logger.log("[OrderStream] Connection established for order:", orderId);
2263
+ return;
2264
+ }
2265
+ if (response.status === 404) {
2266
+ logger.warn("[OrderStream] Stream endpoint unavailable for order:", orderId);
2267
+ return;
2268
+ }
2269
+ throw new Error(`Unexpected response: ${response.status}`);
2270
+ }
2271
+ }).catch((error) => {
2272
+ if (abortController.signal.aborted || error.name === "AbortError") {
2273
+ return;
2274
+ }
2275
+ logger.error("[OrderStream] fetchEventSource failed:", error);
2276
+ });
2277
+ return () => {
2278
+ abortController.abort();
2279
+ };
2280
+ }, [orderId, onPaymentComplete, onDigitalReady, onBespokeUpdate, onConsultationUpdate, onServiceBookingUpdate, onError]);
2281
+ return null;
2282
+ }
2283
+
2284
+ // src/hooks/use-is-mounted.ts
2285
+ import { useEffect as useEffect3, useState as useState3 } from "react";
2286
+ function useIsMounted() {
2287
+ const [mounted, setMounted] = useState3(false);
2288
+ useEffect3(() => {
2289
+ setMounted(true);
2290
+ }, []);
2291
+ return mounted;
2292
+ }
2293
+
2294
+ // src/hooks/use-mobile.ts
2295
+ import { useEffect as useEffect4, useState as useState4 } from "react";
2296
+ var MOBILE_BREAKPOINT = 768;
2297
+ function useIsMobile() {
2298
+ const [isMobile, setIsMobile] = useState4(false);
2299
+ useEffect4(() => {
2300
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
2301
+ const onChange = () => setIsMobile(mql.matches);
2302
+ mql.addEventListener("change", onChange);
2303
+ setIsMobile(mql.matches);
2304
+ return () => mql.removeEventListener("change", onChange);
2305
+ }, []);
2306
+ return isMobile;
2307
+ }
2308
+
2309
+ // src/hooks/use-google-translate.ts
2310
+ import { useEffect as useEffect5, useCallback, useState as useState5, useRef as useRef3 } from "react";
2311
+ var SCRIPT_ID = "google-translate-script";
2312
+ var ELEMENT_ID = "google_translate_element";
2313
+ function fireChange(googleCode) {
2314
+ const combo = document.querySelector(".goog-te-combo");
2315
+ if (combo) {
2316
+ combo.value = googleCode;
2317
+ combo.dispatchEvent(new Event("change"));
2318
+ return true;
2319
+ }
2320
+ return false;
2321
+ }
2322
+ function useGoogleTranslate(configOrLang, appLang) {
2323
+ const ctx = useSdkContext();
2324
+ let cfg;
2325
+ let lang;
2326
+ if (typeof configOrLang === "string") {
2327
+ lang = configOrLang;
2328
+ cfg = resolveHookArgs(void 0, void 0, ctx).config;
2329
+ } else {
2330
+ lang = appLang ?? "en";
2331
+ cfg = resolveHookArgs(configOrLang, void 0, ctx).config;
2332
+ }
2333
+ const [isLoaded, setIsLoaded] = useState5(false);
2334
+ const initRef = useRef3(false);
2335
+ const { data: supportedLangs = [] } = useSupportedLanguages(cfg);
2336
+ const clearCookies = useCallback(() => {
2337
+ if (typeof window === "undefined") return;
2338
+ const domains = [
2339
+ window.location.hostname,
2340
+ "." + window.location.hostname,
2341
+ "." + window.location.hostname.split(".").slice(-2).join(".")
2342
+ ];
2343
+ const path = "/";
2344
+ document.cookie = `googtrans=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=${path};`;
2345
+ domains.forEach((domain) => {
2346
+ document.cookie = `googtrans=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=${path}; domain=${domain};`;
2347
+ });
2348
+ }, []);
2349
+ const resetToEnglish = useCallback(() => {
2350
+ if (typeof window === "undefined") return;
2351
+ const googtrans = document.cookie.split("; ").find((row) => row.startsWith("googtrans="))?.split("=")[1];
2352
+ const domains = [
2353
+ window.location.hostname,
2354
+ "." + window.location.hostname,
2355
+ window.location.hostname.split(".").slice(-2).join("."),
2356
+ "." + window.location.hostname.split(".").slice(-2).join(".")
2357
+ ];
2358
+ const clear = (name) => {
2359
+ document.cookie = `${name}=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;`;
2360
+ domains.forEach((d) => {
2361
+ document.cookie = `${name}=; Path=/; Domain=${d}; Expires=Thu, 01 Jan 1970 00:00:01 GMT;`;
2362
+ });
2363
+ };
2364
+ clear("googtrans");
2365
+ if (googtrans || document.documentElement.classList.contains("translated-ltr") || document.querySelector(".goog-te-banner-frame")) {
2366
+ window.location.reload();
2367
+ return;
2368
+ }
2369
+ document.body.style.top = "0";
2370
+ document.documentElement.classList.remove("translated-ltr", "translated-rtl");
2371
+ const container = document.getElementById(":1.container");
2372
+ if (container) container.style.display = "none";
2373
+ }, []);
2374
+ const changeLanguage = useCallback((nextAppCode) => {
2375
+ if (nextAppCode === "en") {
2376
+ resetToEnglish();
2377
+ return;
2378
+ }
2379
+ const googleCode = nextAppCode;
2380
+ const container = document.getElementById(":1.container");
2381
+ if (container) container.style.display = "block";
2382
+ let tries = 0;
2383
+ const tick = () => {
2384
+ if (fireChange(googleCode)) return;
2385
+ if (tries++ < 30) setTimeout(tick, 200);
2386
+ };
2387
+ tick();
2388
+ }, [resetToEnglish]);
2389
+ useEffect5(() => {
2390
+ if (typeof window === "undefined") return;
2391
+ if (lang === "en" && !initRef.current) return;
2392
+ if (initRef.current) return;
2393
+ if (supportedLangs.length === 0) return;
2394
+ initRef.current = true;
2395
+ if (!document.getElementById(ELEMENT_ID)) {
2396
+ const host = document.createElement("div");
2397
+ host.id = ELEMENT_ID;
2398
+ host.style.display = "none";
2399
+ document.body.appendChild(host);
2400
+ }
2401
+ const includedLanguages = supportedLangs.map((l) => l.code).join(",");
2402
+ window.googleTranslateElementInit = () => {
2403
+ if (window.google?.translate?.TranslateElement) {
2404
+ new window.google.translate.TranslateElement(
2405
+ { pageLanguage: "en", includedLanguages, autoDisplay: false },
2406
+ ELEMENT_ID
2407
+ );
2408
+ setIsLoaded(true);
2409
+ }
2410
+ };
2411
+ if (!document.getElementById(SCRIPT_ID)) {
2412
+ const script = document.createElement("script");
2413
+ script.id = SCRIPT_ID;
2414
+ script.src = "//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit";
2415
+ script.async = true;
2416
+ document.body.appendChild(script);
2417
+ } else {
2418
+ if (window.google?.translate) window.googleTranslateElementInit?.();
2419
+ }
2420
+ }, [lang, supportedLangs]);
2421
+ useEffect5(() => {
2422
+ if (isLoaded || lang === "en" && initRef.current) {
2423
+ changeLanguage(lang);
2424
+ }
2425
+ }, [lang, isLoaded, changeLanguage]);
2426
+ return { isLoaded };
2427
+ }
2428
+
2429
+ // src/hooks/use-payment.ts
2430
+ import { useQuery as useQuery14, useMutation as useMutation7, useQueryClient as useQueryClient7 } from "@tanstack/react-query";
2431
+
2432
+ // src/services/payment.service.ts
2433
+ async function createDedicatedAccount(config, accessToken, request) {
2434
+ const isValidUUID = (str) => {
2435
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
2436
+ return uuidRegex.test(str);
2437
+ };
2438
+ const response = await fetch(`${config.backendUrls.payment}/payments/dedicated-account`, {
2439
+ method: "POST",
2440
+ headers: {
2441
+ "Content-Type": "application/json",
2442
+ "Authorization": `Bearer ${accessToken}`,
2443
+ "X-Storefront-Key": config.storefrontApiKey,
2444
+ "X-Business-ID": config.businessId
2445
+ },
2446
+ body: JSON.stringify({
2447
+ order_id: request.order_id && isValidUUID(request.order_id) ? request.order_id : void 0,
2448
+ amount: request.amount,
2449
+ customer_email: request.customer_email,
2450
+ customer_name: request.customer_name,
2451
+ currency: request.currency,
2452
+ idempotency_key: request.idempotency_key
2453
+ })
2454
+ });
2455
+ if (!response.ok) throw new Error("Failed to create dedicated account");
2456
+ const data = await response.json();
2457
+ return data;
2458
+ }
2459
+ async function initiatePayment(config, accessToken, request) {
2460
+ const isValidUUID = (str) => {
2461
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
2462
+ return uuidRegex.test(str);
2463
+ };
2464
+ const validOrderId = request.order_id && isValidUUID(request.order_id) ? request.order_id : void 0;
2465
+ const response = await fetch(`${config.backendUrls.payment}/payments/storefront/initiate`, {
2466
+ method: "POST",
2467
+ headers: {
2468
+ "Content-Type": "application/json",
2469
+ "Authorization": `Bearer ${accessToken}`,
2470
+ "X-Storefront-Key": config.storefrontApiKey,
2471
+ "X-Business-ID": config.businessId
2472
+ },
2473
+ body: JSON.stringify({
2474
+ amount: request.amount,
2475
+ currency: request.currency,
2476
+ order_id: validOrderId,
2477
+ quote_id: request.quote_id,
2478
+ metadata_json: {
2479
+ customer_email: request.customer_email,
2480
+ customer_name: request.customer_name ?? "",
2481
+ order_id: validOrderId,
2482
+ ...request.metadata ?? {}
2483
+ },
2484
+ idempotency_key: request.idempotency_key
2485
+ })
2486
+ });
2487
+ if (!response.ok) throw new Error("Failed to initiate payment");
2488
+ const data = await response.json();
2489
+ return {
2490
+ id: data.id,
2491
+ gateway_ref: data.gateway_ref,
2492
+ gateway: data.gateway,
2493
+ status: data.status,
2494
+ checkout_url: data.metadata_json?.checkout_url ?? ""
2495
+ };
2496
+ }
2497
+ async function verifyTransaction(configOrReference, reference) {
2498
+ if (typeof configOrReference === "string") {
2499
+ const ref2 = configOrReference;
2500
+ const response2 = await fetch(`/api/payments/verify/${ref2}`, {
2501
+ method: "POST",
2502
+ headers: { "Content-Type": "application/json" }
2503
+ });
2504
+ if (!response2.ok) throw new Error("Failed to verify transaction");
2505
+ return response2.json();
2506
+ }
2507
+ const config = configOrReference;
2508
+ const ref = reference || "";
2509
+ const response = await fetch(`${config.backendUrls.payment}/payments/verify/${ref}`, {
2510
+ method: "POST",
2511
+ headers: {
2512
+ "Content-Type": "application/json",
2513
+ "X-Storefront-Key": config.storefrontApiKey,
2514
+ "X-Business-ID": config.businessId
2515
+ }
2516
+ });
2517
+ if (!response.ok) throw new Error("Failed to verify transaction");
2518
+ const data = await response.json();
2519
+ return data;
2520
+ }
2521
+ async function getTransactionStatus(config, transactionId) {
2522
+ const response = await fetch(`${config.backendUrls.payment}/payments/transactions/${transactionId}`, {
2523
+ headers: {
2524
+ "X-Storefront-Key": config.storefrontApiKey,
2525
+ "X-Business-ID": config.businessId
2526
+ }
2527
+ });
2528
+ if (!response.ok) throw new Error("Failed to get transaction status");
2529
+ const data = await response.json();
2530
+ return data;
2531
+ }
2532
+
2533
+ // src/hooks/use-payment.ts
2534
+ function useCreateDVA(config, accessToken) {
2535
+ const ctx = useSdkContext();
2536
+ try {
2537
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx);
2538
+ const queryClient = useQueryClient7();
2539
+ return useMutation7({
2540
+ mutationFn: (request) => token ? createDedicatedAccount(cfg, token, request) : Promise.reject("No access token"),
2541
+ onSuccess: () => {
2542
+ queryClient.invalidateQueries({ queryKey: ["payment"] });
2543
+ }
2544
+ });
2545
+ } catch (error) {
2546
+ logger.warn("[useCreateDVA] Called outside QueryClientProvider, returning no-op mutation");
2547
+ return {
2548
+ mutate: () => {
2549
+ },
2550
+ mutateAsync: () => Promise.resolve(void 0)
2551
+ };
2552
+ }
2553
+ }
2554
+ function useInitiatePayment(config, accessToken) {
2555
+ const ctx = useSdkContext();
2556
+ try {
2557
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx);
2558
+ return useMutation7({
2559
+ mutationFn: (request) => token ? initiatePayment(cfg, token, request) : Promise.reject("No access token")
2560
+ });
2561
+ } catch (error) {
2562
+ logger.warn("[useInitiatePayment] Called outside QueryClientProvider, returning no-op mutation");
2563
+ return {
2564
+ mutate: () => {
2565
+ },
2566
+ mutateAsync: () => Promise.resolve(void 0)
2567
+ };
2568
+ }
2569
+ }
2570
+ function useVerifyTransaction(config) {
2571
+ const ctx = useSdkContext();
2572
+ try {
2573
+ const { config: cfg } = resolveHookArgs(config, void 0, ctx);
2574
+ return useMutation7({
2575
+ mutationFn: (reference) => verifyTransaction(cfg, reference)
2576
+ });
2577
+ } catch (error) {
2578
+ logger.warn("[useVerifyTransaction] Called outside QueryClientProvider, returning no-op mutation");
2579
+ return {
2580
+ mutate: () => {
2581
+ },
2582
+ mutateAsync: () => Promise.resolve(void 0)
2583
+ };
2584
+ }
2585
+ }
2586
+ function useTransactionStatus(arg1, arg2, arg3) {
2587
+ const ctx = useSdkContext();
2588
+ const isArg1Config = typeof arg1 === "object" && arg1 !== null && "businessId" in arg1;
2589
+ const explicitConfig = isArg1Config ? arg1 : void 0;
2590
+ const transactionId = isArg1Config ? arg2 : typeof arg1 === "string" ? arg1 : "";
2591
+ const enabled = isArg1Config ? arg3 ?? false : typeof arg2 === "boolean" ? arg2 : false;
2592
+ try {
2593
+ const { config: cfg } = resolveHookArgs(explicitConfig, void 0, ctx);
2594
+ return useQuery14({
2595
+ queryKey: ["transaction", "status", transactionId],
2596
+ queryFn: () => getTransactionStatus(cfg, transactionId),
2597
+ enabled: enabled && !!transactionId,
2598
+ refetchInterval: 3e3
2599
+ });
2600
+ } catch (error) {
2601
+ logger.warn("[useTransactionStatus] Called outside QueryClientProvider, returning undefined");
2602
+ return {
2603
+ data: void 0,
2604
+ isLoading: false,
2605
+ error: null,
2606
+ isFetching: false,
2607
+ refetch: () => Promise.resolve({ data: void 0 })
2608
+ };
2609
+ }
2610
+ }
2611
+ function usePollTransactionStatus(arg1, arg2, arg3) {
2612
+ const ctx = useSdkContext();
2613
+ const isArg1Config = typeof arg1 === "object" && arg1 !== null && "businessId" in arg1;
2614
+ const explicitConfig = isArg1Config ? arg1 : void 0;
2615
+ const reference = isArg1Config ? arg2 : typeof arg1 === "string" ? arg1 : "";
2616
+ const enabled = isArg1Config ? arg3 ?? false : typeof arg2 === "boolean" ? arg2 : false;
2617
+ try {
2618
+ const { config: cfg } = resolveHookArgs(explicitConfig, void 0, ctx);
2619
+ return useQuery14({
2620
+ queryKey: ["transaction", "poll", reference],
2621
+ queryFn: () => verifyTransaction(cfg, reference),
2622
+ enabled: enabled && !!reference,
2623
+ refetchInterval: 2e3,
2624
+ retry: 10
2625
+ });
2626
+ } catch (error) {
2627
+ logger.warn("[usePollTransactionStatus] Called outside QueryClientProvider, returning undefined");
2628
+ return {
2629
+ data: void 0,
2630
+ isLoading: false,
2631
+ error: null,
2632
+ isFetching: false,
2633
+ refetch: () => Promise.resolve({ data: void 0 })
2634
+ };
2635
+ }
2636
+ }
2637
+
2638
+ // src/hooks/use-cms.ts
2639
+ import { useQuery as useQuery15, useMutation as useMutation8, useQueryClient as useQueryClient8 } from "@tanstack/react-query";
2640
+
2641
+ // src/services/cms.service.ts
2642
+ async function listCmsEntries(config, modelSlug, params) {
2643
+ const queryParams = new URLSearchParams();
2644
+ queryParams.set("page", (params?.page || 1).toString());
2645
+ queryParams.set("page_size", (params?.page_size || 50).toString());
2646
+ const response = await fetch(
2647
+ `${config.backendUrls.cms}/sdk/${config.businessId}/${modelSlug}/entries?${queryParams.toString()}`,
2648
+ {
2649
+ headers: {
2650
+ "X-Storefront-Key": config.storefrontApiKey,
2651
+ "X-Business-ID": config.businessId
2652
+ }
2653
+ }
2654
+ );
2655
+ if (!response.ok) throw new Error("Failed to list CMS entries");
2656
+ return response.json();
2657
+ }
2658
+ async function getCmsEntry(config, modelSlug, entryId) {
2659
+ const response = await fetch(
2660
+ `${config.backendUrls.cms}/sdk/${config.businessId}/${modelSlug}/entries/${entryId}`,
2661
+ {
2662
+ headers: {
2663
+ "X-Storefront-Key": config.storefrontApiKey,
2664
+ "X-Business-ID": config.businessId
2665
+ }
2666
+ }
2667
+ );
2668
+ if (!response.ok) throw new Error("Failed to get CMS entry");
2669
+ return response.json();
2670
+ }
2671
+ async function createCmsEntry(config, accessToken, modelSlug, params) {
2672
+ const response = await fetch(
2673
+ `${config.backendUrls.cms}/sdk/${config.businessId}/${modelSlug}/entries`,
2674
+ {
2675
+ method: "POST",
2676
+ headers: {
2677
+ "Content-Type": "application/json",
2678
+ "Authorization": `Bearer ${accessToken}`,
2679
+ "X-Storefront-Key": config.storefrontApiKey,
2680
+ "X-Business-ID": config.businessId
2681
+ },
2682
+ body: JSON.stringify(params)
2683
+ }
2684
+ );
2685
+ if (!response.ok) throw new Error("Failed to create CMS entry");
2686
+ return response.json();
2687
+ }
2688
+ async function updateCmsEntry(config, accessToken, modelSlug, entryId, params) {
2689
+ const response = await fetch(
2690
+ `${config.backendUrls.cms}/sdk/${config.businessId}/${modelSlug}/entries/${entryId}`,
2691
+ {
2692
+ method: "PUT",
2693
+ headers: {
2694
+ "Content-Type": "application/json",
2695
+ "Authorization": `Bearer ${accessToken}`,
2696
+ "X-Storefront-Key": config.storefrontApiKey,
2697
+ "X-Business-ID": config.businessId
2698
+ },
2699
+ body: JSON.stringify(params)
2700
+ }
2701
+ );
2702
+ if (!response.ok) throw new Error("Failed to update CMS entry");
2703
+ return response.json();
2704
+ }
2705
+ async function deleteCmsEntry(config, accessToken, modelSlug, entryId) {
2706
+ const response = await fetch(
2707
+ `${config.backendUrls.cms}/sdk/${config.businessId}/${modelSlug}/entries/${entryId}`,
2708
+ {
2709
+ method: "DELETE",
2710
+ headers: {
2711
+ "Authorization": `Bearer ${accessToken}`,
2712
+ "X-Storefront-Key": config.storefrontApiKey,
2713
+ "X-Business-ID": config.businessId
2714
+ }
2715
+ }
2716
+ );
2717
+ if (!response.ok) throw new Error("Failed to delete CMS entry");
2718
+ }
2719
+
2720
+ // src/hooks/use-cms.ts
2721
+ function useCmsEntries(configOrModelSlug, modelSlugOrParams, maybeParams) {
2722
+ const ctx = useSdkContext();
2723
+ let cfg;
2724
+ let slug;
2725
+ let params;
2726
+ if (typeof configOrModelSlug === "string") {
2727
+ slug = configOrModelSlug;
2728
+ params = modelSlugOrParams;
2729
+ cfg = resolveHookArgs(void 0, void 0, ctx).config;
2730
+ } else {
2731
+ cfg = configOrModelSlug;
2732
+ slug = modelSlugOrParams;
2733
+ params = maybeParams;
2734
+ }
2735
+ try {
2736
+ const query = useQuery15({
2737
+ queryKey: ["cms-entries", slug, params],
2738
+ queryFn: () => listCmsEntries(cfg, slug, params),
2739
+ enabled: !!slug
2740
+ });
2741
+ return {
2742
+ entries: query.data?.entries || [],
2743
+ total: query.data?.total || 0,
2744
+ page: query.data?.page || 1,
2745
+ page_size: query.data?.page_size || 50,
2746
+ isLoading: query.isLoading,
2747
+ error: query.error,
2748
+ refetch: query.refetch
2749
+ };
2750
+ } catch (error) {
2751
+ logger.warn("[useCmsEntries] Called outside QueryClientProvider, returning empty list");
2752
+ return {
2753
+ entries: [],
2754
+ total: 0,
2755
+ page: 1,
2756
+ page_size: 50,
2757
+ isLoading: false,
2758
+ error: null,
2759
+ refetch: () => {
2760
+ }
2761
+ };
2762
+ }
2763
+ }
2764
+ function useCmsEntry(configOrModelSlug, modelSlugOrEntryId, maybeEntryId) {
2765
+ const ctx = useSdkContext();
2766
+ let cfg;
2767
+ let slug;
2768
+ let entryId;
2769
+ if (maybeEntryId !== void 0) {
2770
+ cfg = configOrModelSlug;
2771
+ slug = modelSlugOrEntryId;
2772
+ entryId = maybeEntryId;
2773
+ } else {
2774
+ cfg = resolveHookArgs(void 0, void 0, ctx).config;
2775
+ slug = configOrModelSlug;
2776
+ entryId = modelSlugOrEntryId;
2777
+ }
2778
+ try {
2779
+ const query = useQuery15({
2780
+ queryKey: ["cms-entry", slug, entryId],
2781
+ queryFn: () => getCmsEntry(cfg, slug, entryId),
2782
+ enabled: !!slug && !!entryId
2783
+ });
2784
+ return {
2785
+ entry: query.data,
2786
+ isLoading: query.isLoading,
2787
+ error: query.error,
2788
+ refetch: query.refetch
2789
+ };
2790
+ } catch (error) {
2791
+ logger.warn("[useCmsEntry] Called outside QueryClientProvider, returning undefined");
2792
+ return {
2793
+ entry: void 0,
2794
+ isLoading: false,
2795
+ error: null,
2796
+ refetch: () => {
2797
+ }
2798
+ };
2799
+ }
2800
+ }
2801
+ function useCreateCmsEntry(config, accessToken, modelSlug) {
2802
+ const ctx = useSdkContext();
2803
+ try {
2804
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx);
2805
+ const queryClient = useQueryClient8();
2806
+ const mutation = useMutation8({
2807
+ mutationFn: (params) => token && modelSlug ? createCmsEntry(cfg, token, modelSlug, params) : Promise.reject("No access token or modelSlug"),
2808
+ onSuccess: () => {
2809
+ if (modelSlug) queryClient.invalidateQueries({ queryKey: ["cms-entries", modelSlug] });
2810
+ }
2811
+ });
2812
+ return {
2813
+ createEntry: mutation.mutate,
2814
+ isLoading: mutation.isPending,
2815
+ error: mutation.error
2816
+ };
2817
+ } catch (error) {
2818
+ logger.warn("[useCreateCmsEntry] Called outside QueryClientProvider, returning no-op mutation");
2819
+ return {
2820
+ createEntry: () => {
2821
+ },
2822
+ isLoading: false,
2823
+ error: null
2824
+ };
2825
+ }
2826
+ }
2827
+ function useUpdateCmsEntry(config, accessToken, modelSlug) {
2828
+ const ctx = useSdkContext();
2829
+ try {
2830
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx);
2831
+ const queryClient = useQueryClient8();
2832
+ const mutation = useMutation8({
2833
+ mutationFn: ({ entryId, params }) => token && modelSlug ? updateCmsEntry(cfg, token, modelSlug, entryId, params) : Promise.reject("No access token or modelSlug"),
2834
+ onSuccess: () => {
2835
+ if (modelSlug) {
2836
+ queryClient.invalidateQueries({ queryKey: ["cms-entries", modelSlug] });
2837
+ queryClient.invalidateQueries({ queryKey: ["cms-entry", modelSlug] });
2838
+ }
2839
+ }
2840
+ });
2841
+ return {
2842
+ updateEntry: (entryId, params) => mutation.mutate({ entryId, params }),
2843
+ isLoading: mutation.isPending,
2844
+ error: mutation.error
2845
+ };
2846
+ } catch (error) {
2847
+ logger.warn("[useUpdateCmsEntry] Called outside QueryClientProvider, returning no-op mutation");
2848
+ return {
2849
+ updateEntry: () => {
2850
+ },
2851
+ isLoading: false,
2852
+ error: null
2853
+ };
2854
+ }
2855
+ }
2856
+ function useDeleteCmsEntry(config, accessToken, modelSlug) {
2857
+ const ctx = useSdkContext();
2858
+ try {
2859
+ const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx);
2860
+ const queryClient = useQueryClient8();
2861
+ const mutation = useMutation8({
2862
+ mutationFn: (entryId) => token && modelSlug ? deleteCmsEntry(cfg, token, modelSlug, entryId) : Promise.reject("No access token or modelSlug"),
2863
+ onSuccess: () => {
2864
+ if (modelSlug) {
2865
+ queryClient.invalidateQueries({ queryKey: ["cms-entries", modelSlug] });
2866
+ queryClient.invalidateQueries({ queryKey: ["cms-entry", modelSlug] });
2867
+ }
2868
+ }
2869
+ });
2870
+ return {
2871
+ deleteEntry: mutation.mutate,
2872
+ isLoading: mutation.isPending,
2873
+ error: mutation.error
2874
+ };
2875
+ } catch (error) {
2876
+ logger.warn("[useDeleteCmsEntry] Called outside QueryClientProvider, returning no-op mutation");
2877
+ return {
2878
+ deleteEntry: () => {
2879
+ },
2880
+ isLoading: false,
2881
+ error: null
2882
+ };
2883
+ }
2884
+ }
2885
+ export {
2886
+ CartCtx,
2887
+ CartProvider,
2888
+ SdkProvider,
2889
+ collectionKeys,
2890
+ getCountries,
2891
+ getStates,
2892
+ getSupportedCurrenciesList,
2893
+ getSupportedLanguagesList,
2894
+ productKeys,
2895
+ resolveHookArgs,
2896
+ useAcceptQuote,
2897
+ useAddToWishlist,
2898
+ useAppointment,
2899
+ useAppointments,
2900
+ useApproveDeliverable,
2901
+ useAuthUser,
2902
+ useAvailableSlots,
2903
+ useBespokeAvailability,
2904
+ useBookAppointment,
2905
+ useCancelAppointment,
2906
+ useCancelOrder,
2907
+ useCart,
2908
+ useCheckInWishlist,
2909
+ useCmsEntries,
2910
+ useCmsEntry,
2911
+ useConsultation,
2912
+ useConsultationStream,
2913
+ useConsultations,
2914
+ useCountries,
2915
+ useCreateCmsEntry,
2916
+ useCreateConsultation,
2917
+ useCreateDVA,
2918
+ useCreateOrder,
2919
+ useCurrencies,
2920
+ useDeleteCmsEntry,
2921
+ useDeliverables,
2922
+ useFeaturedProducts,
2923
+ useFindOrder,
2924
+ useGoogleTranslate,
2925
+ useInitiatePayment,
2926
+ useIsMobile,
2927
+ useIsMounted,
2928
+ useLatestProducts,
2929
+ useLogin,
2930
+ useLogout,
2931
+ useLowStockProducts,
2932
+ useNewProducts,
2933
+ useOnSaleProducts,
2934
+ useOrder,
2935
+ useOrderStream,
2936
+ useOrderTracking,
2937
+ useOrders,
2938
+ useOrdersList,
2939
+ usePollTransactionStatus,
2940
+ usePopularProducts,
2941
+ useProduct,
2942
+ useRecommendedProducts,
2943
+ useRegister,
2944
+ useRejectQuote,
2945
+ useRemoveFromWishlist,
2946
+ useRemoveProductFromWishlist,
2947
+ useRequestRevision,
2948
+ useSdkContext,
2949
+ useSendMessage,
2950
+ useStates,
2951
+ useStorefrontCollection,
2952
+ useStorefrontCollections,
2953
+ useStorefrontProducts,
2954
+ useSupportedLanguages,
2955
+ useTransactionStatus,
2956
+ useUpdateCmsEntry,
2957
+ useUpdateProfile,
2958
+ useVerifyTransaction,
2959
+ useWishlist,
2960
+ wishlistKeys
2961
+ };
2962
+ //# sourceMappingURL=index.mjs.map