@doswiftly/storefront-sdk 4.4.0 → 4.5.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.
Files changed (89) hide show
  1. package/dist/core/cart/types.d.ts +53 -20
  2. package/dist/core/cart/types.d.ts.map +1 -1
  3. package/dist/core/cart/types.js +3 -0
  4. package/dist/core/operations/cart.d.ts +15 -9
  5. package/dist/core/operations/cart.d.ts.map +1 -1
  6. package/dist/core/operations/cart.js +130 -58
  7. package/dist/index.d.ts +1 -1
  8. package/dist/index.js +1 -1
  9. package/package.json +9 -4
  10. package/src/__tests__/contract/storefront-api.contract.test.ts +0 -450
  11. package/src/__tests__/unit/auth-client.test.ts +0 -210
  12. package/src/__tests__/unit/bot-protection.test.ts +0 -461
  13. package/src/__tests__/unit/cart-client.test.ts +0 -233
  14. package/src/__tests__/unit/cart-store.test.ts +0 -349
  15. package/src/__tests__/unit/create-client.test.ts +0 -356
  16. package/src/__tests__/unit/helpers.test.ts +0 -377
  17. package/src/__tests__/unit/middleware.test.ts +0 -374
  18. package/src/__tests__/unit/test-helpers.ts +0 -103
  19. package/src/core/auth/auth-client.ts +0 -123
  20. package/src/core/auth/cookie-config.ts +0 -23
  21. package/src/core/auth/handlers.ts +0 -168
  22. package/src/core/auth/routes.ts +0 -26
  23. package/src/core/auth/token-client.ts +0 -51
  24. package/src/core/auth/types.ts +0 -54
  25. package/src/core/bot-protection/abstract-manager.ts +0 -185
  26. package/src/core/bot-protection/create-manager.ts +0 -37
  27. package/src/core/bot-protection/eucaptcha-manager.ts +0 -88
  28. package/src/core/bot-protection/fallback-manager.ts +0 -43
  29. package/src/core/bot-protection/turnstile-manager.ts +0 -92
  30. package/src/core/bot-protection/types/eucaptcha.d.ts +0 -28
  31. package/src/core/bot-protection/types/turnstile.d.ts +0 -33
  32. package/src/core/cache.ts +0 -102
  33. package/src/core/cart/cart-client.ts +0 -150
  34. package/src/core/cart/cookie-config.ts +0 -13
  35. package/src/core/cart/types.ts +0 -104
  36. package/src/core/client/compose.ts +0 -15
  37. package/src/core/client/create-client.ts +0 -129
  38. package/src/core/client/dedupe.ts +0 -19
  39. package/src/core/client/execute.ts +0 -70
  40. package/src/core/client/hash.ts +0 -21
  41. package/src/core/client/operation-name.ts +0 -12
  42. package/src/core/client/types.ts +0 -171
  43. package/src/core/currency/cookie-config.ts +0 -13
  44. package/src/core/errors.ts +0 -67
  45. package/src/core/format.ts +0 -254
  46. package/src/core/helpers/assert-no-user-errors.ts +0 -21
  47. package/src/core/helpers/normalize-connection.ts +0 -48
  48. package/src/core/helpers/sanitize-html.ts +0 -42
  49. package/src/core/image.ts +0 -22
  50. package/src/core/index.ts +0 -174
  51. package/src/core/language/cookie-config.ts +0 -13
  52. package/src/core/middleware/auth.ts +0 -27
  53. package/src/core/middleware/bot-protection.ts +0 -140
  54. package/src/core/middleware/currency.ts +0 -27
  55. package/src/core/middleware/errors.ts +0 -86
  56. package/src/core/middleware/language.ts +0 -30
  57. package/src/core/middleware/retry.ts +0 -75
  58. package/src/core/middleware/timeout.ts +0 -61
  59. package/src/core/operations/auth.ts +0 -123
  60. package/src/core/operations/cart.ts +0 -185
  61. package/src/index.ts +0 -25
  62. package/src/react/bot-protection/bot-protection-context.ts +0 -17
  63. package/src/react/bot-protection/bot-protection-widget.tsx +0 -46
  64. package/src/react/cookies.ts +0 -89
  65. package/src/react/helpers/create-store-context.ts +0 -56
  66. package/src/react/hooks/use-auth.ts +0 -218
  67. package/src/react/hooks/use-bot-protection.ts +0 -31
  68. package/src/react/hooks/use-cart-manager.ts +0 -236
  69. package/src/react/hooks/use-currency.ts +0 -23
  70. package/src/react/hooks/use-debounced-value.ts +0 -30
  71. package/src/react/hooks/use-hydrated.ts +0 -20
  72. package/src/react/hooks/use-storefront-client.ts +0 -12
  73. package/src/react/index.ts +0 -71
  74. package/src/react/providers/currency-provider.tsx +0 -30
  75. package/src/react/providers/language-provider.tsx +0 -34
  76. package/src/react/providers/storefront-client-provider.tsx +0 -107
  77. package/src/react/providers/storefront-provider.tsx +0 -99
  78. package/src/react/server/get-storefront-client.ts +0 -60
  79. package/src/react/server/index.ts +0 -1
  80. package/src/react/stores/auth.store.ts +0 -112
  81. package/src/react/stores/cart.context.ts +0 -10
  82. package/src/react/stores/cart.store.ts +0 -254
  83. package/src/react/stores/currency.store.ts +0 -93
  84. package/src/react/stores/index.ts +0 -17
  85. package/src/react/stores/language.store.ts +0 -90
  86. package/src/react/stores/store-context.tsx +0 -103
  87. package/src/react/types/shop-config.ts +0 -22
  88. package/tsconfig.json +0 -20
  89. package/vitest.config.ts +0 -14
@@ -1,218 +0,0 @@
1
- /**
2
- * useAuth — wraps AuthClient + updates auth store.
3
- *
4
- * Centralizes login/logout/renew with dual-layer persistence:
5
- * - httpOnly cookie (for SSR/middleware) — via onSetToken/onClearToken callbacks
6
- * - Zustand store (for client-side state)
7
- *
8
- * Does NOT use React Query — plain async + store updates.
9
- * Template can wrap in useMutation() if React Query features are needed.
10
- *
11
- * @example
12
- * ```tsx
13
- * const { login, logout, isLoading } = useAuth();
14
- *
15
- * const result = await login('user@example.com', 'password');
16
- * if (result.success) router.push('/account');
17
- * ```
18
- */
19
-
20
- 'use client';
21
-
22
- import { useState, useCallback } from 'react';
23
- import { useStorefrontClientContext } from '../providers/storefront-client-provider';
24
- import { useAuthStore, useAuthStoreApi } from '../stores/store-context';
25
- import { StorefrontError } from '../../core/errors';
26
-
27
- export interface UseAuthOptions {
28
- /**
29
- * Called after successful login/renewToken with the new access token.
30
- * Use to set httpOnly cookie via API route.
31
- */
32
- onSetToken?: (token: string) => Promise<void>;
33
- /**
34
- * Called after logout to clear httpOnly cookie.
35
- */
36
- onClearToken?: () => Promise<void>;
37
- }
38
-
39
- export interface LoginResult {
40
- success: boolean;
41
- userErrors: Array<{ message: string; field?: string[] }>;
42
- accessToken?: string;
43
- expiresAt?: string;
44
- }
45
-
46
- export interface LogoutResult {
47
- success: boolean;
48
- userErrors: Array<{ message: string; field?: string[] }>;
49
- }
50
-
51
- export interface TokenRenewResult {
52
- success: boolean;
53
- userErrors: Array<{ message: string; field?: string[] }>;
54
- accessToken?: string;
55
- expiresAt?: string;
56
- }
57
-
58
- export function useAuth(options: UseAuthOptions = {}) {
59
- const { authClient } = useStorefrontClientContext();
60
- const { setAuth, clearAuth } = useAuthStore();
61
- const authStore = useAuthStoreApi();
62
-
63
- const [isLoggingIn, setIsLoggingIn] = useState(false);
64
- const [isLoggingOut, setIsLoggingOut] = useState(false);
65
- const [isRenewingToken, setIsRenewingToken] = useState(false);
66
- const [error, setError] = useState<string | null>(null);
67
-
68
- const login = useCallback(async (email: string, password: string): Promise<LoginResult> => {
69
- setError(null);
70
- setIsLoggingIn(true);
71
-
72
- try {
73
- const result = await authClient.login(email, password);
74
-
75
- // Set httpOnly cookie
76
- if (options.onSetToken) {
77
- await options.onSetToken(result.accessToken);
78
- }
79
-
80
- // Fetch customer data and set store
81
- try {
82
- const customer = await authClient.getCustomer(result.accessToken);
83
- if (customer) {
84
- setAuth(
85
- {
86
- id: customer.id,
87
- email: customer.email,
88
- firstName: customer.firstName ?? undefined,
89
- lastName: customer.lastName ?? undefined,
90
- phone: customer.phone ?? undefined,
91
- },
92
- result.accessToken,
93
- );
94
- } else {
95
- setAuth({ id: '', email }, result.accessToken);
96
- }
97
- } catch {
98
- // Customer fetch failed — store minimal data
99
- setAuth({ id: '', email }, result.accessToken);
100
- }
101
-
102
- return {
103
- success: true,
104
- userErrors: [],
105
- accessToken: result.accessToken,
106
- expiresAt: result.expiresAt,
107
- };
108
- } catch (err) {
109
- if (err instanceof StorefrontError && err.hasUserErrors) {
110
- return {
111
- success: false,
112
- userErrors: err.userErrors.map((e) => ({
113
- message: e.message,
114
- field: e.field,
115
- })),
116
- };
117
- }
118
-
119
- const message = err instanceof Error ? err.message : 'Login failed';
120
- setError(message);
121
- return { success: false, userErrors: [{ message }] };
122
- } finally {
123
- setIsLoggingIn(false);
124
- }
125
- }, [authClient, setAuth, options]);
126
-
127
- const logout = useCallback(async (): Promise<LogoutResult> => {
128
- setError(null);
129
- setIsLoggingOut(true);
130
-
131
- try {
132
- const token = authStore.getState().accessToken;
133
- if (token) {
134
- await authClient.logout(token);
135
- }
136
-
137
- // Clear httpOnly cookie
138
- if (options.onClearToken) {
139
- await options.onClearToken();
140
- }
141
-
142
- clearAuth();
143
-
144
- return { success: true, userErrors: [] };
145
- } catch (err) {
146
- // Even on error, clear local state
147
- clearAuth();
148
- const message = err instanceof Error ? err.message : 'Logout failed';
149
- setError(message);
150
- return { success: false, userErrors: [{ message }] };
151
- } finally {
152
- setIsLoggingOut(false);
153
- }
154
- }, [authClient, clearAuth, options, authStore]);
155
-
156
- const renewToken = useCallback(async (): Promise<TokenRenewResult> => {
157
- setError(null);
158
- setIsRenewingToken(true);
159
-
160
- try {
161
- const token = authStore.getState().accessToken;
162
- if (!token) {
163
- return {
164
- success: false,
165
- userErrors: [{ message: 'No token to renew' }],
166
- };
167
- }
168
-
169
- const result = await authClient.renewToken(token);
170
-
171
- // Update httpOnly cookie
172
- if (options.onSetToken) {
173
- await options.onSetToken(result.accessToken);
174
- }
175
-
176
- // Update store (keep customer data, update token)
177
- const currentCustomer = authStore.getState().customer;
178
- if (currentCustomer) {
179
- setAuth(currentCustomer, result.accessToken);
180
- }
181
-
182
- return {
183
- success: true,
184
- userErrors: [],
185
- accessToken: result.accessToken,
186
- expiresAt: result.expiresAt,
187
- };
188
- } catch (err) {
189
- if (err instanceof StorefrontError && err.hasUserErrors) {
190
- return {
191
- success: false,
192
- userErrors: err.userErrors.map((e) => ({
193
- message: e.message,
194
- field: e.field,
195
- })),
196
- };
197
- }
198
-
199
- const message = err instanceof Error ? err.message : 'Token renewal failed';
200
- setError(message);
201
- return { success: false, userErrors: [{ message }] };
202
- } finally {
203
- setIsRenewingToken(false);
204
- }
205
- }, [authClient, setAuth, options, authStore]);
206
-
207
- return {
208
- login,
209
- logout,
210
- renewToken,
211
-
212
- isLoggingIn,
213
- isLoggingOut,
214
- isRenewingToken,
215
- isLoading: isLoggingIn || isLoggingOut || isRenewingToken,
216
- error,
217
- };
218
- }
@@ -1,31 +0,0 @@
1
- /**
2
- * useBotProtection — escape hatch hook for custom bot protection use cases.
3
- *
4
- * Normally the middleware handles token injection automatically.
5
- * Use this hook only when you need manual control (e.g. custom forms).
6
- */
7
-
8
- 'use client';
9
-
10
- import { useContext, useCallback } from 'react';
11
- import { BotProtectionContext } from '../bot-protection/bot-protection-context';
12
-
13
- export function useBotProtection() {
14
- const ctx = useContext(BotProtectionContext);
15
- const manager = ctx?.manager ?? null;
16
-
17
- const execute = useCallback(
18
- (options?: { action?: string; timeoutMs?: number }) => {
19
- if (!manager) return Promise.resolve(null);
20
- return manager.execute(options);
21
- },
22
- [manager],
23
- );
24
-
25
- return {
26
- /** Execute a bot protection challenge and get a token */
27
- execute,
28
- /** Whether bot protection is configured and available */
29
- isAvailable: !!manager,
30
- };
31
- }
@@ -1,236 +0,0 @@
1
- /**
2
- * useCartManager — wraps CartClient with cart ID persistence + loading states.
3
- *
4
- * Auto-creates cart on first add. CartId persisted in cookie (SSR/edge visible).
5
- * Does NOT use React Query — plain async + useState.
6
- * Template wraps in useMutation() if React Query features are needed.
7
- *
8
- * @example
9
- * ```tsx
10
- * const { addItem, updateQuantity, removeItem, isLoading } = useCartManager();
11
- *
12
- * await addItem([{ merchandiseId: 'variant-123', quantity: 1 }]);
13
- * ```
14
- */
15
-
16
- 'use client';
17
-
18
- import { useState, useCallback } from 'react';
19
- import { useStorefrontClientContext } from '../providers/storefront-client-provider';
20
- import type { Cart, CartLineInput, CartLineUpdateInput, CartCreateInput, CartBuyerIdentityInput } from '../../core/cart/types';
21
- import { StorefrontError } from '../../core/errors';
22
-
23
- // ---------------------------------------------------------------------------
24
- // Cart ID persistence (cookie — SSR/edge visible)
25
- // ---------------------------------------------------------------------------
26
-
27
- function getCartIdFromCookie(): string | null {
28
- if (typeof document === 'undefined') return null;
29
- const match = document.cookie.match(/(?:^|;\s*)cart-id=([^;]*)/);
30
- return match ? decodeURIComponent(match[1]) : null;
31
- }
32
-
33
- function setCartIdCookie(cartId: string): void {
34
- if (typeof document === 'undefined') return;
35
- const maxAge = 30 * 24 * 60 * 60; // 30 days
36
- document.cookie = `cart-id=${encodeURIComponent(cartId)};max-age=${maxAge};path=/;samesite=lax`;
37
- }
38
-
39
- function clearCartIdCookie(): void {
40
- if (typeof document === 'undefined') return;
41
- document.cookie = 'cart-id=;max-age=0;path=/';
42
- }
43
-
44
- export function useCartManager() {
45
- const { cartClient } = useStorefrontClientContext();
46
- const [isLoading, setIsLoading] = useState(false);
47
- const [error, setError] = useState<string | null>(null);
48
-
49
- /**
50
- * Get existing cart ID from cookie or create a new cart.
51
- */
52
- const getOrCreateCartId = useCallback(async (forceNew = false): Promise<string> => {
53
- if (!forceNew) {
54
- const existing = getCartIdFromCookie();
55
- if (existing) return existing;
56
- }
57
-
58
- const cart = await cartClient.create();
59
- setCartIdCookie(cart.id);
60
- return cart.id;
61
- }, [cartClient]);
62
-
63
- /**
64
- * Check if error indicates cart not found (expired).
65
- */
66
- const isCartExpired = (err: unknown): boolean => {
67
- if (err instanceof StorefrontError) {
68
- return err.message.toLowerCase().includes('cart not found') ||
69
- err.message.toLowerCase().includes('cart does not exist');
70
- }
71
- return false;
72
- };
73
-
74
- /**
75
- * Fetch current cart. Returns null if no cart exists.
76
- */
77
- const getCart = useCallback(async (): Promise<Cart | null> => {
78
- const cartId = getCartIdFromCookie();
79
- if (!cartId) return null;
80
-
81
- try {
82
- return await cartClient.get(cartId);
83
- } catch (err) {
84
- if (isCartExpired(err)) {
85
- clearCartIdCookie();
86
- return null;
87
- }
88
- throw err;
89
- }
90
- }, [cartClient]);
91
-
92
- /**
93
- * Add items to cart. Creates cart if needed.
94
- * On expired cart, clears cookie, creates new cart, retries once.
95
- */
96
- const addItem = useCallback(async (
97
- lines: CartLineInput[],
98
- options?: { forceNewCart?: boolean },
99
- ): Promise<Cart> => {
100
- setError(null);
101
- setIsLoading(true);
102
-
103
- try {
104
- const cartId = await getOrCreateCartId(options?.forceNewCart);
105
- const cart = await cartClient.addItems(cartId, lines);
106
- return cart;
107
- } catch (err) {
108
- if (isCartExpired(err) && !options?.forceNewCart) {
109
- clearCartIdCookie();
110
- return addItem(lines, { forceNewCart: true });
111
- }
112
-
113
- const message = err instanceof Error ? err.message : 'Failed to add to cart';
114
- setError(message);
115
- throw err;
116
- } finally {
117
- setIsLoading(false);
118
- }
119
- }, [cartClient, getOrCreateCartId]);
120
-
121
- /**
122
- * Update line items (quantity, attributes).
123
- */
124
- const updateItem = useCallback(async (
125
- lines: CartLineUpdateInput[],
126
- ): Promise<Cart> => {
127
- setError(null);
128
- setIsLoading(true);
129
-
130
- try {
131
- const cartId = getCartIdFromCookie();
132
- if (!cartId) throw new Error('No cart found');
133
- return await cartClient.updateItems(cartId, lines);
134
- } catch (err) {
135
- if (isCartExpired(err)) {
136
- clearCartIdCookie();
137
- }
138
- const message = err instanceof Error ? err.message : 'Failed to update cart';
139
- setError(message);
140
- throw err;
141
- } finally {
142
- setIsLoading(false);
143
- }
144
- }, [cartClient]);
145
-
146
- /**
147
- * Remove items by line IDs.
148
- */
149
- const removeItem = useCallback(async (lineIds: string[]): Promise<Cart> => {
150
- setError(null);
151
- setIsLoading(true);
152
-
153
- try {
154
- const cartId = getCartIdFromCookie();
155
- if (!cartId) throw new Error('No cart found');
156
- return await cartClient.removeItems(cartId, lineIds);
157
- } catch (err) {
158
- if (isCartExpired(err)) {
159
- clearCartIdCookie();
160
- }
161
- const message = err instanceof Error ? err.message : 'Failed to remove from cart';
162
- setError(message);
163
- throw err;
164
- } finally {
165
- setIsLoading(false);
166
- }
167
- }, [cartClient]);
168
-
169
- /**
170
- * Update discount codes (replaces all existing).
171
- */
172
- const updateDiscountCodes = useCallback(async (codes: string[]): Promise<Cart> => {
173
- setError(null);
174
- setIsLoading(true);
175
-
176
- try {
177
- const cartId = getCartIdFromCookie();
178
- if (!cartId) throw new Error('No cart found');
179
- return await cartClient.updateDiscountCodes(cartId, codes);
180
- } catch (err) {
181
- const message = err instanceof Error ? err.message : 'Failed to update discount codes';
182
- setError(message);
183
- throw err;
184
- } finally {
185
- setIsLoading(false);
186
- }
187
- }, [cartClient]);
188
-
189
- /**
190
- * Update cart note.
191
- */
192
- const updateNote = useCallback(async (note: string): Promise<Cart> => {
193
- setError(null);
194
- setIsLoading(true);
195
-
196
- try {
197
- const cartId = getCartIdFromCookie();
198
- if (!cartId) throw new Error('No cart found');
199
- return await cartClient.updateNote(cartId, note);
200
- } catch (err) {
201
- const message = err instanceof Error ? err.message : 'Failed to update note';
202
- setError(message);
203
- throw err;
204
- } finally {
205
- setIsLoading(false);
206
- }
207
- }, [cartClient]);
208
-
209
- /**
210
- * Clear cart — removes cookie.
211
- */
212
- const clearCart = useCallback(() => {
213
- clearCartIdCookie();
214
- }, []);
215
-
216
- /**
217
- * Get current cart ID from cookie (if exists).
218
- */
219
- const getCartId = useCallback((): string | null => {
220
- return getCartIdFromCookie();
221
- }, []);
222
-
223
- return {
224
- getCart,
225
- addItem,
226
- updateItem,
227
- removeItem,
228
- updateDiscountCodes,
229
- updateNote,
230
- clearCart,
231
- getCartId,
232
-
233
- isLoading,
234
- error,
235
- };
236
- }
@@ -1,23 +0,0 @@
1
- /**
2
- * useCurrency — convenience hook for currency state.
3
- */
4
-
5
- 'use client';
6
-
7
- import { useCurrencyStore } from '../stores/store-context';
8
-
9
- export function useCurrency() {
10
- const currency = useCurrencyStore((s) => s.currency);
11
- const baseCurrency = useCurrencyStore((s) => s.baseCurrency);
12
- const supportedCurrencies = useCurrencyStore((s) => s.supportedCurrencies);
13
- const setCurrency = useCurrencyStore((s) => s.setCurrency);
14
- const isLoaded = useCurrencyStore((s) => s.isLoaded);
15
-
16
- return {
17
- currency,
18
- baseCurrency,
19
- supportedCurrencies,
20
- setCurrency,
21
- isLoaded,
22
- };
23
- }
@@ -1,30 +0,0 @@
1
- 'use client';
2
-
3
- import { useState, useEffect } from 'react';
4
-
5
- /**
6
- * Debounce a value.
7
- *
8
- * @param value - Value to debounce
9
- * @param delay - Delay in ms (default: 300)
10
- * @returns Debounced value
11
- *
12
- * @example
13
- * ```tsx
14
- * const [query, setQuery] = useState("");
15
- * const debouncedQuery = useDebouncedValue(query, 300);
16
- * ```
17
- */
18
- export function useDebouncedValue<T>(value: T, delay = 300): T {
19
- const [debouncedValue, setDebouncedValue] = useState(value);
20
-
21
- useEffect(() => {
22
- const timer = setTimeout(() => {
23
- setDebouncedValue(value);
24
- }, delay);
25
-
26
- return () => clearTimeout(timer);
27
- }, [value, delay]);
28
-
29
- return debouncedValue;
30
- }
@@ -1,20 +0,0 @@
1
- 'use client';
2
-
3
- import { useSyncExternalStore } from 'react';
4
-
5
- const emptySubscribe = () => () => {};
6
-
7
- /**
8
- * Returns false during SSR and first client render,
9
- * then true after hydration completes.
10
- *
11
- * Use this to guard any content that depends on browser-only state
12
- * (localStorage, cookies, window) to prevent hydration mismatches.
13
- */
14
- export function useHydrated() {
15
- return useSyncExternalStore(
16
- emptySubscribe,
17
- () => true, // Client: true
18
- () => false, // Server: false
19
- );
20
- }
@@ -1,12 +0,0 @@
1
- /**
2
- * useStorefrontClient — access StorefrontClient from context.
3
- */
4
-
5
- 'use client';
6
-
7
- import { useStorefrontClientContext } from '../providers/storefront-client-provider';
8
- import type { StorefrontClient } from '../../core/client/types';
9
-
10
- export function useStorefrontClient(): StorefrontClient {
11
- return useStorefrontClientContext().client;
12
- }
@@ -1,71 +0,0 @@
1
- /**
2
- * @doswiftly/storefront-sdk/react — React adapter
3
- *
4
- * Provides React providers, Zustand stores, and hooks
5
- * that wrap the framework-agnostic core.
6
- *
7
- * Peer dependencies: react ^18 || ^19, zustand ^5
8
- *
9
- * @example
10
- * ```tsx
11
- * import { StorefrontProvider, useAuth, useCartManager, useCurrency } from '@doswiftly/storefront-sdk/react';
12
- * ```
13
- */
14
-
15
- // Providers
16
- export { StorefrontProvider, type StorefrontProviderProps } from './providers/storefront-provider';
17
- export { StorefrontClientProvider, type StorefrontClientProviderProps } from './providers/storefront-client-provider';
18
- export { CurrencyProvider, type CurrencyProviderProps } from './providers/currency-provider';
19
- export { LanguageProvider, type LanguageProviderProps } from './providers/language-provider';
20
-
21
- // Hooks
22
- export { useAuth, type UseAuthOptions, type LoginResult, type LogoutResult, type TokenRenewResult } from './hooks/use-auth';
23
- export { useCartManager } from './hooks/use-cart-manager';
24
- export { useStorefrontClient } from './hooks/use-storefront-client';
25
- export { useCurrency } from './hooks/use-currency';
26
-
27
- // Store hooks (Context-based)
28
- export { useAuthStore, useAuthStoreApi, useAuthHydrated } from './stores/store-context';
29
- export { useCurrencyStore, useCurrencyStoreApi } from './stores/store-context';
30
- export { useLanguageStore, useLanguageStoreApi } from './stores/store-context';
31
-
32
- // Store types
33
- export type { AuthStore, CustomerInfo } from './stores/auth.store';
34
- export type { CurrencyStore, ShopCurrencyData } from './stores/currency.store';
35
- export type { LanguageStore } from './stores/language.store';
36
- export type { ShopConfig } from './types/shop-config';
37
-
38
- // Selectors
39
- export { selectCurrency, selectBaseCurrency, selectSupportedCurrencies, selectIsLoaded } from './stores/currency.store';
40
- export { selectLanguage, selectDefaultLanguage, selectSupportedLanguages, selectLanguageIsLoaded } from './stores/language.store';
41
-
42
- // Cookie utilities
43
- export { getCookie, setCookie, deleteCookie, getCurrencyFromCookieAsync, getCartIdFromCookieAsync } from './cookies';
44
-
45
- // Bot protection
46
- export { useBotProtection } from './hooks/use-bot-protection';
47
-
48
- // Generic hooks
49
- export { useHydrated } from './hooks/use-hydrated';
50
- export { useDebouncedValue } from './hooks/use-debounced-value';
51
-
52
- // Cart store (DI-based)
53
- export {
54
- createCartStore,
55
- selectCartId,
56
- selectIsCartOpen,
57
- selectCartIsLoading,
58
- } from './stores/cart.store';
59
- export type {
60
- CartState,
61
- CartStoreConfig,
62
- CartActions,
63
- CartData,
64
- CartMutationAction,
65
- CartLineInput,
66
- CartLineUpdateInput,
67
- } from './stores/cart.store';
68
- export { CartProvider, useCartStore, useCartStoreApi } from './stores/cart.context';
69
-
70
- // Store context helper
71
- export { createStoreContext } from './helpers/create-store-context';
@@ -1,30 +0,0 @@
1
- /**
2
- * CurrencyProvider — initializes currency store from Shop data.
3
- *
4
- * Thin wrapper that calls useCurrencyStore.initialize() on mount
5
- * with the shop's currency configuration from the server.
6
- */
7
-
8
- 'use client';
9
-
10
- import React, { useEffect } from 'react';
11
- import { useCurrencyStore } from '../stores/store-context';
12
- import type { ShopCurrencyData } from '../stores/currency.store';
13
-
14
- export interface CurrencyProviderProps {
15
- children: React.ReactNode;
16
- shopData: ShopCurrencyData;
17
- }
18
-
19
- export function CurrencyProvider({ children, shopData }: CurrencyProviderProps) {
20
- const initialize = useCurrencyStore((s) => s.initialize);
21
- const isLoaded = useCurrencyStore((s) => s.isLoaded);
22
-
23
- useEffect(() => {
24
- if (!isLoaded) {
25
- initialize(shopData);
26
- }
27
- }, [initialize, isLoaded, shopData]);
28
-
29
- return <>{children}</>;
30
- }