@doswiftly/storefront-sdk 18.1.0 → 19.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/CHANGELOG.md +129 -0
- package/dist/core/client/create-client.d.ts.map +1 -1
- package/dist/core/client/create-client.js +8 -1
- package/dist/core/client/remote-debug-transport.d.ts +48 -0
- package/dist/core/client/remote-debug-transport.d.ts.map +1 -0
- package/dist/core/client/remote-debug-transport.js +198 -0
- package/dist/core/client/types.d.ts +51 -1
- package/dist/core/client/types.d.ts.map +1 -1
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -0
- package/dist/react/cookies.d.ts +16 -23
- package/dist/react/cookies.d.ts.map +1 -1
- package/dist/react/cookies.js +16 -51
- package/dist/react/hooks/use-cart-manager.d.ts +7 -0
- package/dist/react/hooks/use-cart-manager.d.ts.map +1 -1
- package/dist/react/hooks/use-cart-manager.js +5 -2
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +3 -2
- package/dist/react/providers/cart-manager-provider.d.ts +8 -1
- package/dist/react/providers/cart-manager-provider.d.ts.map +1 -1
- package/dist/react/providers/cart-manager-provider.js +2 -1
- package/dist/react/providers/storefront-provider.d.ts +12 -1
- package/dist/react/providers/storefront-provider.d.ts.map +1 -1
- package/dist/react/providers/storefront-provider.js +4 -3
- package/dist/react/server/cookie-readers.d.ts +29 -0
- package/dist/react/server/cookie-readers.d.ts.map +1 -0
- package/dist/react/server/cookie-readers.js +52 -0
- package/dist/react/server/index.d.ts +1 -0
- package/dist/react/server/index.d.ts.map +1 -1
- package/dist/react/server/index.js +2 -0
- package/dist/react/stores/currency.store.d.ts +6 -1
- package/dist/react/stores/currency.store.d.ts.map +1 -1
- package/dist/react/stores/currency.store.js +49 -41
- package/dist/react/stores/language.store.d.ts +6 -1
- package/dist/react/stores/language.store.d.ts.map +1 -1
- package/dist/react/stores/language.store.js +46 -38
- package/package.json +1 -1
package/dist/react/cookies.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Client-side cookie utilities for SDK consumers.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Synchronous read/write over `document.cookie`, SSR-safe via a `typeof document`
|
|
5
|
+
* guard (return null / no-op when there is no document). To read these cookies in
|
|
6
|
+
* a Next.js Server Component use the `@doswiftly/storefront-sdk/react/server`
|
|
7
|
+
* entry (`readCartIdCookie`, `readCurrencyCookie`).
|
|
6
8
|
*/
|
|
7
9
|
/**
|
|
8
10
|
* Get cookie value by name (client-side only).
|
|
@@ -35,8 +37,8 @@ export function deleteCookie(name, path = '/') {
|
|
|
35
37
|
return;
|
|
36
38
|
document.cookie = `${name}=;max-age=0;path=${path}`;
|
|
37
39
|
}
|
|
38
|
-
import { CURRENCY_COOKIE_NAME } from '../core/currency/cookie-config';
|
|
39
40
|
import { CART_COOKIE_NAME, CART_COOKIE_MAX_AGE } from '../core/cart/cookie-config';
|
|
41
|
+
import { cookieDebugEvent } from '../core/client/remote-debug-transport';
|
|
40
42
|
/**
|
|
41
43
|
* Build a browser-side `CartCookieStore` backed by `document.cookie`.
|
|
42
44
|
*
|
|
@@ -56,55 +58,18 @@ import { CART_COOKIE_NAME, CART_COOKIE_MAX_AGE } from '../core/cart/cookie-confi
|
|
|
56
58
|
* });
|
|
57
59
|
* ```
|
|
58
60
|
*/
|
|
59
|
-
export function createBrowserCartCookieStore() {
|
|
61
|
+
export function createBrowserCartCookieStore(options) {
|
|
62
|
+
const emit = options?.onDebug;
|
|
60
63
|
return {
|
|
61
64
|
get: () => getCookie(CART_COOKIE_NAME),
|
|
62
|
-
set: (cartId,
|
|
63
|
-
|
|
65
|
+
set: (cartId, setOptions) => {
|
|
66
|
+
const maxAge = setOptions?.maxAge ?? CART_COOKIE_MAX_AGE;
|
|
67
|
+
setCookie(CART_COOKIE_NAME, cartId, { maxAge });
|
|
68
|
+
emit?.(cookieDebugEvent(CART_COOKIE_NAME, 'set', cartId, maxAge));
|
|
69
|
+
},
|
|
70
|
+
clear: () => {
|
|
71
|
+
deleteCookie(CART_COOKIE_NAME);
|
|
72
|
+
emit?.(cookieDebugEvent(CART_COOKIE_NAME, 'clear'));
|
|
64
73
|
},
|
|
65
|
-
clear: () => deleteCookie(CART_COOKIE_NAME),
|
|
66
74
|
};
|
|
67
75
|
}
|
|
68
|
-
/**
|
|
69
|
-
* Get preferred currency from cookie (async — works with Next.js cookies()).
|
|
70
|
-
* Falls back to document.cookie on client.
|
|
71
|
-
*/
|
|
72
|
-
export async function getCurrencyFromCookieAsync() {
|
|
73
|
-
// Server-side: try Next.js cookies()
|
|
74
|
-
try {
|
|
75
|
-
const { cookies } = await import('next/headers');
|
|
76
|
-
const cookieStore = await cookies();
|
|
77
|
-
return cookieStore.get(CURRENCY_COOKIE_NAME)?.value ?? null;
|
|
78
|
-
}
|
|
79
|
-
catch {
|
|
80
|
-
// Not in a server context or next not available
|
|
81
|
-
}
|
|
82
|
-
// Client-side fallback
|
|
83
|
-
return getCookie(CURRENCY_COOKIE_NAME);
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Get cart ID from cookie (async — works with Next.js cookies()).
|
|
87
|
-
* Falls back to document.cookie on client.
|
|
88
|
-
*
|
|
89
|
-
* Use in Server Components for SSR cart badge:
|
|
90
|
-
* ```typescript
|
|
91
|
-
* const cartId = await getCartIdFromCookieAsync();
|
|
92
|
-
* if (cartId) {
|
|
93
|
-
* const cart = await fetchCart(cartId);
|
|
94
|
-
* // Render cart badge with real totalQuantity — no skeleton needed
|
|
95
|
-
* }
|
|
96
|
-
* ```
|
|
97
|
-
*/
|
|
98
|
-
export async function getCartIdFromCookieAsync() {
|
|
99
|
-
// Server-side: try Next.js cookies()
|
|
100
|
-
try {
|
|
101
|
-
const { cookies } = await import('next/headers');
|
|
102
|
-
const cookieStore = await cookies();
|
|
103
|
-
return cookieStore.get(CART_COOKIE_NAME)?.value ?? null;
|
|
104
|
-
}
|
|
105
|
-
catch {
|
|
106
|
-
// Not in a server context or next not available
|
|
107
|
-
}
|
|
108
|
-
// Client-side fallback
|
|
109
|
-
return getCookie(CART_COOKIE_NAME);
|
|
110
|
-
}
|
|
@@ -87,6 +87,7 @@
|
|
|
87
87
|
*/
|
|
88
88
|
import type { Cart, CartLineInput, CartLineUpdateInput, CartBuyerIdentityInput, CartAddressInput, CartAttributeInput, CartCompleteInput, CartSelectShippingMethodInput, CartSelectPaymentMethodInput, CartClearPaymentSelectionInput, CartApplyGiftCardInput, CartRemoveGiftCardInput, CartUpdateGiftCardRecipientInput, PaymentCreateInput, PaymentSession } from '../../core/cart/types';
|
|
89
89
|
import type { CartMutationOutcome, CartCompleteOutcome } from '../../core/cart/cart-client';
|
|
90
|
+
import type { DebugEvent } from '../../core/client/types';
|
|
90
91
|
import { type CartExpiredEvent } from '../../core/cart/cart-recovery';
|
|
91
92
|
/**
|
|
92
93
|
* Names of mutations exposed by the hook — narrows `status.operation` for
|
|
@@ -165,6 +166,12 @@ export interface UseCartManagerOptions extends CartManagerLifecycleCallbacks {
|
|
|
165
166
|
* customer service "view this cart", multi-cart B2B selectors.
|
|
166
167
|
*/
|
|
167
168
|
initialCartId?: string | null;
|
|
169
|
+
/**
|
|
170
|
+
* Optional debug sink — emits a `phase: 'cookie'` {@link DebugEvent} whenever the `cart-id`
|
|
171
|
+
* cookie is set or cleared (including the `clear()` that `complete()` performs after checkout).
|
|
172
|
+
* Wire it to the same transport the GraphQL client uses for a single shared debug timeline.
|
|
173
|
+
*/
|
|
174
|
+
cookieDebug?: (event: DebugEvent) => void;
|
|
168
175
|
}
|
|
169
176
|
export interface UseCartManagerResult {
|
|
170
177
|
getCart: () => Promise<Cart | null>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-cart-manager.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/use-cart-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsFG;AAMH,OAAO,KAAK,EACV,IAAI,EACJ,aAAa,EACb,mBAAmB,EACnB,sBAAsB,EACtB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,6BAA6B,EAC7B,4BAA4B,EAC5B,8BAA8B,EAC9B,sBAAsB,EACtB,uBAAuB,EACvB,gCAAgC,EAChC,kBAAkB,EAClB,cAAc,EACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAC5F,OAAO,EAKL,KAAK,gBAAgB,EAEtB,MAAM,+BAA+B,CAAC;AAGvC;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAC5B,SAAS,GACT,YAAY,GACZ,YAAY,GACZ,qBAAqB,GACrB,oBAAoB,GACpB,mBAAmB,GACnB,qBAAqB,GACrB,YAAY,GACZ,kBAAkB,GAClB,sBAAsB,GACtB,qBAAqB,GACrB,uBAAuB,GACvB,eAAe,GACf,gBAAgB,GAChB,yBAAyB,GACzB,UAAU,GACV,eAAe,CAAC;AAEpB;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,oBAAoB,CAAA;CAAE,GACpD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,oBAAoB,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAChE;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,oBAAoB,CAAA;CAAE,CAAC;AAEzD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,6BAA6B;IAC5C,kEAAkE;IAClE,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC5D,sDAAsD;IACtD,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC9D;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,oBAAoB,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC3E;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAsB,SAAQ,6BAA6B;IAC1E;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"use-cart-manager.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/use-cart-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsFG;AAMH,OAAO,KAAK,EACV,IAAI,EACJ,aAAa,EACb,mBAAmB,EACnB,sBAAsB,EACtB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,6BAA6B,EAC7B,4BAA4B,EAC5B,8BAA8B,EAC9B,sBAAsB,EACtB,uBAAuB,EACvB,gCAAgC,EAChC,kBAAkB,EAClB,cAAc,EACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAC5F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAKL,KAAK,gBAAgB,EAEtB,MAAM,+BAA+B,CAAC;AAGvC;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAC5B,SAAS,GACT,YAAY,GACZ,YAAY,GACZ,qBAAqB,GACrB,oBAAoB,GACpB,mBAAmB,GACnB,qBAAqB,GACrB,YAAY,GACZ,kBAAkB,GAClB,sBAAsB,GACtB,qBAAqB,GACrB,uBAAuB,GACvB,eAAe,GACf,gBAAgB,GAChB,yBAAyB,GACzB,UAAU,GACV,eAAe,CAAC;AAEpB;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,oBAAoB,CAAA;CAAE,GACpD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,oBAAoB,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAChE;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,oBAAoB,CAAA;CAAE,CAAC;AAEzD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,6BAA6B;IAC5C,kEAAkE;IAClE,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC5D,sDAAsD;IACtD,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC9D;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,oBAAoB,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC3E;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAsB,SAAQ,6BAA6B;IAC1E;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CAC3C;AAED,MAAM,WAAW,oBAAoB;IAEnC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IACpC,SAAS,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAG/B,OAAO,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAClE,mBAAmB,EAAE,CAAC,aAAa,EAAE,sBAAsB,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC7F,kBAAkB,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAChF,mBAAmB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACvE,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC3D,gBAAgB,EAAE,CAAC,UAAU,EAAE,kBAAkB,EAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAGrF,UAAU,EAAE,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC3E,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAChE,iBAAiB,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC/E,oBAAoB,EAAE,CACpB,KAAK,EAAE,IAAI,CAAC,6BAA6B,EAAE,QAAQ,CAAC,KACjD,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAClC,mBAAmB,EAAE,CACnB,KAAK,EAAE,IAAI,CAAC,4BAA4B,EAAE,QAAQ,CAAC,KAChD,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAClC,qBAAqB,EAAE,CACrB,KAAK,CAAC,EAAE,IAAI,CAAC,8BAA8B,EAAE,QAAQ,CAAC,KACnD,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAClC,aAAa,EAAE,CACb,KAAK,EAAE,IAAI,CAAC,sBAAsB,EAAE,QAAQ,CAAC,KAC1C,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAClC,cAAc,EAAE,CACd,KAAK,EAAE,IAAI,CAAC,uBAAuB,EAAE,QAAQ,CAAC,KAC3C,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAClC,uBAAuB,EAAE,CACvB,KAAK,EAAE,IAAI,CAAC,gCAAgC,EAAE,QAAQ,CAAC,KACpD,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAElC;;;;;;OAMG;IACH,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAEtF;;;;;OAKG;IACH,aAAa,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAGtE,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,SAAS,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;IAGvE,MAAM,EAAE,iBAAiB,CAAC;IAG1B,6CAA6C;IAC7C,SAAS,EAAE,OAAO,CAAC;IACnB,kEAAkE;IAClE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AA2BD,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,oBAAoB,CAoapF"}
|
|
@@ -117,8 +117,11 @@ function isDedicatedChannelError(err) {
|
|
|
117
117
|
export function useCartManager(options) {
|
|
118
118
|
const { cartClient } = useStorefrontClientContext();
|
|
119
119
|
const [status, setStatus] = useState({ type: 'idle' });
|
|
120
|
-
// Cookie store is stateless — keep one instance per hook mount.
|
|
121
|
-
|
|
120
|
+
// Cookie store is stateless — keep one instance per hook mount. A stable ref-backed wrapper lets
|
|
121
|
+
// the optional `cookieDebug` change without rebuilding the store (and therefore the runner).
|
|
122
|
+
const cookieDebugRef = useRef(options?.cookieDebug);
|
|
123
|
+
cookieDebugRef.current = options?.cookieDebug;
|
|
124
|
+
const cookieStore = useMemo(() => createBrowserCartCookieStore({ onDebug: (event) => cookieDebugRef.current?.(event) }), []);
|
|
122
125
|
// Latest-callback ref: the mutation wrapper reads `lifecycleRef.current` so it
|
|
123
126
|
// always fires the current callbacks while keeping its own deps array empty
|
|
124
127
|
// (a stable `wrapMutation` avoids rebuilding every mutation on each render).
|
package/dist/react/index.d.ts
CHANGED
|
@@ -36,7 +36,7 @@ export type { LanguageStore } from './stores/language.store';
|
|
|
36
36
|
export type { ShopConfig } from './types/shop-config';
|
|
37
37
|
export { selectCurrency, selectBaseCurrency, selectSupportedCurrencies, selectIsLoaded } from './stores/currency.store';
|
|
38
38
|
export { selectLanguage, selectDefaultLanguage, selectSupportedLanguages, selectLanguageIsLoaded } from './stores/language.store';
|
|
39
|
-
export { getCookie, setCookie, deleteCookie,
|
|
39
|
+
export { getCookie, setCookie, deleteCookie, createBrowserCartCookieStore, } from './cookies';
|
|
40
40
|
export { useBotProtection } from './hooks/use-bot-protection';
|
|
41
41
|
export { useHydrated } from './hooks/use-hydrated';
|
|
42
42
|
export { useDebouncedValue } from './hooks/use-debounced-value';
|
|
@@ -1 +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;AAC7F,OAAO,EAAE,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAC7F,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,KAAK,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AAG9H,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC9H,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxF,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC5F,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,KAAK,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AACrH,OAAO,EAAE,iBAAiB,EAAE,KAAK,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAC/F,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,YAAY,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpH,OAAO,EAAE,cAAc,EAAE,KAAK,oBAAoB,EAAE,KAAK,iBAAiB,EAAE,KAAK,oBAAoB,EAAE,KAAK,qBAAqB,EAAE,KAAK,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AACxM,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC9G,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;AAC/E,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;AAC/E,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAGtD,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACxH,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"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"}
|
package/dist/react/index.js
CHANGED
|
@@ -35,8 +35,9 @@ export { useLanguageStore, useLanguageStoreApi } from './stores/store-context';
|
|
|
35
35
|
// Selectors
|
|
36
36
|
export { selectCurrency, selectBaseCurrency, selectSupportedCurrencies, selectIsLoaded } from './stores/currency.store';
|
|
37
37
|
export { selectLanguage, selectDefaultLanguage, selectSupportedLanguages, selectLanguageIsLoaded } from './stores/language.store';
|
|
38
|
-
// Cookie utilities
|
|
39
|
-
|
|
38
|
+
// Cookie utilities (client-side). Server-side readers (readCartIdCookie,
|
|
39
|
+
// readCurrencyCookie) live in `@doswiftly/storefront-sdk/react/server`.
|
|
40
|
+
export { getCookie, setCookie, deleteCookie, createBrowserCartCookieStore, } from './cookies';
|
|
40
41
|
// Bot protection
|
|
41
42
|
export { useBotProtection } from './hooks/use-bot-protection';
|
|
42
43
|
// Generic hooks
|
|
@@ -29,19 +29,26 @@
|
|
|
29
29
|
*/
|
|
30
30
|
import { type ReactNode } from 'react';
|
|
31
31
|
import { type CartManagerLifecycleCallbacks, type UseCartManagerResult } from '../hooks/use-cart-manager';
|
|
32
|
+
import type { DebugEvent } from '../../core/client/types';
|
|
32
33
|
export interface CartManagerProviderProps extends CartManagerLifecycleCallbacks {
|
|
33
34
|
/**
|
|
34
35
|
* Server-known cart-id seed forwarded to `useCartManager`. Used only when the
|
|
35
36
|
* `cart-id` cookie is empty on mount — the cookie always wins when present.
|
|
36
37
|
*/
|
|
37
38
|
initialCartId?: string | null;
|
|
39
|
+
/**
|
|
40
|
+
* Optional debug sink forwarded to `useCartManager` — emits a `phase: 'cookie'` {@link DebugEvent}
|
|
41
|
+
* on every `cart-id` set/clear (including the `complete()` clear). Wire it to the same transport
|
|
42
|
+
* the GraphQL client uses for one shared debug timeline.
|
|
43
|
+
*/
|
|
44
|
+
cookieDebug?: (event: DebugEvent) => void;
|
|
38
45
|
children: ReactNode;
|
|
39
46
|
}
|
|
40
47
|
/**
|
|
41
48
|
* Creates one `useCartManager` instance and exposes it to descendants via
|
|
42
49
|
* Context. Lifecycle callbacks are forwarded to the underlying hook.
|
|
43
50
|
*/
|
|
44
|
-
export declare function CartManagerProvider({ initialCartId, onMutationStart, onMutationSuccess, onMutationError, children, }: CartManagerProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
51
|
+
export declare function CartManagerProvider({ initialCartId, cookieDebug, onMutationStart, onMutationSuccess, onMutationError, children, }: CartManagerProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
45
52
|
/**
|
|
46
53
|
* Read the shared cart manager provided by the nearest `<CartManagerProvider>`.
|
|
47
54
|
* Throws when called outside a provider.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cart-manager-provider.d.ts","sourceRoot":"","sources":["../../../src/react/providers/cart-manager-provider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,EAEL,KAAK,6BAA6B,EAClC,KAAK,oBAAoB,EAC1B,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"cart-manager-provider.d.ts","sourceRoot":"","sources":["../../../src/react/providers/cart-manager-provider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,EAEL,KAAK,6BAA6B,EAClC,KAAK,oBAAoB,EAC1B,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAK1D,MAAM,WAAW,wBAAyB,SAAQ,6BAA6B;IAC7E;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1C,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,aAAa,EACb,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,QAAQ,GACT,EAAE,wBAAwB,2CAU1B;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,oBAAoB,CAM5D"}
|
|
@@ -37,9 +37,10 @@ CartManagerContext.displayName = 'CartManagerContext';
|
|
|
37
37
|
* Creates one `useCartManager` instance and exposes it to descendants via
|
|
38
38
|
* Context. Lifecycle callbacks are forwarded to the underlying hook.
|
|
39
39
|
*/
|
|
40
|
-
export function CartManagerProvider({ initialCartId, onMutationStart, onMutationSuccess, onMutationError, children, }) {
|
|
40
|
+
export function CartManagerProvider({ initialCartId, cookieDebug, onMutationStart, onMutationSuccess, onMutationError, children, }) {
|
|
41
41
|
const manager = useCartManager({
|
|
42
42
|
initialCartId,
|
|
43
|
+
cookieDebug,
|
|
43
44
|
onMutationStart,
|
|
44
45
|
onMutationSuccess,
|
|
45
46
|
onMutationError,
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
*/
|
|
32
32
|
import { type StorefrontClientProviderProps } from './storefront-client-provider';
|
|
33
33
|
import { type CurrencyProviderProps } from './currency-provider';
|
|
34
|
+
import type { DebugEvent } from '../../core/client/types';
|
|
34
35
|
export interface StorefrontProviderProps extends StorefrontClientProviderProps {
|
|
35
36
|
shopData: CurrencyProviderProps['shopData'];
|
|
36
37
|
/**
|
|
@@ -91,6 +92,16 @@ export interface StorefrontProviderProps extends StorefrontClientProviderProps {
|
|
|
91
92
|
* scheduler arm on the first render (cold start) without a whoami round-trip.
|
|
92
93
|
*/
|
|
93
94
|
initialExpiresAt?: string | null;
|
|
95
|
+
/**
|
|
96
|
+
* Optional debug sink for cookie events. When provided, the currency and language stores emit a
|
|
97
|
+
* `phase: 'cookie'` {@link DebugEvent} whenever their cookie is written. Wire it to the same
|
|
98
|
+
* transport the GraphQL client uses (one shared sessionId) so cookie writes appear on the same
|
|
99
|
+
* timeline as GraphQL operations. (Cart-id events are wired separately on the cart cookie store.)
|
|
100
|
+
*
|
|
101
|
+
* Must be referentially stable (e.g. from a memoized module singleton) — the stores are created
|
|
102
|
+
* once at provider mount, so a later `cookieDebug` swap is not observed.
|
|
103
|
+
*/
|
|
104
|
+
cookieDebug?: (event: DebugEvent) => void;
|
|
94
105
|
}
|
|
95
|
-
export declare function StorefrontProvider({ children, config, middleware, shopData, initialIsAuthenticated, initialAccessToken, initialExpiresAt, initialLanguage, autoRefresh, authBasePath, }: StorefrontProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
106
|
+
export declare function StorefrontProvider({ children, config, middleware, shopData, initialIsAuthenticated, initialAccessToken, initialExpiresAt, initialLanguage, autoRefresh, authBasePath, cookieDebug, }: StorefrontProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
96
107
|
//# sourceMappingURL=storefront-provider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storefront-provider.d.ts","sourceRoot":"","sources":["../../../src/react/providers/storefront-provider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AASH,OAAO,EAA4B,KAAK,6BAA6B,EAAE,MAAM,8BAA8B,CAAC;AAC5G,OAAO,EAAoB,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"storefront-provider.d.ts","sourceRoot":"","sources":["../../../src/react/providers/storefront-provider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AASH,OAAO,EAA4B,KAAK,6BAA6B,EAAE,MAAM,8BAA8B,CAAC;AAC5G,OAAO,EAAoB,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAQnF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D,MAAM,WAAW,uBAAwB,SAAQ,6BAA6B;IAC5E,QAAQ,EAAE,qBAAqB,CAAC,UAAU,CAAC,CAAC;IAC5C;;;;;;;;;;OAUG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC;;;;;;;;;;;;;;;;OAgBG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CAC3C;AAED,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,MAAM,EACN,UAAU,EACV,QAAQ,EACR,sBAAsB,EACtB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,YAAY,EACZ,WAAW,GACZ,EAAE,uBAAuB,2CAyCzB"}
|
|
@@ -45,10 +45,11 @@ import { BotProtectionWidget } from '../bot-protection/bot-protection-widget';
|
|
|
45
45
|
import { createSessionExpiredEmitter } from '../../core/auth/session-events';
|
|
46
46
|
import { SessionExpiredContext } from '../hooks/use-session-expired';
|
|
47
47
|
import { useSessionRefresh } from '../hooks/use-session-refresh';
|
|
48
|
-
export function StorefrontProvider({ children, config, middleware, shopData, initialIsAuthenticated, initialAccessToken, initialExpiresAt, initialLanguage, autoRefresh, authBasePath, }) {
|
|
48
|
+
export function StorefrontProvider({ children, config, middleware, shopData, initialIsAuthenticated, initialAccessToken, initialExpiresAt, initialLanguage, autoRefresh, authBasePath, cookieDebug, }) {
|
|
49
49
|
const authStoreRef = useRef(createAuthStore({ initialIsAuthenticated, initialAccessToken, initialExpiresAt }));
|
|
50
|
-
const
|
|
51
|
-
const
|
|
50
|
+
const cookieDebugOptions = cookieDebug ? { onDebug: cookieDebug } : undefined;
|
|
51
|
+
const currencyStoreRef = useRef(createCurrencyStore(cookieDebugOptions));
|
|
52
|
+
const languageStoreRef = useRef(createLanguageStore(initialLanguage, cookieDebugOptions));
|
|
52
53
|
const sessionExpiredRef = useRef(createSessionExpiredEmitter());
|
|
53
54
|
const botProtectionRef = useRef(shopData.botProtection ? createBotProtectionManager(shopData.botProtection) : null);
|
|
54
55
|
return (_jsx(AuthStoreContext.Provider, { value: authStoreRef.current, children: _jsx(CurrencyStoreContext.Provider, { value: currencyStoreRef.current, children: _jsx(LanguageStoreContext.Provider, { value: languageStoreRef.current, children: _jsx(StorefrontClientProvider, { config: config, middleware: middleware, botProtection: botProtectionRef.current, botProtectionOperations: shopData.botProtection?.protectedOperations, sessionExpiredEmitter: sessionExpiredRef.current, authBasePath: authBasePath, children: _jsx(BotProtectionContext.Provider, { value: { manager: botProtectionRef.current }, children: _jsx(CurrencyProvider, { shopData: shopData, children: _jsxs(LanguageProvider, { shopData: shopData, children: [_jsx(BotProtectionWidget, { manager: botProtectionRef.current }), _jsx(SessionRefreshRunner, { autoRefresh: autoRefresh, emitter: sessionExpiredRef.current }), _jsx(SessionExpiredContext.Provider, { value: sessionExpiredRef.current, children: children })] }) }) }) }) }) }) }));
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-first readers for the storefront's readable first-party cookies.
|
|
3
|
+
*
|
|
4
|
+
* `readCartIdCookie` / `readCurrencyCookie` return the `cart-id` /
|
|
5
|
+
* `preferred-currency` cookie value. They run server-first: in a Next.js Server
|
|
6
|
+
* Component they read the request cookies via `next/headers`; when that is
|
|
7
|
+
* unavailable (client bundle, build time, non-Next runtime) they fall back to
|
|
8
|
+
* `document.cookie`. This isomorphic behaviour is deliberate and safe here
|
|
9
|
+
* because both cookies are readable (NOT httpOnly) — unlike the auth token,
|
|
10
|
+
* which `getInitialAuth` reads server-only precisely because it is httpOnly.
|
|
11
|
+
*
|
|
12
|
+
* They live under `@doswiftly/storefront-sdk/react/server` so the `next/headers`
|
|
13
|
+
* dependency stays out of the client entry; the dynamic import keeps importing
|
|
14
|
+
* this module safe in runtimes without `next/headers`.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* // app/checkout/page.tsx (Server Component)
|
|
19
|
+
* import { readCartIdCookie } from '@doswiftly/storefront-sdk/react/server';
|
|
20
|
+
*
|
|
21
|
+
* const cartId = await readCartIdCookie();
|
|
22
|
+
* const cart = cartId ? await fetchCart(cartId) : null;
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
/** Read the first-party `cart-id` cookie (server-first, client fallback). */
|
|
26
|
+
export declare function readCartIdCookie(): Promise<string | null>;
|
|
27
|
+
/** Read the first-party `preferred-currency` cookie (server-first, client fallback). */
|
|
28
|
+
export declare function readCurrencyCookie(): Promise<string | null>;
|
|
29
|
+
//# sourceMappingURL=cookie-readers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cookie-readers.d.ts","sourceRoot":"","sources":["../../../src/react/server/cookie-readers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAuBH,6EAA6E;AAC7E,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAE/D;AAED,wFAAwF;AACxF,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAEjE"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-first readers for the storefront's readable first-party cookies.
|
|
3
|
+
*
|
|
4
|
+
* `readCartIdCookie` / `readCurrencyCookie` return the `cart-id` /
|
|
5
|
+
* `preferred-currency` cookie value. They run server-first: in a Next.js Server
|
|
6
|
+
* Component they read the request cookies via `next/headers`; when that is
|
|
7
|
+
* unavailable (client bundle, build time, non-Next runtime) they fall back to
|
|
8
|
+
* `document.cookie`. This isomorphic behaviour is deliberate and safe here
|
|
9
|
+
* because both cookies are readable (NOT httpOnly) — unlike the auth token,
|
|
10
|
+
* which `getInitialAuth` reads server-only precisely because it is httpOnly.
|
|
11
|
+
*
|
|
12
|
+
* They live under `@doswiftly/storefront-sdk/react/server` so the `next/headers`
|
|
13
|
+
* dependency stays out of the client entry; the dynamic import keeps importing
|
|
14
|
+
* this module safe in runtimes without `next/headers`.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* // app/checkout/page.tsx (Server Component)
|
|
19
|
+
* import { readCartIdCookie } from '@doswiftly/storefront-sdk/react/server';
|
|
20
|
+
*
|
|
21
|
+
* const cartId = await readCartIdCookie();
|
|
22
|
+
* const cart = cartId ? await fetchCart(cartId) : null;
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
import { CART_COOKIE_NAME } from '../../core/cart/cookie-config';
|
|
26
|
+
import { CURRENCY_COOKIE_NAME } from '../../core/currency/cookie-config';
|
|
27
|
+
import { getCookie } from '../cookies';
|
|
28
|
+
/**
|
|
29
|
+
* Read a cookie server-first: the request cookies via `next/headers` in a Server
|
|
30
|
+
* Component, falling back to `document.cookie` on the client / outside a request
|
|
31
|
+
* scope. Returns null when the cookie is absent on both sides.
|
|
32
|
+
*/
|
|
33
|
+
async function readCookieIsomorphic(name) {
|
|
34
|
+
try {
|
|
35
|
+
const { cookies } = await import('next/headers');
|
|
36
|
+
const store = await cookies();
|
|
37
|
+
return store.get(name)?.value ?? null;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// No Next.js server request scope (client bundle, build time, non-Next
|
|
41
|
+
// runtime) — fall back to the client reader (null on the server).
|
|
42
|
+
return getCookie(name);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** Read the first-party `cart-id` cookie (server-first, client fallback). */
|
|
46
|
+
export async function readCartIdCookie() {
|
|
47
|
+
return readCookieIsomorphic(CART_COOKIE_NAME);
|
|
48
|
+
}
|
|
49
|
+
/** Read the first-party `preferred-currency` cookie (server-first, client fallback). */
|
|
50
|
+
export async function readCurrencyCookie() {
|
|
51
|
+
return readCookieIsomorphic(CURRENCY_COOKIE_NAME);
|
|
52
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { getStorefrontClient, type ServerClientOptions } from './get-storefront-client';
|
|
2
2
|
export { createStorefrontAuthRoute, type StorefrontAuthRouteOptions, type StorefrontAuthRouteHandlers, } from './create-storefront-auth-route';
|
|
3
3
|
export { getInitialAuth, type InitialAuth } from './get-initial-auth';
|
|
4
|
+
export { readCartIdCookie, readCurrencyCookie } from './cookie-readers';
|
|
4
5
|
export { trustedForwardedHostValidator, originAllowlistValidator, type OriginValidator, type OriginValidatorContext, } from '../../core/auth/handlers';
|
|
5
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/react/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAGxF,OAAO,EACL,yBAAyB,EACzB,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,GACjC,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGtE,OAAO,EACL,6BAA6B,EAC7B,wBAAwB,EACxB,KAAK,eAAe,EACpB,KAAK,sBAAsB,GAC5B,MAAM,0BAA0B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/react/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAGxF,OAAO,EACL,yBAAyB,EACzB,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,GACjC,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGtE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAGxE,OAAO,EACL,6BAA6B,EAC7B,wBAAwB,EACxB,KAAK,eAAe,EACpB,KAAK,sBAAsB,GAC5B,MAAM,0BAA0B,CAAC"}
|
|
@@ -3,5 +3,7 @@ export { getStorefrontClient } from './get-storefront-client';
|
|
|
3
3
|
export { createStorefrontAuthRoute, } from './create-storefront-auth-route';
|
|
4
4
|
// Server-only cold-start auth seed from the first-party cookies.
|
|
5
5
|
export { getInitialAuth } from './get-initial-auth';
|
|
6
|
+
// Server-first readers for the readable first-party cookies (cart-id, currency).
|
|
7
|
+
export { readCartIdCookie, readCurrencyCookie } from './cookie-readers';
|
|
6
8
|
// Origin validators — wire CSRF defense-in-depth on the route handlers from a single import.
|
|
7
9
|
export { trustedForwardedHostValidator, originAllowlistValidator, } from '../../core/auth/handlers';
|
|
@@ -6,6 +6,11 @@
|
|
|
6
6
|
* through React Context — eliminates module duplication in Turbopack.
|
|
7
7
|
*/
|
|
8
8
|
import type { ShopConfig } from '../types/shop-config';
|
|
9
|
+
import type { DebugEvent } from '../../core/client/types';
|
|
10
|
+
export interface CreateCurrencyStoreOptions {
|
|
11
|
+
/** Optional debug sink — emits a `phase: 'cookie'` event whenever the currency cookie is written. */
|
|
12
|
+
onDebug?: (event: DebugEvent) => void;
|
|
13
|
+
}
|
|
9
14
|
/**
|
|
10
15
|
* @deprecated Use ShopConfig instead. Kept for backward compatibility of type exports.
|
|
11
16
|
*/
|
|
@@ -18,7 +23,7 @@ export interface CurrencyStore {
|
|
|
18
23
|
initialize: (shopData: ShopConfig) => void;
|
|
19
24
|
setCurrency: (currency: string) => void;
|
|
20
25
|
}
|
|
21
|
-
export declare const createCurrencyStore: () => import("zustand").StoreApi<CurrencyStore>;
|
|
26
|
+
export declare const createCurrencyStore: (options?: CreateCurrencyStoreOptions) => import("zustand").StoreApi<CurrencyStore>;
|
|
22
27
|
export declare const selectCurrency: (state: CurrencyStore) => string | null;
|
|
23
28
|
export declare const selectBaseCurrency: (state: CurrencyStore) => string | null;
|
|
24
29
|
export declare const selectSupportedCurrencies: (state: CurrencyStore) => string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"currency.store.d.ts","sourceRoot":"","sources":["../../../src/react/stores/currency.store.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"currency.store.d.ts","sourceRoot":"","sources":["../../../src/react/stores/currency.store.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAG1D,MAAM,WAAW,0BAA0B;IACzC,qGAAqG;IACrG,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CACvC;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC;AAE1C,MAAM,WAAW,aAAa;IAE5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;IAGlB,UAAU,EAAE,CAAC,QAAQ,EAAE,UAAU,KAAK,IAAI,CAAC;IAC3C,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED,eAAO,MAAM,mBAAmB,GAAI,UAAU,0BAA0B,8CA2DvE,CAAC;AAMF,eAAO,MAAM,cAAc,GAAI,OAAO,aAAa,kBAAmB,CAAC;AACvE,eAAO,MAAM,kBAAkB,GAAI,OAAO,aAAa,kBAAuB,CAAC;AAC/E,eAAO,MAAM,yBAAyB,GAAI,OAAO,aAAa,aAA8B,CAAC;AAC7F,eAAO,MAAM,cAAc,GAAI,OAAO,aAAa,YAAmB,CAAC"}
|
|
@@ -8,48 +8,56 @@
|
|
|
8
8
|
import { createStore } from 'zustand/vanilla';
|
|
9
9
|
import { CURRENCY_COOKIE_NAME, CURRENCY_COOKIE_MAX_AGE } from '../../core/currency/cookie-config';
|
|
10
10
|
import { getCookie, setCookie } from '../cookies';
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
currency
|
|
15
|
-
isLoaded: false,
|
|
16
|
-
initialize: (shopData) => {
|
|
17
|
-
// 1. Try saved currency from cookie (SSR-safe)
|
|
18
|
-
const saved = getCookie(CURRENCY_COOKIE_NAME);
|
|
19
|
-
// 2. Try to detect from browser locale
|
|
20
|
-
let detected;
|
|
21
|
-
if (shopData.localeToCurrencyMap && typeof navigator !== 'undefined') {
|
|
22
|
-
const browserLocale = navigator.language;
|
|
23
|
-
const match = shopData.localeToCurrencyMap.find((m) => m.locale === browserLocale);
|
|
24
|
-
detected = match?.currency;
|
|
25
|
-
}
|
|
26
|
-
// 3. Determine final currency (priority: saved > detected > base)
|
|
27
|
-
const finalCurrency = saved && shopData.supportedCurrencies.includes(saved)
|
|
28
|
-
? saved
|
|
29
|
-
: detected && shopData.supportedCurrencies.includes(detected)
|
|
30
|
-
? detected
|
|
31
|
-
: shopData.currencyCode;
|
|
32
|
-
set({
|
|
33
|
-
baseCurrency: shopData.currencyCode,
|
|
34
|
-
supportedCurrencies: shopData.supportedCurrencies,
|
|
35
|
-
currency: finalCurrency,
|
|
36
|
-
isLoaded: true,
|
|
37
|
-
});
|
|
38
|
-
// Ensure cookie is set if we determined a currency
|
|
39
|
-
if (finalCurrency && !saved) {
|
|
40
|
-
setCookie(CURRENCY_COOKIE_NAME, finalCurrency, { maxAge: CURRENCY_COOKIE_MAX_AGE });
|
|
41
|
-
}
|
|
42
|
-
},
|
|
43
|
-
setCurrency: (currency) => {
|
|
44
|
-
const { supportedCurrencies } = get();
|
|
45
|
-
if (!supportedCurrencies.includes(currency)) {
|
|
46
|
-
console.warn(`[CurrencyStore] Currency ${currency} not supported`);
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
set({ currency });
|
|
11
|
+
import { cookieDebugEvent } from '../../core/client/remote-debug-transport';
|
|
12
|
+
export const createCurrencyStore = (options) => {
|
|
13
|
+
const emit = options?.onDebug;
|
|
14
|
+
const persist = (currency) => {
|
|
50
15
|
setCookie(CURRENCY_COOKIE_NAME, currency, { maxAge: CURRENCY_COOKIE_MAX_AGE });
|
|
51
|
-
|
|
52
|
-
}
|
|
16
|
+
emit?.(cookieDebugEvent(CURRENCY_COOKIE_NAME, 'set', currency, CURRENCY_COOKIE_MAX_AGE));
|
|
17
|
+
};
|
|
18
|
+
return createStore()((set, get) => ({
|
|
19
|
+
baseCurrency: null,
|
|
20
|
+
supportedCurrencies: [],
|
|
21
|
+
currency: null,
|
|
22
|
+
isLoaded: false,
|
|
23
|
+
initialize: (shopData) => {
|
|
24
|
+
// 1. Try saved currency from cookie (SSR-safe)
|
|
25
|
+
const saved = getCookie(CURRENCY_COOKIE_NAME);
|
|
26
|
+
// 2. Try to detect from browser locale
|
|
27
|
+
let detected;
|
|
28
|
+
if (shopData.localeToCurrencyMap && typeof navigator !== 'undefined') {
|
|
29
|
+
const browserLocale = navigator.language;
|
|
30
|
+
const match = shopData.localeToCurrencyMap.find((m) => m.locale === browserLocale);
|
|
31
|
+
detected = match?.currency;
|
|
32
|
+
}
|
|
33
|
+
// 3. Determine final currency (priority: saved > detected > base)
|
|
34
|
+
const finalCurrency = saved && shopData.supportedCurrencies.includes(saved)
|
|
35
|
+
? saved
|
|
36
|
+
: detected && shopData.supportedCurrencies.includes(detected)
|
|
37
|
+
? detected
|
|
38
|
+
: shopData.currencyCode;
|
|
39
|
+
set({
|
|
40
|
+
baseCurrency: shopData.currencyCode,
|
|
41
|
+
supportedCurrencies: shopData.supportedCurrencies,
|
|
42
|
+
currency: finalCurrency,
|
|
43
|
+
isLoaded: true,
|
|
44
|
+
});
|
|
45
|
+
// Ensure cookie is set if we determined a currency
|
|
46
|
+
if (finalCurrency && !saved) {
|
|
47
|
+
persist(finalCurrency);
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
setCurrency: (currency) => {
|
|
51
|
+
const { supportedCurrencies } = get();
|
|
52
|
+
if (!supportedCurrencies.includes(currency)) {
|
|
53
|
+
console.warn(`[CurrencyStore] Currency ${currency} not supported`);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
set({ currency });
|
|
57
|
+
persist(currency);
|
|
58
|
+
},
|
|
59
|
+
}));
|
|
60
|
+
};
|
|
53
61
|
// ---------------------------------------------------------------------------
|
|
54
62
|
// Selectors (for use with useCurrencyStore(selector))
|
|
55
63
|
// ---------------------------------------------------------------------------
|
|
@@ -17,6 +17,11 @@
|
|
|
17
17
|
* - SDK language store (X-Lang header, framework-agnostic)
|
|
18
18
|
*/
|
|
19
19
|
import type { ShopConfig } from '../types/shop-config';
|
|
20
|
+
import type { DebugEvent } from '../../core/client/types';
|
|
21
|
+
export interface CreateLanguageStoreOptions {
|
|
22
|
+
/** Optional debug sink — emits a `phase: 'cookie'` event whenever the language cookie is written. */
|
|
23
|
+
onDebug?: (event: DebugEvent) => void;
|
|
24
|
+
}
|
|
20
25
|
export interface LanguageStore {
|
|
21
26
|
defaultLanguage: string | null;
|
|
22
27
|
supportedLanguages: string[];
|
|
@@ -25,7 +30,7 @@ export interface LanguageStore {
|
|
|
25
30
|
initialize: (shopData: ShopConfig) => void;
|
|
26
31
|
setLanguage: (language: string) => void;
|
|
27
32
|
}
|
|
28
|
-
export declare const createLanguageStore: (initialLanguage?: string | null) => import("zustand").StoreApi<LanguageStore>;
|
|
33
|
+
export declare const createLanguageStore: (initialLanguage?: string | null, options?: CreateLanguageStoreOptions) => import("zustand").StoreApi<LanguageStore>;
|
|
29
34
|
export declare const selectLanguage: (state: LanguageStore) => string | null;
|
|
30
35
|
export declare const selectDefaultLanguage: (state: LanguageStore) => string | null;
|
|
31
36
|
export declare const selectSupportedLanguages: (state: LanguageStore) => string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"language.store.d.ts","sourceRoot":"","sources":["../../../src/react/stores/language.store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"language.store.d.ts","sourceRoot":"","sources":["../../../src/react/stores/language.store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAG1D,MAAM,WAAW,0BAA0B;IACzC,qGAAqG;IACrG,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,aAAa;IAE5B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;IAGlB,UAAU,EAAE,CAAC,QAAQ,EAAE,UAAU,KAAK,IAAI,CAAC;IAC3C,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED,eAAO,MAAM,mBAAmB,GAC9B,kBAAkB,MAAM,GAAG,IAAI,EAC/B,UAAU,0BAA0B,8CAmDrC,CAAC;AAMF,eAAO,MAAM,cAAc,GAAI,OAAO,aAAa,kBAAmB,CAAC;AACvE,eAAO,MAAM,qBAAqB,GAAI,OAAO,aAAa,kBAA0B,CAAC;AACrF,eAAO,MAAM,wBAAwB,GAAI,OAAO,aAAa,aAA6B,CAAC;AAC3F,eAAO,MAAM,sBAAsB,GAAI,OAAO,aAAa,YAAmB,CAAC"}
|