@behio/storefront-sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +999 -0
- package/dist/chunk-26WZOAWP.js +609 -0
- package/dist/chunk-3OJEEMLI.mjs +609 -0
- package/dist/index.d.mts +566 -0
- package/dist/index.d.ts +566 -0
- package/dist/index.js +20 -0
- package/dist/index.mjs +20 -0
- package/dist/react.d.mts +166 -0
- package/dist/react.d.ts +166 -0
- package/dist/react.js +813 -0
- package/dist/react.mjs +813 -0
- package/package.json +61 -0
package/dist/react.mjs
ADDED
|
@@ -0,0 +1,813 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BehioStorefront
|
|
3
|
+
} from "./chunk-3OJEEMLI.mjs";
|
|
4
|
+
|
|
5
|
+
// src/react/provider.tsx
|
|
6
|
+
import { useRef, useEffect, useMemo } from "react";
|
|
7
|
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
8
|
+
|
|
9
|
+
// src/react/context.ts
|
|
10
|
+
import { createContext, useContext } from "react";
|
|
11
|
+
var BehioContext = createContext(null);
|
|
12
|
+
function useBehio() {
|
|
13
|
+
const ctx = useContext(BehioContext);
|
|
14
|
+
if (!ctx) {
|
|
15
|
+
throw new Error("useBehio must be used within a <BehioProvider>");
|
|
16
|
+
}
|
|
17
|
+
return ctx;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// src/react/storage.ts
|
|
21
|
+
function getCookie(name) {
|
|
22
|
+
if (typeof document === "undefined") return null;
|
|
23
|
+
const match = document.cookie.match(new RegExp("(?:^|; )" + name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "=([^;]*)"));
|
|
24
|
+
return match ? decodeURIComponent(match[1]) : null;
|
|
25
|
+
}
|
|
26
|
+
function setCookie(name, value, maxAgeDays = 30) {
|
|
27
|
+
if (typeof document === "undefined") return;
|
|
28
|
+
const maxAge = maxAgeDays * 24 * 60 * 60;
|
|
29
|
+
document.cookie = `${name}=${encodeURIComponent(value)}; path=/; max-age=${maxAge}; SameSite=Lax`;
|
|
30
|
+
}
|
|
31
|
+
function removeCookie(name) {
|
|
32
|
+
if (typeof document === "undefined") return;
|
|
33
|
+
document.cookie = `${name}=; path=/; max-age=0; SameSite=Lax`;
|
|
34
|
+
}
|
|
35
|
+
var cookieStorage = {
|
|
36
|
+
get: getCookie,
|
|
37
|
+
set: setCookie,
|
|
38
|
+
remove: removeCookie
|
|
39
|
+
};
|
|
40
|
+
var localStorageAdapter = {
|
|
41
|
+
get(key) {
|
|
42
|
+
try {
|
|
43
|
+
return window.localStorage.getItem(key);
|
|
44
|
+
} catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
set(key, value) {
|
|
49
|
+
try {
|
|
50
|
+
window.localStorage.setItem(key, value);
|
|
51
|
+
} catch {
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
remove(key) {
|
|
55
|
+
try {
|
|
56
|
+
window.localStorage.removeItem(key);
|
|
57
|
+
} catch {
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
function createMemoryStorage() {
|
|
62
|
+
const store = /* @__PURE__ */ new Map();
|
|
63
|
+
return {
|
|
64
|
+
get(key) {
|
|
65
|
+
return store.get(key) ?? null;
|
|
66
|
+
},
|
|
67
|
+
set(key, value) {
|
|
68
|
+
store.set(key, value);
|
|
69
|
+
},
|
|
70
|
+
remove(key) {
|
|
71
|
+
store.delete(key);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
var memoryStorage = createMemoryStorage();
|
|
76
|
+
function detectStorage() {
|
|
77
|
+
if (typeof document !== "undefined") {
|
|
78
|
+
return cookieStorage;
|
|
79
|
+
}
|
|
80
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
81
|
+
return localStorageAdapter;
|
|
82
|
+
}
|
|
83
|
+
return createMemoryStorage();
|
|
84
|
+
}
|
|
85
|
+
function resolveStorage(option) {
|
|
86
|
+
if (!option) return detectStorage();
|
|
87
|
+
if (typeof option === "object") return option;
|
|
88
|
+
switch (option) {
|
|
89
|
+
case "cookies":
|
|
90
|
+
return cookieStorage;
|
|
91
|
+
case "localStorage":
|
|
92
|
+
return localStorageAdapter;
|
|
93
|
+
case "memory":
|
|
94
|
+
return createMemoryStorage();
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
var STORAGE_KEYS = {
|
|
98
|
+
ACCESS_TOKEN: "behio_access_token",
|
|
99
|
+
REFRESH_TOKEN: "behio_refresh_token",
|
|
100
|
+
CART_SESSION: "behio_cart_session"
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// src/react/provider.tsx
|
|
104
|
+
import { jsx } from "react/jsx-runtime";
|
|
105
|
+
function BehioProvider({
|
|
106
|
+
apiKey,
|
|
107
|
+
baseUrl,
|
|
108
|
+
locale,
|
|
109
|
+
currency,
|
|
110
|
+
storage: storageOption,
|
|
111
|
+
queryClient: externalQueryClient,
|
|
112
|
+
children
|
|
113
|
+
}) {
|
|
114
|
+
const storageAdapter = useMemo(() => resolveStorage(storageOption), [storageOption]);
|
|
115
|
+
const clientRef = useRef(null);
|
|
116
|
+
if (!clientRef.current) {
|
|
117
|
+
clientRef.current = new BehioStorefront({
|
|
118
|
+
apiKey,
|
|
119
|
+
baseUrl,
|
|
120
|
+
locale,
|
|
121
|
+
currency
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
const client = clientRef.current;
|
|
125
|
+
useEffect(() => {
|
|
126
|
+
const accessToken = storageAdapter.get(STORAGE_KEYS.ACCESS_TOKEN);
|
|
127
|
+
const refreshToken = storageAdapter.get(STORAGE_KEYS.REFRESH_TOKEN);
|
|
128
|
+
if (accessToken && refreshToken) {
|
|
129
|
+
client.setTokens({ accessToken, refreshToken });
|
|
130
|
+
}
|
|
131
|
+
const cartSession = storageAdapter.get(STORAGE_KEYS.CART_SESSION);
|
|
132
|
+
if (cartSession) {
|
|
133
|
+
client.setCartSession(cartSession);
|
|
134
|
+
}
|
|
135
|
+
}, [client, storageAdapter]);
|
|
136
|
+
const queryClientRef = useRef(null);
|
|
137
|
+
const qc = useMemo(() => {
|
|
138
|
+
if (externalQueryClient) return externalQueryClient;
|
|
139
|
+
if (!queryClientRef.current) {
|
|
140
|
+
queryClientRef.current = new QueryClient({
|
|
141
|
+
defaultOptions: {
|
|
142
|
+
queries: {
|
|
143
|
+
staleTime: 6e4,
|
|
144
|
+
retry: 1
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
return queryClientRef.current;
|
|
150
|
+
}, [externalQueryClient]);
|
|
151
|
+
const ctxValue = useMemo(
|
|
152
|
+
() => ({ client, storage: storageAdapter }),
|
|
153
|
+
[client, storageAdapter]
|
|
154
|
+
);
|
|
155
|
+
return /* @__PURE__ */ jsx(QueryClientProvider, { client: qc, children: /* @__PURE__ */ jsx(BehioContext.Provider, { value: ctxValue, children }) });
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// src/react/hooks/use-products.ts
|
|
159
|
+
import { useQuery } from "@tanstack/react-query";
|
|
160
|
+
function useProducts(query) {
|
|
161
|
+
const { client } = useBehio();
|
|
162
|
+
const { initialData, enabled, ...productsQuery } = query ?? {};
|
|
163
|
+
const serializedQuery = JSON.stringify(productsQuery);
|
|
164
|
+
return useQuery({
|
|
165
|
+
queryKey: ["behio", "products", serializedQuery],
|
|
166
|
+
queryFn: () => client.catalog.getProducts(productsQuery),
|
|
167
|
+
initialData,
|
|
168
|
+
enabled
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// src/react/hooks/use-product.ts
|
|
173
|
+
import { useQuery as useQuery2 } from "@tanstack/react-query";
|
|
174
|
+
function useProduct(slug, options) {
|
|
175
|
+
const { client } = useBehio();
|
|
176
|
+
return useQuery2({
|
|
177
|
+
queryKey: ["behio", "product", slug],
|
|
178
|
+
queryFn: () => client.catalog.getProduct(slug, {
|
|
179
|
+
locale: options?.locale,
|
|
180
|
+
currency: options?.currency
|
|
181
|
+
}),
|
|
182
|
+
initialData: options?.initialData,
|
|
183
|
+
enabled: options?.enabled ?? !!slug
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// src/react/hooks/use-categories.ts
|
|
188
|
+
import { useQuery as useQuery3 } from "@tanstack/react-query";
|
|
189
|
+
function useCategories(locale) {
|
|
190
|
+
const { client } = useBehio();
|
|
191
|
+
return useQuery3({
|
|
192
|
+
queryKey: ["behio", "categories", locale],
|
|
193
|
+
queryFn: async () => {
|
|
194
|
+
const result = await client.catalog.getCategories(locale);
|
|
195
|
+
return result.categories;
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// src/react/hooks/use-labels.ts
|
|
201
|
+
import { useQuery as useQuery4 } from "@tanstack/react-query";
|
|
202
|
+
function useLabels(locale) {
|
|
203
|
+
const { client } = useBehio();
|
|
204
|
+
return useQuery4({
|
|
205
|
+
queryKey: ["behio", "labels", locale],
|
|
206
|
+
queryFn: async () => {
|
|
207
|
+
const result = await client.catalog.getLabels(locale);
|
|
208
|
+
return result.labels;
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// src/react/hooks/use-featured.ts
|
|
214
|
+
import { useQuery as useQuery5 } from "@tanstack/react-query";
|
|
215
|
+
function useFeatured(options) {
|
|
216
|
+
const { client } = useBehio();
|
|
217
|
+
return useQuery5({
|
|
218
|
+
queryKey: ["behio", "featured", options?.locale, options?.currency],
|
|
219
|
+
queryFn: () => client.catalog.getFeatured({
|
|
220
|
+
locale: options?.locale,
|
|
221
|
+
currency: options?.currency
|
|
222
|
+
}),
|
|
223
|
+
initialData: options?.initialData,
|
|
224
|
+
enabled: options?.enabled
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// src/react/hooks/use-filters.ts
|
|
229
|
+
import { useQuery as useQuery6 } from "@tanstack/react-query";
|
|
230
|
+
function useFilters() {
|
|
231
|
+
const { client } = useBehio();
|
|
232
|
+
return useQuery6({
|
|
233
|
+
queryKey: ["behio", "filters"],
|
|
234
|
+
queryFn: async () => {
|
|
235
|
+
const result = await client.catalog.getFilters();
|
|
236
|
+
return result.filters;
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// src/react/hooks/use-search.ts
|
|
242
|
+
import { useState, useEffect as useEffect2 } from "react";
|
|
243
|
+
import { useQuery as useQuery7 } from "@tanstack/react-query";
|
|
244
|
+
function useSearch(query, options) {
|
|
245
|
+
const { client } = useBehio();
|
|
246
|
+
const debounceMs = options?.debounceMs ?? 300;
|
|
247
|
+
const [debouncedQuery, setDebouncedQuery] = useState(query);
|
|
248
|
+
useEffect2(() => {
|
|
249
|
+
if (debounceMs <= 0) {
|
|
250
|
+
setDebouncedQuery(query);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
const timer = setTimeout(() => setDebouncedQuery(query), debounceMs);
|
|
254
|
+
return () => clearTimeout(timer);
|
|
255
|
+
}, [query, debounceMs]);
|
|
256
|
+
return useQuery7({
|
|
257
|
+
queryKey: ["behio", "search", debouncedQuery, options?.page, options?.limit],
|
|
258
|
+
queryFn: () => client.catalog.search(debouncedQuery, {
|
|
259
|
+
page: options?.page,
|
|
260
|
+
limit: options?.limit
|
|
261
|
+
}),
|
|
262
|
+
enabled: (options?.enabled ?? true) && debouncedQuery.length > 0
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// src/react/hooks/use-cart.ts
|
|
267
|
+
import { useCallback } from "react";
|
|
268
|
+
import { useQuery as useQuery8, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
269
|
+
var CART_KEY = ["behio", "cart"];
|
|
270
|
+
function useCart() {
|
|
271
|
+
const { client, storage } = useBehio();
|
|
272
|
+
const queryClient = useQueryClient();
|
|
273
|
+
const {
|
|
274
|
+
data: cart,
|
|
275
|
+
isLoading,
|
|
276
|
+
error
|
|
277
|
+
} = useQuery8({
|
|
278
|
+
queryKey: [...CART_KEY],
|
|
279
|
+
queryFn: () => client.cart.get(),
|
|
280
|
+
// Only fetch if we have a cart session or are logged in
|
|
281
|
+
enabled: !!client.getCartSession() || !!client.getAccessToken()
|
|
282
|
+
});
|
|
283
|
+
const addMutation = useMutation({
|
|
284
|
+
mutationFn: async ({ productId, quantity }) => {
|
|
285
|
+
return client.cart.addItem({ productId, quantity: quantity ?? 1 });
|
|
286
|
+
},
|
|
287
|
+
onSuccess: (result) => {
|
|
288
|
+
if (result.newSessionToken) {
|
|
289
|
+
storage.set(STORAGE_KEYS.CART_SESSION, result.newSessionToken);
|
|
290
|
+
}
|
|
291
|
+
queryClient.setQueryData([...CART_KEY], result);
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
const updateMutation = useMutation({
|
|
295
|
+
mutationFn: async ({ itemId, quantity }) => {
|
|
296
|
+
return client.cart.updateQuantity(itemId, quantity);
|
|
297
|
+
},
|
|
298
|
+
onMutate: async ({ itemId, quantity }) => {
|
|
299
|
+
await queryClient.cancelQueries({ queryKey: [...CART_KEY] });
|
|
300
|
+
const previous = queryClient.getQueryData([...CART_KEY]);
|
|
301
|
+
if (previous) {
|
|
302
|
+
const updatedItems = previous.items.map(
|
|
303
|
+
(item) => item.id === itemId ? { ...item, quantity, totalPrice: item.unitPrice * quantity } : item
|
|
304
|
+
);
|
|
305
|
+
queryClient.setQueryData([...CART_KEY], {
|
|
306
|
+
...previous,
|
|
307
|
+
items: updatedItems,
|
|
308
|
+
itemCount: updatedItems.reduce((sum, i) => sum + i.quantity, 0)
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
return { previous };
|
|
312
|
+
},
|
|
313
|
+
onError: (_err, _vars, context) => {
|
|
314
|
+
if (context?.previous) {
|
|
315
|
+
queryClient.setQueryData([...CART_KEY], context.previous);
|
|
316
|
+
}
|
|
317
|
+
},
|
|
318
|
+
onSettled: () => {
|
|
319
|
+
queryClient.invalidateQueries({ queryKey: [...CART_KEY] });
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
const removeMutation = useMutation({
|
|
323
|
+
mutationFn: async (itemId) => {
|
|
324
|
+
return client.cart.removeItem(itemId);
|
|
325
|
+
},
|
|
326
|
+
onMutate: async (itemId) => {
|
|
327
|
+
await queryClient.cancelQueries({ queryKey: [...CART_KEY] });
|
|
328
|
+
const previous = queryClient.getQueryData([...CART_KEY]);
|
|
329
|
+
if (previous) {
|
|
330
|
+
const updatedItems = previous.items.filter((item) => item.id !== itemId);
|
|
331
|
+
queryClient.setQueryData([...CART_KEY], {
|
|
332
|
+
...previous,
|
|
333
|
+
items: updatedItems,
|
|
334
|
+
itemCount: updatedItems.reduce((sum, i) => sum + i.quantity, 0)
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
return { previous };
|
|
338
|
+
},
|
|
339
|
+
onError: (_err, _vars, context) => {
|
|
340
|
+
if (context?.previous) {
|
|
341
|
+
queryClient.setQueryData([...CART_KEY], context.previous);
|
|
342
|
+
}
|
|
343
|
+
},
|
|
344
|
+
onSettled: () => {
|
|
345
|
+
queryClient.invalidateQueries({ queryKey: [...CART_KEY] });
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
const clearMutation = useMutation({
|
|
349
|
+
mutationFn: () => client.cart.clear(),
|
|
350
|
+
onSuccess: () => {
|
|
351
|
+
queryClient.setQueryData([...CART_KEY], null);
|
|
352
|
+
client.clearCartSession();
|
|
353
|
+
storage.remove(STORAGE_KEYS.CART_SESSION);
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
const applyDiscountMutation = useMutation({
|
|
357
|
+
mutationFn: (code) => client.cart.applyDiscount(code),
|
|
358
|
+
onSuccess: (result) => {
|
|
359
|
+
queryClient.setQueryData([...CART_KEY], result);
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
const removeDiscountMutation = useMutation({
|
|
363
|
+
mutationFn: () => client.cart.removeDiscount(),
|
|
364
|
+
onSuccess: (result) => {
|
|
365
|
+
queryClient.setQueryData([...CART_KEY], result);
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
const mergeMutation = useMutation({
|
|
369
|
+
mutationFn: () => client.cart.merge(),
|
|
370
|
+
onSuccess: (result) => {
|
|
371
|
+
queryClient.setQueryData([...CART_KEY], result);
|
|
372
|
+
client.clearCartSession();
|
|
373
|
+
storage.remove(STORAGE_KEYS.CART_SESSION);
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
const addItem = useCallback(
|
|
377
|
+
(productId, quantity) => addMutation.mutateAsync({ productId, quantity }),
|
|
378
|
+
[addMutation]
|
|
379
|
+
);
|
|
380
|
+
const updateQuantity = useCallback(
|
|
381
|
+
(itemId, quantity) => updateMutation.mutateAsync({ itemId, quantity }),
|
|
382
|
+
[updateMutation]
|
|
383
|
+
);
|
|
384
|
+
const removeItem = useCallback(
|
|
385
|
+
(itemId) => removeMutation.mutateAsync(itemId),
|
|
386
|
+
[removeMutation]
|
|
387
|
+
);
|
|
388
|
+
const clear = useCallback(
|
|
389
|
+
() => clearMutation.mutateAsync(),
|
|
390
|
+
[clearMutation]
|
|
391
|
+
);
|
|
392
|
+
const applyDiscount = useCallback(
|
|
393
|
+
(code) => applyDiscountMutation.mutateAsync(code),
|
|
394
|
+
[applyDiscountMutation]
|
|
395
|
+
);
|
|
396
|
+
const removeDiscount = useCallback(
|
|
397
|
+
() => removeDiscountMutation.mutateAsync(),
|
|
398
|
+
[removeDiscountMutation]
|
|
399
|
+
);
|
|
400
|
+
const merge = useCallback(
|
|
401
|
+
() => mergeMutation.mutateAsync(),
|
|
402
|
+
[mergeMutation]
|
|
403
|
+
);
|
|
404
|
+
return {
|
|
405
|
+
cart: cart ?? null,
|
|
406
|
+
isLoading,
|
|
407
|
+
error,
|
|
408
|
+
// Actions
|
|
409
|
+
addItem,
|
|
410
|
+
updateQuantity,
|
|
411
|
+
removeItem,
|
|
412
|
+
clear,
|
|
413
|
+
applyDiscount,
|
|
414
|
+
removeDiscount,
|
|
415
|
+
merge,
|
|
416
|
+
// Computed
|
|
417
|
+
itemCount: cart?.itemCount ?? 0,
|
|
418
|
+
isEmpty: !cart || cart.items.length === 0,
|
|
419
|
+
// Mutation states
|
|
420
|
+
isAdding: addMutation.isPending,
|
|
421
|
+
isUpdating: updateMutation.isPending,
|
|
422
|
+
isRemoving: removeMutation.isPending
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// src/react/hooks/use-cart-count.ts
|
|
427
|
+
import { useQuery as useQuery9, useQueryClient as useQueryClient2 } from "@tanstack/react-query";
|
|
428
|
+
var CART_KEY2 = ["behio", "cart"];
|
|
429
|
+
function useCartCount() {
|
|
430
|
+
const { client } = useBehio();
|
|
431
|
+
const queryClient = useQueryClient2();
|
|
432
|
+
const cachedCart = queryClient.getQueryData([...CART_KEY2]);
|
|
433
|
+
const { data } = useQuery9({
|
|
434
|
+
queryKey: [...CART_KEY2],
|
|
435
|
+
queryFn: () => client.cart.get(),
|
|
436
|
+
enabled: !cachedCart && (!!client.getCartSession() || !!client.getAccessToken())
|
|
437
|
+
});
|
|
438
|
+
const cart = cachedCart ?? data;
|
|
439
|
+
return cart?.itemCount ?? 0;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// src/react/hooks/use-auth.ts
|
|
443
|
+
import { useCallback as useCallback2 } from "react";
|
|
444
|
+
import { useQuery as useQuery10, useMutation as useMutation2, useQueryClient as useQueryClient3 } from "@tanstack/react-query";
|
|
445
|
+
var CUSTOMER_KEY = ["behio", "customer"];
|
|
446
|
+
var CART_KEY3 = ["behio", "cart"];
|
|
447
|
+
function useAuth() {
|
|
448
|
+
const { client, storage } = useBehio();
|
|
449
|
+
const queryClient = useQueryClient3();
|
|
450
|
+
const isLoggedIn = !!client.getAccessToken();
|
|
451
|
+
const {
|
|
452
|
+
data: customer,
|
|
453
|
+
isLoading
|
|
454
|
+
} = useQuery10({
|
|
455
|
+
queryKey: [...CUSTOMER_KEY],
|
|
456
|
+
queryFn: () => client.customer.getProfile(),
|
|
457
|
+
enabled: isLoggedIn
|
|
458
|
+
});
|
|
459
|
+
const persistTokens = useCallback2(
|
|
460
|
+
(tokens) => {
|
|
461
|
+
client.setTokens(tokens);
|
|
462
|
+
storage.set(STORAGE_KEYS.ACCESS_TOKEN, tokens.accessToken);
|
|
463
|
+
storage.set(STORAGE_KEYS.REFRESH_TOKEN, tokens.refreshToken);
|
|
464
|
+
},
|
|
465
|
+
[client, storage]
|
|
466
|
+
);
|
|
467
|
+
const clearAuth = useCallback2(() => {
|
|
468
|
+
client.clearTokens();
|
|
469
|
+
storage.remove(STORAGE_KEYS.ACCESS_TOKEN);
|
|
470
|
+
storage.remove(STORAGE_KEYS.REFRESH_TOKEN);
|
|
471
|
+
queryClient.setQueryData([...CUSTOMER_KEY], null);
|
|
472
|
+
queryClient.invalidateQueries({ queryKey: ["behio", "orders"] });
|
|
473
|
+
queryClient.invalidateQueries({ queryKey: ["behio", "addresses"] });
|
|
474
|
+
}, [client, storage, queryClient]);
|
|
475
|
+
const postAuth = useCallback2(async () => {
|
|
476
|
+
await queryClient.invalidateQueries({ queryKey: [...CUSTOMER_KEY] });
|
|
477
|
+
if (client.getCartSession()) {
|
|
478
|
+
try {
|
|
479
|
+
await client.cart.merge();
|
|
480
|
+
client.clearCartSession();
|
|
481
|
+
storage.remove(STORAGE_KEYS.CART_SESSION);
|
|
482
|
+
} catch {
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
queryClient.invalidateQueries({ queryKey: [...CART_KEY3] });
|
|
486
|
+
}, [client, storage, queryClient]);
|
|
487
|
+
const loginMutation = useMutation2({
|
|
488
|
+
mutationFn: async ({ email, password }) => {
|
|
489
|
+
return client.auth.login({ email, password });
|
|
490
|
+
},
|
|
491
|
+
onSuccess: async (tokens) => {
|
|
492
|
+
persistTokens(tokens);
|
|
493
|
+
await postAuth();
|
|
494
|
+
}
|
|
495
|
+
});
|
|
496
|
+
const registerMutation = useMutation2({
|
|
497
|
+
mutationFn: async (input) => {
|
|
498
|
+
return client.auth.register(input);
|
|
499
|
+
},
|
|
500
|
+
onSuccess: async (tokens) => {
|
|
501
|
+
persistTokens(tokens);
|
|
502
|
+
await postAuth();
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
const logoutMutation = useMutation2({
|
|
506
|
+
mutationFn: () => client.auth.logout(),
|
|
507
|
+
onSettled: () => {
|
|
508
|
+
clearAuth();
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
const forgotPasswordMutation = useMutation2({
|
|
512
|
+
mutationFn: (email) => client.auth.forgotPassword(email)
|
|
513
|
+
});
|
|
514
|
+
const resetPasswordMutation = useMutation2({
|
|
515
|
+
mutationFn: ({ token, newPassword }) => client.auth.resetPassword(token, newPassword)
|
|
516
|
+
});
|
|
517
|
+
const verifyEmailMutation = useMutation2({
|
|
518
|
+
mutationFn: (token) => client.auth.verifyEmail(token)
|
|
519
|
+
});
|
|
520
|
+
const login = useCallback2(
|
|
521
|
+
(email, password) => loginMutation.mutateAsync({ email, password }).then(() => void 0),
|
|
522
|
+
[loginMutation]
|
|
523
|
+
);
|
|
524
|
+
const register = useCallback2(
|
|
525
|
+
(input) => registerMutation.mutateAsync(input).then(() => void 0),
|
|
526
|
+
[registerMutation]
|
|
527
|
+
);
|
|
528
|
+
const logout = useCallback2(
|
|
529
|
+
() => logoutMutation.mutateAsync().then(() => void 0),
|
|
530
|
+
[logoutMutation]
|
|
531
|
+
);
|
|
532
|
+
const forgotPassword = useCallback2(
|
|
533
|
+
(email) => forgotPasswordMutation.mutateAsync(email).then(() => void 0),
|
|
534
|
+
[forgotPasswordMutation]
|
|
535
|
+
);
|
|
536
|
+
const resetPassword = useCallback2(
|
|
537
|
+
(token, newPassword) => resetPasswordMutation.mutateAsync({ token, newPassword }).then(() => void 0),
|
|
538
|
+
[resetPasswordMutation]
|
|
539
|
+
);
|
|
540
|
+
const verifyEmail = useCallback2(
|
|
541
|
+
(token) => verifyEmailMutation.mutateAsync(token).then(() => void 0),
|
|
542
|
+
[verifyEmailMutation]
|
|
543
|
+
);
|
|
544
|
+
return {
|
|
545
|
+
isLoggedIn,
|
|
546
|
+
customer: customer ?? null,
|
|
547
|
+
isLoading,
|
|
548
|
+
// Actions
|
|
549
|
+
login,
|
|
550
|
+
register,
|
|
551
|
+
logout,
|
|
552
|
+
forgotPassword,
|
|
553
|
+
resetPassword,
|
|
554
|
+
verifyEmail,
|
|
555
|
+
// Mutation states
|
|
556
|
+
isLoggingIn: loginMutation.isPending,
|
|
557
|
+
isRegistering: registerMutation.isPending,
|
|
558
|
+
loginError: loginMutation.error,
|
|
559
|
+
registerError: registerMutation.error
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// src/react/hooks/use-customer.ts
|
|
564
|
+
import { useCallback as useCallback3 } from "react";
|
|
565
|
+
import { useQuery as useQuery11, useMutation as useMutation3, useQueryClient as useQueryClient4 } from "@tanstack/react-query";
|
|
566
|
+
var CUSTOMER_KEY2 = ["behio", "customer"];
|
|
567
|
+
function useCustomer() {
|
|
568
|
+
const { client } = useBehio();
|
|
569
|
+
const queryClient = useQueryClient4();
|
|
570
|
+
const {
|
|
571
|
+
data,
|
|
572
|
+
isLoading,
|
|
573
|
+
error
|
|
574
|
+
} = useQuery11({
|
|
575
|
+
queryKey: [...CUSTOMER_KEY2],
|
|
576
|
+
queryFn: () => client.customer.getProfile(),
|
|
577
|
+
enabled: !!client.getAccessToken()
|
|
578
|
+
});
|
|
579
|
+
const updateMutation = useMutation3({
|
|
580
|
+
mutationFn: (data2) => client.customer.updateProfile(data2),
|
|
581
|
+
onSuccess: (updated) => {
|
|
582
|
+
queryClient.setQueryData([...CUSTOMER_KEY2], updated);
|
|
583
|
+
}
|
|
584
|
+
});
|
|
585
|
+
const updateProfile = useCallback3(
|
|
586
|
+
(profileData) => updateMutation.mutateAsync(profileData),
|
|
587
|
+
[updateMutation]
|
|
588
|
+
);
|
|
589
|
+
return {
|
|
590
|
+
data: data ?? null,
|
|
591
|
+
isLoading,
|
|
592
|
+
error,
|
|
593
|
+
updateProfile,
|
|
594
|
+
isUpdating: updateMutation.isPending
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// src/react/hooks/use-addresses.ts
|
|
599
|
+
import { useCallback as useCallback4 } from "react";
|
|
600
|
+
import { useQuery as useQuery12, useMutation as useMutation4, useQueryClient as useQueryClient5 } from "@tanstack/react-query";
|
|
601
|
+
var ADDRESSES_KEY = ["behio", "addresses"];
|
|
602
|
+
function useAddresses() {
|
|
603
|
+
const { client } = useBehio();
|
|
604
|
+
const queryClient = useQueryClient5();
|
|
605
|
+
const {
|
|
606
|
+
data,
|
|
607
|
+
isLoading,
|
|
608
|
+
error
|
|
609
|
+
} = useQuery12({
|
|
610
|
+
queryKey: [...ADDRESSES_KEY],
|
|
611
|
+
queryFn: async () => {
|
|
612
|
+
const result = await client.customer.getAddresses();
|
|
613
|
+
return result.items;
|
|
614
|
+
},
|
|
615
|
+
enabled: !!client.getAccessToken()
|
|
616
|
+
});
|
|
617
|
+
const createMutation = useMutation4({
|
|
618
|
+
mutationFn: (address) => client.customer.createAddress(address),
|
|
619
|
+
onSuccess: () => {
|
|
620
|
+
queryClient.invalidateQueries({ queryKey: [...ADDRESSES_KEY] });
|
|
621
|
+
}
|
|
622
|
+
});
|
|
623
|
+
const updateMutation = useMutation4({
|
|
624
|
+
mutationFn: ({ addressId, data: data2 }) => client.customer.updateAddress(addressId, data2),
|
|
625
|
+
onSuccess: () => {
|
|
626
|
+
queryClient.invalidateQueries({ queryKey: [...ADDRESSES_KEY] });
|
|
627
|
+
}
|
|
628
|
+
});
|
|
629
|
+
const deleteMutation = useMutation4({
|
|
630
|
+
mutationFn: (addressId) => client.customer.deleteAddress(addressId),
|
|
631
|
+
onSuccess: () => {
|
|
632
|
+
queryClient.invalidateQueries({ queryKey: [...ADDRESSES_KEY] });
|
|
633
|
+
}
|
|
634
|
+
});
|
|
635
|
+
const createAddress = useCallback4(
|
|
636
|
+
(address) => createMutation.mutateAsync(address),
|
|
637
|
+
[createMutation]
|
|
638
|
+
);
|
|
639
|
+
const updateAddress = useCallback4(
|
|
640
|
+
(addressId, addressData) => updateMutation.mutateAsync({ addressId, data: addressData }),
|
|
641
|
+
[updateMutation]
|
|
642
|
+
);
|
|
643
|
+
const deleteAddress = useCallback4(
|
|
644
|
+
(addressId) => deleteMutation.mutateAsync(addressId),
|
|
645
|
+
[deleteMutation]
|
|
646
|
+
);
|
|
647
|
+
return {
|
|
648
|
+
addresses: data ?? [],
|
|
649
|
+
isLoading,
|
|
650
|
+
error,
|
|
651
|
+
createAddress,
|
|
652
|
+
updateAddress,
|
|
653
|
+
deleteAddress,
|
|
654
|
+
isCreating: createMutation.isPending,
|
|
655
|
+
isDeleting: deleteMutation.isPending
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// src/react/hooks/use-orders.ts
|
|
660
|
+
import { useQuery as useQuery13 } from "@tanstack/react-query";
|
|
661
|
+
function useOrders(options) {
|
|
662
|
+
const { client } = useBehio();
|
|
663
|
+
return useQuery13({
|
|
664
|
+
queryKey: ["behio", "orders", options?.page, options?.limit],
|
|
665
|
+
queryFn: () => client.orders.list({
|
|
666
|
+
page: options?.page,
|
|
667
|
+
limit: options?.limit
|
|
668
|
+
}),
|
|
669
|
+
enabled: (options?.enabled ?? true) && !!client.getAccessToken()
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// src/react/hooks/use-order.ts
|
|
674
|
+
import { useCallback as useCallback5 } from "react";
|
|
675
|
+
import { useQuery as useQuery14, useMutation as useMutation5, useQueryClient as useQueryClient6 } from "@tanstack/react-query";
|
|
676
|
+
function useOrder(orderNumber) {
|
|
677
|
+
const { client } = useBehio();
|
|
678
|
+
const queryClient = useQueryClient6();
|
|
679
|
+
const {
|
|
680
|
+
data,
|
|
681
|
+
isLoading,
|
|
682
|
+
error
|
|
683
|
+
} = useQuery14({
|
|
684
|
+
queryKey: ["behio", "order", orderNumber],
|
|
685
|
+
queryFn: () => client.orders.get(orderNumber),
|
|
686
|
+
enabled: !!orderNumber && !!client.getAccessToken()
|
|
687
|
+
});
|
|
688
|
+
const cancelMutation = useMutation5({
|
|
689
|
+
mutationFn: () => client.orders.cancel(orderNumber),
|
|
690
|
+
onSuccess: (updated) => {
|
|
691
|
+
queryClient.setQueryData(["behio", "order", orderNumber], updated);
|
|
692
|
+
queryClient.invalidateQueries({ queryKey: ["behio", "orders"] });
|
|
693
|
+
}
|
|
694
|
+
});
|
|
695
|
+
const cancel = useCallback5(
|
|
696
|
+
() => cancelMutation.mutateAsync(),
|
|
697
|
+
[cancelMutation]
|
|
698
|
+
);
|
|
699
|
+
return {
|
|
700
|
+
data: data ?? null,
|
|
701
|
+
isLoading,
|
|
702
|
+
error,
|
|
703
|
+
cancel,
|
|
704
|
+
isCancelling: cancelMutation.isPending
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// src/react/hooks/use-checkout.ts
|
|
709
|
+
import { useState as useState2, useCallback as useCallback6 } from "react";
|
|
710
|
+
import { useMutation as useMutation6, useQueryClient as useQueryClient7 } from "@tanstack/react-query";
|
|
711
|
+
function useCheckout() {
|
|
712
|
+
const { client, storage } = useBehio();
|
|
713
|
+
const queryClient = useQueryClient7();
|
|
714
|
+
const [order, setOrder] = useState2(null);
|
|
715
|
+
const mutation = useMutation6({
|
|
716
|
+
mutationFn: (input) => client.checkout.createOrder(input),
|
|
717
|
+
onSuccess: (result) => {
|
|
718
|
+
setOrder(result);
|
|
719
|
+
storage.remove(STORAGE_KEYS.CART_SESSION);
|
|
720
|
+
queryClient.invalidateQueries({ queryKey: ["behio", "cart"] });
|
|
721
|
+
queryClient.invalidateQueries({ queryKey: ["behio", "orders"] });
|
|
722
|
+
}
|
|
723
|
+
});
|
|
724
|
+
const createOrder = useCallback6(
|
|
725
|
+
(input) => mutation.mutateAsync(input),
|
|
726
|
+
[mutation]
|
|
727
|
+
);
|
|
728
|
+
const reset = useCallback6(() => {
|
|
729
|
+
setOrder(null);
|
|
730
|
+
mutation.reset();
|
|
731
|
+
}, [mutation]);
|
|
732
|
+
return {
|
|
733
|
+
createOrder,
|
|
734
|
+
isCreating: mutation.isPending,
|
|
735
|
+
error: mutation.error,
|
|
736
|
+
order,
|
|
737
|
+
reset
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
// src/react/hooks/use-pages.ts
|
|
742
|
+
import { useQuery as useQuery15 } from "@tanstack/react-query";
|
|
743
|
+
function usePages(locale) {
|
|
744
|
+
const { client } = useBehio();
|
|
745
|
+
return useQuery15({
|
|
746
|
+
queryKey: ["behio", "pages", locale],
|
|
747
|
+
queryFn: async () => {
|
|
748
|
+
const result = await client.pages.list(locale);
|
|
749
|
+
return result.pages;
|
|
750
|
+
}
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
function usePage(slug, locale) {
|
|
754
|
+
const { client } = useBehio();
|
|
755
|
+
return useQuery15({
|
|
756
|
+
queryKey: ["behio", "page", slug, locale],
|
|
757
|
+
queryFn: () => client.pages.get(slug, locale),
|
|
758
|
+
enabled: !!slug
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
// src/react/hooks/use-shop-info.ts
|
|
763
|
+
import { useQuery as useQuery16 } from "@tanstack/react-query";
|
|
764
|
+
function useShopInfo() {
|
|
765
|
+
const { client } = useBehio();
|
|
766
|
+
return useQuery16({
|
|
767
|
+
queryKey: ["behio", "shop-info"],
|
|
768
|
+
queryFn: () => client.getShopInfo()
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
// src/react/utils/format-price.ts
|
|
773
|
+
function formatPrice(amount, currency, locale) {
|
|
774
|
+
const resolvedLocale = locale ?? "cs";
|
|
775
|
+
try {
|
|
776
|
+
return new Intl.NumberFormat(resolvedLocale, {
|
|
777
|
+
style: "currency",
|
|
778
|
+
currency,
|
|
779
|
+
minimumFractionDigits: Number.isInteger(amount) ? 0 : 2,
|
|
780
|
+
maximumFractionDigits: 2
|
|
781
|
+
}).format(amount);
|
|
782
|
+
} catch {
|
|
783
|
+
return `${amount} ${currency}`;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
export {
|
|
787
|
+
BehioProvider,
|
|
788
|
+
cookieStorage,
|
|
789
|
+
createMemoryStorage,
|
|
790
|
+
detectStorage,
|
|
791
|
+
formatPrice,
|
|
792
|
+
localStorageAdapter,
|
|
793
|
+
memoryStorage,
|
|
794
|
+
useAddresses,
|
|
795
|
+
useAuth,
|
|
796
|
+
useBehio,
|
|
797
|
+
useCart,
|
|
798
|
+
useCartCount,
|
|
799
|
+
useCategories,
|
|
800
|
+
useCheckout,
|
|
801
|
+
useCustomer,
|
|
802
|
+
useFeatured,
|
|
803
|
+
useFilters,
|
|
804
|
+
useLabels,
|
|
805
|
+
useOrder,
|
|
806
|
+
useOrders,
|
|
807
|
+
usePage,
|
|
808
|
+
usePages,
|
|
809
|
+
useProduct,
|
|
810
|
+
useProducts,
|
|
811
|
+
useSearch,
|
|
812
|
+
useShopInfo
|
|
813
|
+
};
|