@doswiftly/storefront-sdk 4.0.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 +430 -0
- package/dist/__tests__/unit/test-helpers.d.ts +46 -0
- package/dist/__tests__/unit/test-helpers.d.ts.map +1 -0
- package/dist/__tests__/unit/test-helpers.js +72 -0
- package/dist/core/auth/auth-client.d.ts +46 -0
- package/dist/core/auth/auth-client.d.ts.map +1 -0
- package/dist/core/auth/auth-client.js +82 -0
- package/dist/core/auth/cookie-config.d.ts +18 -0
- package/dist/core/auth/cookie-config.d.ts.map +1 -0
- package/dist/core/auth/cookie-config.js +18 -0
- package/dist/core/auth/handlers.d.ts +32 -0
- package/dist/core/auth/handlers.d.ts.map +1 -0
- package/dist/core/auth/handlers.js +127 -0
- package/dist/core/auth/routes.d.ts +21 -0
- package/dist/core/auth/routes.d.ts.map +1 -0
- package/dist/core/auth/routes.js +14 -0
- package/dist/core/auth/token-client.d.ts +26 -0
- package/dist/core/auth/token-client.d.ts.map +1 -0
- package/dist/core/auth/token-client.js +42 -0
- package/dist/core/auth/types.d.ts +53 -0
- package/dist/core/auth/types.d.ts.map +1 -0
- package/dist/core/auth/types.js +4 -0
- package/dist/core/cache.d.ts +54 -0
- package/dist/core/cache.d.ts.map +1 -0
- package/dist/core/cache.js +82 -0
- package/dist/core/cart/cart-client.d.ts +57 -0
- package/dist/core/cart/cart-client.d.ts.map +1 -0
- package/dist/core/cart/cart-client.js +89 -0
- package/dist/core/cart/types.d.ts +110 -0
- package/dist/core/cart/types.d.ts.map +1 -0
- package/dist/core/cart/types.js +6 -0
- package/dist/core/client/compose.d.ts +9 -0
- package/dist/core/client/compose.d.ts.map +1 -0
- package/dist/core/client/compose.js +9 -0
- package/dist/core/client/create-client.d.ts +15 -0
- package/dist/core/client/create-client.d.ts.map +1 -0
- package/dist/core/client/create-client.js +85 -0
- package/dist/core/client/dedupe.d.ts +7 -0
- package/dist/core/client/dedupe.d.ts.map +1 -0
- package/dist/core/client/dedupe.js +16 -0
- package/dist/core/client/execute.d.ts +20 -0
- package/dist/core/client/execute.d.ts.map +1 -0
- package/dist/core/client/execute.js +48 -0
- package/dist/core/client/hash.d.ts +7 -0
- package/dist/core/client/hash.d.ts.map +1 -0
- package/dist/core/client/hash.js +21 -0
- package/dist/core/client/operation-name.d.ts +7 -0
- package/dist/core/client/operation-name.d.ts.map +1 -0
- package/dist/core/client/operation-name.js +10 -0
- package/dist/core/client/types.d.ts +126 -0
- package/dist/core/client/types.d.ts.map +1 -0
- package/dist/core/client/types.js +26 -0
- package/dist/core/errors.d.ts +43 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +43 -0
- package/dist/core/format.d.ts +92 -0
- package/dist/core/format.d.ts.map +1 -0
- package/dist/core/format.js +216 -0
- package/dist/core/helpers/assert-no-user-errors.d.ts +10 -0
- package/dist/core/helpers/assert-no-user-errors.d.ts.map +1 -0
- package/dist/core/helpers/assert-no-user-errors.js +16 -0
- package/dist/core/helpers/normalize-connection.d.ts +36 -0
- package/dist/core/helpers/normalize-connection.d.ts.map +1 -0
- package/dist/core/helpers/normalize-connection.js +21 -0
- package/dist/core/helpers/sanitize-html.d.ts +8 -0
- package/dist/core/helpers/sanitize-html.d.ts.map +1 -0
- package/dist/core/helpers/sanitize-html.js +35 -0
- package/dist/core/index.d.ts +59 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +68 -0
- package/dist/core/middleware/auth.d.ts +16 -0
- package/dist/core/middleware/auth.d.ts.map +1 -0
- package/dist/core/middleware/auth.js +22 -0
- package/dist/core/middleware/currency.d.ts +15 -0
- package/dist/core/middleware/currency.d.ts.map +1 -0
- package/dist/core/middleware/currency.js +21 -0
- package/dist/core/middleware/errors.d.ts +24 -0
- package/dist/core/middleware/errors.d.ts.map +1 -0
- package/dist/core/middleware/errors.js +77 -0
- package/dist/core/middleware/retry.d.ts +22 -0
- package/dist/core/middleware/retry.d.ts.map +1 -0
- package/dist/core/middleware/retry.js +58 -0
- package/dist/core/middleware/timeout.d.ts +19 -0
- package/dist/core/middleware/timeout.d.ts.map +1 -0
- package/dist/core/middleware/timeout.js +51 -0
- package/dist/core/operations/auth.d.ts +11 -0
- package/dist/core/operations/auth.d.ts.map +1 -0
- package/dist/core/operations/auth.js +112 -0
- package/dist/core/operations/cart.d.ts +15 -0
- package/dist/core/operations/cart.d.ts.map +1 -0
- package/dist/core/operations/cart.js +169 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/react/cookies.d.ts +28 -0
- package/dist/react/cookies.d.ts.map +1 -0
- package/dist/react/cookies.js +49 -0
- package/dist/react/helpers/create-store-context.d.ts +37 -0
- package/dist/react/helpers/create-store-context.d.ts.map +1 -0
- package/dist/react/helpers/create-store-context.js +47 -0
- package/dist/react/hooks/use-auth.d.ts +65 -0
- package/dist/react/hooks/use-auth.d.ts.map +1 -0
- package/dist/react/hooks/use-auth.js +168 -0
- package/dist/react/hooks/use-cart-manager.d.ts +30 -0
- package/dist/react/hooks/use-cart-manager.d.ts.map +1 -0
- package/dist/react/hooks/use-cart-manager.js +223 -0
- package/dist/react/hooks/use-currency.d.ts +11 -0
- package/dist/react/hooks/use-currency.d.ts.map +1 -0
- package/dist/react/hooks/use-currency.js +19 -0
- package/dist/react/hooks/use-debounced-value.d.ts +15 -0
- package/dist/react/hooks/use-debounced-value.d.ts.map +1 -0
- package/dist/react/hooks/use-debounced-value.js +25 -0
- package/dist/react/hooks/use-hydrated.d.ts +9 -0
- package/dist/react/hooks/use-hydrated.d.ts.map +1 -0
- package/dist/react/hooks/use-hydrated.js +14 -0
- package/dist/react/hooks/use-storefront-client.d.ts +6 -0
- package/dist/react/hooks/use-storefront-client.d.ts.map +1 -0
- package/dist/react/hooks/use-storefront-client.js +8 -0
- package/dist/react/index.d.ts +30 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +34 -0
- package/dist/react/providers/currency-provider.d.ts +14 -0
- package/dist/react/providers/currency-provider.d.ts.map +1 -0
- package/dist/react/providers/currency-provider.js +20 -0
- package/dist/react/providers/storefront-client-provider.d.ts +33 -0
- package/dist/react/providers/storefront-client-provider.d.ts.map +1 -0
- package/dist/react/providers/storefront-client-provider.js +57 -0
- package/dist/react/providers/storefront-provider.d.ts +42 -0
- package/dist/react/providers/storefront-provider.d.ts.map +1 -0
- package/dist/react/providers/storefront-provider.js +40 -0
- package/dist/react/server/get-storefront-client.d.ts +42 -0
- package/dist/react/server/get-storefront-client.d.ts.map +1 -0
- package/dist/react/server/get-storefront-client.js +44 -0
- package/dist/react/server/index.d.ts +2 -0
- package/dist/react/server/index.d.ts.map +1 -0
- package/dist/react/server/index.js +1 -0
- package/dist/react/stores/auth.store.d.ts +48 -0
- package/dist/react/stores/auth.store.d.ts.map +1 -0
- package/dist/react/stores/auth.store.js +67 -0
- package/dist/react/stores/currency.store.d.ts +29 -0
- package/dist/react/stores/currency.store.d.ts.map +1 -0
- package/dist/react/stores/currency.store.js +76 -0
- package/dist/react/stores/index.d.ts +8 -0
- package/dist/react/stores/index.d.ts.map +1 -0
- package/dist/react/stores/index.js +10 -0
- package/dist/react/stores/store-context.d.ts +27 -0
- package/dist/react/stores/store-context.d.ts.map +1 -0
- package/dist/react/stores/store-context.js +62 -0
- package/package.json +71 -0
- package/src/__tests__/contract/storefront-api.contract.test.ts +450 -0
- package/src/__tests__/unit/auth-client.test.ts +210 -0
- package/src/__tests__/unit/cart-client.test.ts +233 -0
- package/src/__tests__/unit/create-client.test.ts +356 -0
- package/src/__tests__/unit/helpers.test.ts +377 -0
- package/src/__tests__/unit/middleware.test.ts +374 -0
- package/src/__tests__/unit/test-helpers.ts +103 -0
- package/src/core/auth/auth-client.ts +123 -0
- package/src/core/auth/cookie-config.ts +23 -0
- package/src/core/auth/handlers.ts +168 -0
- package/src/core/auth/routes.ts +26 -0
- package/src/core/auth/token-client.ts +51 -0
- package/src/core/auth/types.ts +54 -0
- package/src/core/cache.ts +102 -0
- package/src/core/cart/cart-client.ts +150 -0
- package/src/core/cart/types.ts +104 -0
- package/src/core/client/compose.ts +15 -0
- package/src/core/client/create-client.ts +129 -0
- package/src/core/client/dedupe.ts +19 -0
- package/src/core/client/execute.ts +70 -0
- package/src/core/client/hash.ts +21 -0
- package/src/core/client/operation-name.ts +12 -0
- package/src/core/client/types.ts +171 -0
- package/src/core/errors.ts +67 -0
- package/src/core/format.ts +254 -0
- package/src/core/helpers/assert-no-user-errors.ts +21 -0
- package/src/core/helpers/normalize-connection.ts +48 -0
- package/src/core/helpers/sanitize-html.ts +42 -0
- package/src/core/index.ts +148 -0
- package/src/core/middleware/auth.ts +27 -0
- package/src/core/middleware/currency.ts +26 -0
- package/src/core/middleware/errors.ts +86 -0
- package/src/core/middleware/retry.ts +75 -0
- package/src/core/middleware/timeout.ts +61 -0
- package/src/core/operations/auth.ts +123 -0
- package/src/core/operations/cart.ts +185 -0
- package/src/index.ts +25 -0
- package/src/react/cookies.ts +54 -0
- package/src/react/helpers/create-store-context.ts +56 -0
- package/src/react/hooks/use-auth.ts +218 -0
- package/src/react/hooks/use-cart-manager.ts +236 -0
- package/src/react/hooks/use-currency.ts +23 -0
- package/src/react/hooks/use-debounced-value.ts +30 -0
- package/src/react/hooks/use-hydrated.ts +20 -0
- package/src/react/hooks/use-storefront-client.ts +12 -0
- package/src/react/index.ts +45 -0
- package/src/react/providers/currency-provider.tsx +30 -0
- package/src/react/providers/storefront-client-provider.tsx +90 -0
- package/src/react/providers/storefront-provider.tsx +71 -0
- package/src/react/server/get-storefront-client.ts +60 -0
- package/src/react/server/index.ts +1 -0
- package/src/react/stores/auth.store.ts +112 -0
- package/src/react/stores/currency.store.ts +113 -0
- package/src/react/stores/index.ts +17 -0
- package/src/react/stores/store-context.tsx +82 -0
- package/tsconfig.json +20 -0
- package/vitest.config.ts +14 -0
|
@@ -0,0 +1,223 @@
|
|
|
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
|
+
'use client';
|
|
16
|
+
import { useState, useCallback } from 'react';
|
|
17
|
+
import { useStorefrontClientContext } from '../providers/storefront-client-provider';
|
|
18
|
+
import { StorefrontError } from '../../core/errors';
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// Cart ID persistence (cookie — SSR/edge visible)
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
function getCartIdFromCookie() {
|
|
23
|
+
if (typeof document === 'undefined')
|
|
24
|
+
return null;
|
|
25
|
+
const match = document.cookie.match(/(?:^|;\s*)cart-id=([^;]*)/);
|
|
26
|
+
return match ? decodeURIComponent(match[1]) : null;
|
|
27
|
+
}
|
|
28
|
+
function setCartIdCookie(cartId) {
|
|
29
|
+
if (typeof document === 'undefined')
|
|
30
|
+
return;
|
|
31
|
+
const maxAge = 30 * 24 * 60 * 60; // 30 days
|
|
32
|
+
document.cookie = `cart-id=${encodeURIComponent(cartId)};max-age=${maxAge};path=/;samesite=lax`;
|
|
33
|
+
}
|
|
34
|
+
function clearCartIdCookie() {
|
|
35
|
+
if (typeof document === 'undefined')
|
|
36
|
+
return;
|
|
37
|
+
document.cookie = 'cart-id=;max-age=0;path=/';
|
|
38
|
+
}
|
|
39
|
+
export function useCartManager() {
|
|
40
|
+
const { cartClient } = useStorefrontClientContext();
|
|
41
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
42
|
+
const [error, setError] = useState(null);
|
|
43
|
+
/**
|
|
44
|
+
* Get existing cart ID from cookie or create a new cart.
|
|
45
|
+
*/
|
|
46
|
+
const getOrCreateCartId = useCallback(async (forceNew = false) => {
|
|
47
|
+
if (!forceNew) {
|
|
48
|
+
const existing = getCartIdFromCookie();
|
|
49
|
+
if (existing)
|
|
50
|
+
return existing;
|
|
51
|
+
}
|
|
52
|
+
const cart = await cartClient.create();
|
|
53
|
+
setCartIdCookie(cart.id);
|
|
54
|
+
return cart.id;
|
|
55
|
+
}, [cartClient]);
|
|
56
|
+
/**
|
|
57
|
+
* Check if error indicates cart not found (expired).
|
|
58
|
+
*/
|
|
59
|
+
const isCartExpired = (err) => {
|
|
60
|
+
if (err instanceof StorefrontError) {
|
|
61
|
+
return err.message.toLowerCase().includes('cart not found') ||
|
|
62
|
+
err.message.toLowerCase().includes('cart does not exist');
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Fetch current cart. Returns null if no cart exists.
|
|
68
|
+
*/
|
|
69
|
+
const getCart = useCallback(async () => {
|
|
70
|
+
const cartId = getCartIdFromCookie();
|
|
71
|
+
if (!cartId)
|
|
72
|
+
return null;
|
|
73
|
+
try {
|
|
74
|
+
return await cartClient.get(cartId);
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
if (isCartExpired(err)) {
|
|
78
|
+
clearCartIdCookie();
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
throw err;
|
|
82
|
+
}
|
|
83
|
+
}, [cartClient]);
|
|
84
|
+
/**
|
|
85
|
+
* Add items to cart. Creates cart if needed.
|
|
86
|
+
* On expired cart, clears cookie, creates new cart, retries once.
|
|
87
|
+
*/
|
|
88
|
+
const addItem = useCallback(async (lines, options) => {
|
|
89
|
+
setError(null);
|
|
90
|
+
setIsLoading(true);
|
|
91
|
+
try {
|
|
92
|
+
const cartId = await getOrCreateCartId(options?.forceNewCart);
|
|
93
|
+
const cart = await cartClient.addItems(cartId, lines);
|
|
94
|
+
return cart;
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
if (isCartExpired(err) && !options?.forceNewCart) {
|
|
98
|
+
clearCartIdCookie();
|
|
99
|
+
return addItem(lines, { forceNewCart: true });
|
|
100
|
+
}
|
|
101
|
+
const message = err instanceof Error ? err.message : 'Failed to add to cart';
|
|
102
|
+
setError(message);
|
|
103
|
+
throw err;
|
|
104
|
+
}
|
|
105
|
+
finally {
|
|
106
|
+
setIsLoading(false);
|
|
107
|
+
}
|
|
108
|
+
}, [cartClient, getOrCreateCartId]);
|
|
109
|
+
/**
|
|
110
|
+
* Update line items (quantity, attributes).
|
|
111
|
+
*/
|
|
112
|
+
const updateItem = useCallback(async (lines) => {
|
|
113
|
+
setError(null);
|
|
114
|
+
setIsLoading(true);
|
|
115
|
+
try {
|
|
116
|
+
const cartId = getCartIdFromCookie();
|
|
117
|
+
if (!cartId)
|
|
118
|
+
throw new Error('No cart found');
|
|
119
|
+
return await cartClient.updateItems(cartId, lines);
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
if (isCartExpired(err)) {
|
|
123
|
+
clearCartIdCookie();
|
|
124
|
+
}
|
|
125
|
+
const message = err instanceof Error ? err.message : 'Failed to update cart';
|
|
126
|
+
setError(message);
|
|
127
|
+
throw err;
|
|
128
|
+
}
|
|
129
|
+
finally {
|
|
130
|
+
setIsLoading(false);
|
|
131
|
+
}
|
|
132
|
+
}, [cartClient]);
|
|
133
|
+
/**
|
|
134
|
+
* Remove items by line IDs.
|
|
135
|
+
*/
|
|
136
|
+
const removeItem = useCallback(async (lineIds) => {
|
|
137
|
+
setError(null);
|
|
138
|
+
setIsLoading(true);
|
|
139
|
+
try {
|
|
140
|
+
const cartId = getCartIdFromCookie();
|
|
141
|
+
if (!cartId)
|
|
142
|
+
throw new Error('No cart found');
|
|
143
|
+
return await cartClient.removeItems(cartId, lineIds);
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
if (isCartExpired(err)) {
|
|
147
|
+
clearCartIdCookie();
|
|
148
|
+
}
|
|
149
|
+
const message = err instanceof Error ? err.message : 'Failed to remove from cart';
|
|
150
|
+
setError(message);
|
|
151
|
+
throw err;
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
setIsLoading(false);
|
|
155
|
+
}
|
|
156
|
+
}, [cartClient]);
|
|
157
|
+
/**
|
|
158
|
+
* Update discount codes (replaces all existing).
|
|
159
|
+
*/
|
|
160
|
+
const updateDiscountCodes = useCallback(async (codes) => {
|
|
161
|
+
setError(null);
|
|
162
|
+
setIsLoading(true);
|
|
163
|
+
try {
|
|
164
|
+
const cartId = getCartIdFromCookie();
|
|
165
|
+
if (!cartId)
|
|
166
|
+
throw new Error('No cart found');
|
|
167
|
+
return await cartClient.updateDiscountCodes(cartId, codes);
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
const message = err instanceof Error ? err.message : 'Failed to update discount codes';
|
|
171
|
+
setError(message);
|
|
172
|
+
throw err;
|
|
173
|
+
}
|
|
174
|
+
finally {
|
|
175
|
+
setIsLoading(false);
|
|
176
|
+
}
|
|
177
|
+
}, [cartClient]);
|
|
178
|
+
/**
|
|
179
|
+
* Update cart note.
|
|
180
|
+
*/
|
|
181
|
+
const updateNote = useCallback(async (note) => {
|
|
182
|
+
setError(null);
|
|
183
|
+
setIsLoading(true);
|
|
184
|
+
try {
|
|
185
|
+
const cartId = getCartIdFromCookie();
|
|
186
|
+
if (!cartId)
|
|
187
|
+
throw new Error('No cart found');
|
|
188
|
+
return await cartClient.updateNote(cartId, note);
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
const message = err instanceof Error ? err.message : 'Failed to update note';
|
|
192
|
+
setError(message);
|
|
193
|
+
throw err;
|
|
194
|
+
}
|
|
195
|
+
finally {
|
|
196
|
+
setIsLoading(false);
|
|
197
|
+
}
|
|
198
|
+
}, [cartClient]);
|
|
199
|
+
/**
|
|
200
|
+
* Clear cart — removes cookie.
|
|
201
|
+
*/
|
|
202
|
+
const clearCart = useCallback(() => {
|
|
203
|
+
clearCartIdCookie();
|
|
204
|
+
}, []);
|
|
205
|
+
/**
|
|
206
|
+
* Get current cart ID from cookie (if exists).
|
|
207
|
+
*/
|
|
208
|
+
const getCartId = useCallback(() => {
|
|
209
|
+
return getCartIdFromCookie();
|
|
210
|
+
}, []);
|
|
211
|
+
return {
|
|
212
|
+
getCart,
|
|
213
|
+
addItem,
|
|
214
|
+
updateItem,
|
|
215
|
+
removeItem,
|
|
216
|
+
updateDiscountCodes,
|
|
217
|
+
updateNote,
|
|
218
|
+
clearCart,
|
|
219
|
+
getCartId,
|
|
220
|
+
isLoading,
|
|
221
|
+
error,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useCurrency — convenience hook for currency state.
|
|
3
|
+
*/
|
|
4
|
+
export declare function useCurrency(): {
|
|
5
|
+
currency: string | null;
|
|
6
|
+
baseCurrency: string | null;
|
|
7
|
+
supportedCurrencies: string[];
|
|
8
|
+
setCurrency: (currency: string) => void;
|
|
9
|
+
isLoaded: boolean;
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=use-currency.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-currency.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/use-currency.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,wBAAgB,WAAW;;;;;;EAc1B"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useCurrency — convenience hook for currency state.
|
|
3
|
+
*/
|
|
4
|
+
'use client';
|
|
5
|
+
import { useCurrencyStore } from '../stores/store-context';
|
|
6
|
+
export function useCurrency() {
|
|
7
|
+
const currency = useCurrencyStore((s) => s.currency);
|
|
8
|
+
const baseCurrency = useCurrencyStore((s) => s.baseCurrency);
|
|
9
|
+
const supportedCurrencies = useCurrencyStore((s) => s.supportedCurrencies);
|
|
10
|
+
const setCurrency = useCurrencyStore((s) => s.setCurrency);
|
|
11
|
+
const isLoaded = useCurrencyStore((s) => s.isLoaded);
|
|
12
|
+
return {
|
|
13
|
+
currency,
|
|
14
|
+
baseCurrency,
|
|
15
|
+
supportedCurrencies,
|
|
16
|
+
setCurrency,
|
|
17
|
+
isLoaded,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debounce a value.
|
|
3
|
+
*
|
|
4
|
+
* @param value - Value to debounce
|
|
5
|
+
* @param delay - Delay in ms (default: 300)
|
|
6
|
+
* @returns Debounced value
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* const [query, setQuery] = useState("");
|
|
11
|
+
* const debouncedQuery = useDebouncedValue(query, 300);
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare function useDebouncedValue<T>(value: T, delay?: number): T;
|
|
15
|
+
//# sourceMappingURL=use-debounced-value.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-debounced-value.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/use-debounced-value.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,SAAM,GAAG,CAAC,CAY7D"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Debounce a value.
|
|
5
|
+
*
|
|
6
|
+
* @param value - Value to debounce
|
|
7
|
+
* @param delay - Delay in ms (default: 300)
|
|
8
|
+
* @returns Debounced value
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* const [query, setQuery] = useState("");
|
|
13
|
+
* const debouncedQuery = useDebouncedValue(query, 300);
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export function useDebouncedValue(value, delay = 300) {
|
|
17
|
+
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
const timer = setTimeout(() => {
|
|
20
|
+
setDebouncedValue(value);
|
|
21
|
+
}, delay);
|
|
22
|
+
return () => clearTimeout(timer);
|
|
23
|
+
}, [value, delay]);
|
|
24
|
+
return debouncedValue;
|
|
25
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns false during SSR and first client render,
|
|
3
|
+
* then true after hydration completes.
|
|
4
|
+
*
|
|
5
|
+
* Use this to guard any content that depends on browser-only state
|
|
6
|
+
* (localStorage, cookies, window) to prevent hydration mismatches.
|
|
7
|
+
*/
|
|
8
|
+
export declare function useHydrated(): boolean;
|
|
9
|
+
//# sourceMappingURL=use-hydrated.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-hydrated.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/use-hydrated.ts"],"names":[],"mappings":"AAMA;;;;;;GAMG;AACH,wBAAgB,WAAW,YAM1B"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useSyncExternalStore } from 'react';
|
|
3
|
+
const emptySubscribe = () => () => { };
|
|
4
|
+
/**
|
|
5
|
+
* Returns false during SSR and first client render,
|
|
6
|
+
* then true after hydration completes.
|
|
7
|
+
*
|
|
8
|
+
* Use this to guard any content that depends on browser-only state
|
|
9
|
+
* (localStorage, cookies, window) to prevent hydration mismatches.
|
|
10
|
+
*/
|
|
11
|
+
export function useHydrated() {
|
|
12
|
+
return useSyncExternalStore(emptySubscribe, () => true, // Client: true
|
|
13
|
+
() => false);
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-storefront-client.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/use-storefront-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,wBAAgB,mBAAmB,IAAI,gBAAgB,CAEtD"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useStorefrontClient — access StorefrontClient from context.
|
|
3
|
+
*/
|
|
4
|
+
'use client';
|
|
5
|
+
import { useStorefrontClientContext } from '../providers/storefront-client-provider';
|
|
6
|
+
export function useStorefrontClient() {
|
|
7
|
+
return useStorefrontClientContext().client;
|
|
8
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
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
|
+
export { StorefrontProvider, type StorefrontProviderProps } from './providers/storefront-provider';
|
|
15
|
+
export { StorefrontClientProvider, type StorefrontClientProviderProps } from './providers/storefront-client-provider';
|
|
16
|
+
export { CurrencyProvider, type CurrencyProviderProps } from './providers/currency-provider';
|
|
17
|
+
export { useAuth, type UseAuthOptions, type LoginResult, type LogoutResult, type TokenRenewResult } from './hooks/use-auth';
|
|
18
|
+
export { useCartManager } from './hooks/use-cart-manager';
|
|
19
|
+
export { useStorefrontClient } from './hooks/use-storefront-client';
|
|
20
|
+
export { useCurrency } from './hooks/use-currency';
|
|
21
|
+
export { useAuthStore, useAuthStoreApi, useAuthHydrated } from './stores/store-context';
|
|
22
|
+
export { useCurrencyStore, useCurrencyStoreApi } from './stores/store-context';
|
|
23
|
+
export type { AuthStore, CustomerInfo } from './stores/auth.store';
|
|
24
|
+
export type { CurrencyStore, ShopCurrencyData } from './stores/currency.store';
|
|
25
|
+
export { selectCurrency, selectBaseCurrency, selectSupportedCurrencies, selectIsLoaded } from './stores/currency.store';
|
|
26
|
+
export { getCookie, setCookie, deleteCookie, getCurrencyFromCookieAsync } from './cookies';
|
|
27
|
+
export { useHydrated } from './hooks/use-hydrated';
|
|
28
|
+
export { useDebouncedValue } from './hooks/use-debounced-value';
|
|
29
|
+
export { createStoreContext } from './helpers/create-store-context';
|
|
30
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,kBAAkB,EAAE,KAAK,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AACnG,OAAO,EAAE,wBAAwB,EAAE,KAAK,6BAA6B,EAAE,MAAM,wCAAwC,CAAC;AACtH,OAAO,EAAE,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAG7F,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC5H,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGnD,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACxF,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAG/E,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAG/E,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGxH,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AAG3F,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAGhE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
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
|
+
// Providers
|
|
15
|
+
export { StorefrontProvider } from './providers/storefront-provider';
|
|
16
|
+
export { StorefrontClientProvider } from './providers/storefront-client-provider';
|
|
17
|
+
export { CurrencyProvider } from './providers/currency-provider';
|
|
18
|
+
// Hooks
|
|
19
|
+
export { useAuth } from './hooks/use-auth';
|
|
20
|
+
export { useCartManager } from './hooks/use-cart-manager';
|
|
21
|
+
export { useStorefrontClient } from './hooks/use-storefront-client';
|
|
22
|
+
export { useCurrency } from './hooks/use-currency';
|
|
23
|
+
// Store hooks (Context-based)
|
|
24
|
+
export { useAuthStore, useAuthStoreApi, useAuthHydrated } from './stores/store-context';
|
|
25
|
+
export { useCurrencyStore, useCurrencyStoreApi } from './stores/store-context';
|
|
26
|
+
// Selectors
|
|
27
|
+
export { selectCurrency, selectBaseCurrency, selectSupportedCurrencies, selectIsLoaded } from './stores/currency.store';
|
|
28
|
+
// Cookie utilities
|
|
29
|
+
export { getCookie, setCookie, deleteCookie, getCurrencyFromCookieAsync } from './cookies';
|
|
30
|
+
// Generic hooks
|
|
31
|
+
export { useHydrated } from './hooks/use-hydrated';
|
|
32
|
+
export { useDebouncedValue } from './hooks/use-debounced-value';
|
|
33
|
+
// Store context helper
|
|
34
|
+
export { createStoreContext } from './helpers/create-store-context';
|
|
@@ -0,0 +1,14 @@
|
|
|
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
|
+
import React from 'react';
|
|
8
|
+
import type { ShopCurrencyData } from '../stores/currency.store';
|
|
9
|
+
export interface CurrencyProviderProps {
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
shopData: ShopCurrencyData;
|
|
12
|
+
}
|
|
13
|
+
export declare function CurrencyProvider({ children, shopData }: CurrencyProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
//# sourceMappingURL=currency-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"currency-provider.d.ts","sourceRoot":"","sources":["../../../src/react/providers/currency-provider.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAoB,MAAM,OAAO,CAAC;AAEzC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,QAAQ,EAAE,gBAAgB,CAAC;CAC5B;AAED,wBAAgB,gBAAgB,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,qBAAqB,2CAW7E"}
|
|
@@ -0,0 +1,20 @@
|
|
|
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
|
+
'use client';
|
|
8
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
9
|
+
import { useEffect } from 'react';
|
|
10
|
+
import { useCurrencyStore } from '../stores/store-context';
|
|
11
|
+
export function CurrencyProvider({ children, shopData }) {
|
|
12
|
+
const initialize = useCurrencyStore((s) => s.initialize);
|
|
13
|
+
const isLoaded = useCurrencyStore((s) => s.isLoaded);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
if (!isLoaded) {
|
|
16
|
+
initialize(shopData);
|
|
17
|
+
}
|
|
18
|
+
}, [initialize, isLoaded, shopData]);
|
|
19
|
+
return _jsx(_Fragment, { children: children });
|
|
20
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StorefrontClientProvider — React context for SDK clients.
|
|
3
|
+
*
|
|
4
|
+
* Creates StorefrontClient + CartClient + AuthClient and provides them
|
|
5
|
+
* to the component tree via React context.
|
|
6
|
+
*
|
|
7
|
+
* Registers default middleware pipeline: auth → currency → retry → timeout → errors.
|
|
8
|
+
*/
|
|
9
|
+
import React from 'react';
|
|
10
|
+
import { CartClient } from '../../core/cart/cart-client';
|
|
11
|
+
import { AuthClient } from '../../core/auth/auth-client';
|
|
12
|
+
import type { StorefrontClient, StorefrontClientConfig, Middleware } from '../../core/client/types';
|
|
13
|
+
export interface StorefrontClientContextValue {
|
|
14
|
+
client: StorefrontClient;
|
|
15
|
+
cartClient: CartClient;
|
|
16
|
+
authClient: AuthClient;
|
|
17
|
+
}
|
|
18
|
+
export interface StorefrontClientProviderProps {
|
|
19
|
+
children: React.ReactNode;
|
|
20
|
+
config: StorefrontClientConfig;
|
|
21
|
+
/**
|
|
22
|
+
* Additional middleware to prepend to the default pipeline.
|
|
23
|
+
* Default pipeline: auth → currency → [custom] → retry → timeout → errors
|
|
24
|
+
*/
|
|
25
|
+
middleware?: Middleware[];
|
|
26
|
+
}
|
|
27
|
+
export declare function StorefrontClientProvider({ children, config, middleware: customMiddleware, }: StorefrontClientProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
28
|
+
/**
|
|
29
|
+
* Get StorefrontClient context value.
|
|
30
|
+
* Must be used within StorefrontClientProvider.
|
|
31
|
+
*/
|
|
32
|
+
export declare function useStorefrontClientContext(): StorefrontClientContextValue;
|
|
33
|
+
//# sourceMappingURL=storefront-client-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storefront-client-provider.d.ts","sourceRoot":"","sources":["../../../src/react/providers/storefront-client-provider.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAA6C,MAAM,OAAO,CAAC;AAElE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAOzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAEpG,MAAM,WAAW,4BAA4B;IAC3C,MAAM,EAAE,gBAAgB,CAAC;IACzB,UAAU,EAAE,UAAU,CAAC;IACvB,UAAU,EAAE,UAAU,CAAC;CACxB;AAID,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,EAAE,sBAAsB,CAAC;IAC/B;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED,wBAAgB,wBAAwB,CAAC,EACvC,QAAQ,EACR,MAAM,EACN,UAAU,EAAE,gBAAqB,GAClC,EAAE,6BAA6B,2CAgC/B;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,IAAI,4BAA4B,CAMzE"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StorefrontClientProvider — React context for SDK clients.
|
|
3
|
+
*
|
|
4
|
+
* Creates StorefrontClient + CartClient + AuthClient and provides them
|
|
5
|
+
* to the component tree via React context.
|
|
6
|
+
*
|
|
7
|
+
* Registers default middleware pipeline: auth → currency → retry → timeout → errors.
|
|
8
|
+
*/
|
|
9
|
+
'use client';
|
|
10
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
11
|
+
import { createContext, useContext, useMemo } from 'react';
|
|
12
|
+
import { createStorefrontClient } from '../../core/client/create-client';
|
|
13
|
+
import { CartClient } from '../../core/cart/cart-client';
|
|
14
|
+
import { AuthClient } from '../../core/auth/auth-client';
|
|
15
|
+
import { authMiddleware } from '../../core/middleware/auth';
|
|
16
|
+
import { currencyMiddleware } from '../../core/middleware/currency';
|
|
17
|
+
import { retryMiddleware } from '../../core/middleware/retry';
|
|
18
|
+
import { timeoutMiddleware } from '../../core/middleware/timeout';
|
|
19
|
+
import { errorMiddleware } from '../../core/middleware/errors';
|
|
20
|
+
import { useAuthStoreApi, useCurrencyStoreApi } from '../stores/store-context';
|
|
21
|
+
const StorefrontClientContext = createContext(null);
|
|
22
|
+
export function StorefrontClientProvider({ children, config, middleware: customMiddleware = [], }) {
|
|
23
|
+
const authStore = useAuthStoreApi();
|
|
24
|
+
const currencyStore = useCurrencyStoreApi();
|
|
25
|
+
const value = useMemo(() => {
|
|
26
|
+
const client = createStorefrontClient({
|
|
27
|
+
...config,
|
|
28
|
+
middleware: [
|
|
29
|
+
// Header middleware (runs first)
|
|
30
|
+
authMiddleware(() => authStore.getState().accessToken),
|
|
31
|
+
currencyMiddleware(() => currencyStore.getState().currency),
|
|
32
|
+
// Custom middleware from props
|
|
33
|
+
...customMiddleware,
|
|
34
|
+
// Infrastructure middleware (runs last)
|
|
35
|
+
retryMiddleware({ maxRetries: 2 }),
|
|
36
|
+
timeoutMiddleware({ timeout: 5000 }),
|
|
37
|
+
errorMiddleware(),
|
|
38
|
+
],
|
|
39
|
+
});
|
|
40
|
+
const cartClient = new CartClient(client);
|
|
41
|
+
const authClient = new AuthClient(client);
|
|
42
|
+
return { client, cartClient, authClient };
|
|
43
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
44
|
+
}, [config.apiUrl, config.shopSlug, authStore, currencyStore]);
|
|
45
|
+
return (_jsx(StorefrontClientContext.Provider, { value: value, children: children }));
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get StorefrontClient context value.
|
|
49
|
+
* Must be used within StorefrontClientProvider.
|
|
50
|
+
*/
|
|
51
|
+
export function useStorefrontClientContext() {
|
|
52
|
+
const ctx = useContext(StorefrontClientContext);
|
|
53
|
+
if (!ctx) {
|
|
54
|
+
throw new Error('useStorefrontClientContext must be used within StorefrontClientProvider');
|
|
55
|
+
}
|
|
56
|
+
return ctx;
|
|
57
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StorefrontProvider — convenience composition of all SDK providers.
|
|
3
|
+
*
|
|
4
|
+
* Creates store instances via useRef (stable across re-renders) and provides
|
|
5
|
+
* them through React Context. Store Contexts wrap StorefrontClientProvider
|
|
6
|
+
* so that middleware can access store state via useAuthStoreApi/useCurrencyStoreApi.
|
|
7
|
+
*
|
|
8
|
+
* Composition order: Store Contexts → StorefrontClientProvider → CurrencyProvider
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* // app/layout.tsx
|
|
13
|
+
* import { StorefrontProvider } from '@doswiftly/storefront-sdk/react';
|
|
14
|
+
*
|
|
15
|
+
* export default async function RootLayout({ children }) {
|
|
16
|
+
* const shopData = await fetchShop();
|
|
17
|
+
* return (
|
|
18
|
+
* <StorefrontProvider
|
|
19
|
+
* config={{ apiUrl: '...', shopSlug: '...' }}
|
|
20
|
+
* shopData={shopData}
|
|
21
|
+
* >
|
|
22
|
+
* {children}
|
|
23
|
+
* </StorefrontProvider>
|
|
24
|
+
* );
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
import { type StorefrontClientProviderProps } from './storefront-client-provider';
|
|
29
|
+
import { type CurrencyProviderProps } from './currency-provider';
|
|
30
|
+
export interface StorefrontProviderProps extends StorefrontClientProviderProps {
|
|
31
|
+
shopData: CurrencyProviderProps['shopData'];
|
|
32
|
+
/**
|
|
33
|
+
* Server-side auth hint — set to `true` when httpOnly auth cookie exists.
|
|
34
|
+
* This allows the auth store to start with `isAuthenticated: true` on first render,
|
|
35
|
+
* eliminating the flash of "Sign In" while Zustand persist rehydrates from localStorage.
|
|
36
|
+
*
|
|
37
|
+
* Read from cookies() in a Server Component (layout.tsx) and pass here.
|
|
38
|
+
*/
|
|
39
|
+
initialIsAuthenticated?: boolean;
|
|
40
|
+
}
|
|
41
|
+
export declare function StorefrontProvider({ children, config, middleware, shopData, initialIsAuthenticated, }: StorefrontProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
42
|
+
//# sourceMappingURL=storefront-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storefront-provider.d.ts","sourceRoot":"","sources":["../../../src/react/providers/storefront-provider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAQH,OAAO,EAA4B,KAAK,6BAA6B,EAAE,MAAM,8BAA8B,CAAC;AAC5G,OAAO,EAAoB,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAEnF,MAAM,WAAW,uBAAwB,SAAQ,6BAA6B;IAC5E,QAAQ,EAAE,qBAAqB,CAAC,UAAU,CAAC,CAAC;IAC5C;;;;;;OAMG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,MAAM,EACN,UAAU,EACV,QAAQ,EACR,sBAAsB,GACvB,EAAE,uBAAuB,2CAezB"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StorefrontProvider — convenience composition of all SDK providers.
|
|
3
|
+
*
|
|
4
|
+
* Creates store instances via useRef (stable across re-renders) and provides
|
|
5
|
+
* them through React Context. Store Contexts wrap StorefrontClientProvider
|
|
6
|
+
* so that middleware can access store state via useAuthStoreApi/useCurrencyStoreApi.
|
|
7
|
+
*
|
|
8
|
+
* Composition order: Store Contexts → StorefrontClientProvider → CurrencyProvider
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* // app/layout.tsx
|
|
13
|
+
* import { StorefrontProvider } from '@doswiftly/storefront-sdk/react';
|
|
14
|
+
*
|
|
15
|
+
* export default async function RootLayout({ children }) {
|
|
16
|
+
* const shopData = await fetchShop();
|
|
17
|
+
* return (
|
|
18
|
+
* <StorefrontProvider
|
|
19
|
+
* config={{ apiUrl: '...', shopSlug: '...' }}
|
|
20
|
+
* shopData={shopData}
|
|
21
|
+
* >
|
|
22
|
+
* {children}
|
|
23
|
+
* </StorefrontProvider>
|
|
24
|
+
* );
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
'use client';
|
|
29
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
30
|
+
import { useRef } from 'react';
|
|
31
|
+
import { AuthStoreContext, CurrencyStoreContext } from '../stores/store-context';
|
|
32
|
+
import { createAuthStore } from '../stores/auth.store';
|
|
33
|
+
import { createCurrencyStore } from '../stores/currency.store';
|
|
34
|
+
import { StorefrontClientProvider } from './storefront-client-provider';
|
|
35
|
+
import { CurrencyProvider } from './currency-provider';
|
|
36
|
+
export function StorefrontProvider({ children, config, middleware, shopData, initialIsAuthenticated, }) {
|
|
37
|
+
const authStoreRef = useRef(createAuthStore(initialIsAuthenticated));
|
|
38
|
+
const currencyStoreRef = useRef(createCurrencyStore());
|
|
39
|
+
return (_jsx(AuthStoreContext.Provider, { value: authStoreRef.current, children: _jsx(CurrencyStoreContext.Provider, { value: currencyStoreRef.current, children: _jsx(StorefrontClientProvider, { config: config, middleware: middleware, children: _jsx(CurrencyProvider, { shopData: shopData, children: children }) }) }) }));
|
|
40
|
+
}
|